blob: 567768402845ea0c8c2688fec7ab39632c0dea7d [file] [log] [blame] [edit]
# Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import logging
import os
import re
import sys
from xml.dom import minidom
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
class security_DbusOwners(test.test):
version = 1
_DBUS_CONFIG_DIR = '/etc/dbus-1/system.d/'
def load_baseline(self):
"""
Return a list of interface names we expect to be owned
by chronos.
"""
# Figure out path to baseline file, by looking up our own path
bpath = os.path.abspath(__file__)
bpath = os.path.join(os.path.dirname(bpath), 'baseline')
bfile = open(bpath)
baseline_data = bfile.read()
baseline_set = set(baseline_data.splitlines())
bfile.close()
return baseline_set
def fetch_owners(self):
"""
For every dbus interface XML, look for <policy user="chronos">
sections containing <allow own="InterfaceName">. Return the
list of interfaces owned by chronos
"""
chronos_owned = []
for root, dirs, files in os.walk(self._DBUS_CONFIG_DIR):
for filename in files:
# Skip cruft like dotfiles
if not re.search('^[^.].*\.conf$', filename):
logging.debug('Skipping %s' % filename)
continue
logging.debug('Parsing %s' % filename)
xmldoc = minidom.parse(os.path.join(root,filename))
policies = xmldoc.getElementsByTagName('policy')
for policy in policies:
if (policy.hasAttribute('user') and
policy.getAttribute('user') == 'chronos'):
allows = policy.getElementsByTagName('allow')
for allow in allows:
if allow.hasAttribute('own'):
chronos_owned.append(allow.getAttribute('own'))
return set(chronos_owned)
def run_once(self):
"""
Enumerate all the Dbus interfaces owned by chronos.
Fail if it does not match the expected set.
"""
observed_set = self.fetch_owners()
baseline_set = self.load_baseline()
# If something in the observed set is not
# covered by the baseline...
diff = observed_set.difference(baseline_set)
if len(diff) > 0:
for iface in diff:
logging.error('New chronos-owned interface %s' % iface)
# Or, things in baseline are missing from the system:
diff2 = baseline_set.difference(observed_set)
if len(diff2) > 0:
for iface in diff2:
logging.error('Missing chronos-owned interface %s' % iface)
if (len(diff) + len(diff2)) > 0:
raise error.TestFail('Baseline mismatch')