blob: 1ea19bd1b3df7c0bbbfc11e0f01e497caee0746e [file] [log] [blame]
# 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
from autotest_lib.client.bin import test, utils
from autotest_lib.client.common_lib import error
import os.path
class security_ReservedPrivileges(test.test):
version = 1
def reserved_commands(self, command_list):
process_list = []
for line in command_list:
items = line.split()
# We don't care about defunct processes for purposes of this test,
# so skip to the next process if we encounter one.
if '<defunct>' in items:
continue
# There are n items in the list. The first is the command, all of
# the remaining are either the different users or groups. They
# must all match, if they don't we collect it.
matches = [i for i,owners in enumerate(items) if owners == items[1]]
# We do < because some processes have the same name as their owner.
# in that case the number of items will equal the number of matches
if (len(matches) < (len(items) - 1)):
process_list.append(items[0])
return set(process_list)
def load_baseline(self, bltype):
# Figure out path to baseline file, by looking up our own path
path = os.path.abspath(__file__)
path = os.path.join(os.path.dirname(path), 'baseline.%s' % bltype)
if (os.path.isfile(path) == False):
return set([])
baseline_file = open(path)
baseline_data = baseline_file.read()
baseline_set = set(baseline_data.splitlines())
baseline_file.close()
return baseline_set
def run_once(self, owner_type='user'):
"""
Do a find on the system for commands with reserved privileges and
compare against baseline. Fail if these do not match.
"""
# Find the max column width needed to represent user and group names
# in ps outoupt.
usermax = utils.system_output("cut -d: -f1 /etc/passwd | wc -L",
ignore_status=True)
usermax = max(int(usermax), 8)
groupmax = utils.system_output("cut -d: -f1 /etc/group | wc -L",
ignore_status=True)
groupmax = max(int(groupmax), 8)
if (owner_type == 'user'):
command = ('ps --no-headers -eo '\
'comm:16,euser:%d,ruser:%d,suser:%d,fuser:%d' %
(usermax, usermax, usermax, usermax))
else:
command = ('ps --no-headers -eo comm:16,rgroup:%d,group:%d' %
(groupmax, groupmax))
command_output = utils.system_output(command, ignore_status=True)
output_lines = command_output.splitlines()
dump_file = open(os.path.join(self.resultsdir, "ps_output"), 'w')
for line in output_lines:
dump_file.write(line.strip() + "\n")
dump_file.close()
observed_set = self.reserved_commands(output_lines)
baseline_set = self.load_baseline(owner_type)
# If something in the observed set is not
# covered by the baseline...
diff = observed_set.difference(baseline_set)
if len(diff) > 0:
for command in diff:
logging.error('Unexpected command: %s' % command)
# Or, things in baseline are missing from the system:
diff2 = baseline_set.difference(observed_set)
if len(diff2) > 0:
for command in diff2:
logging.error('Missing command: %s' % command)
if (len(diff) + len(diff2)) > 0:
raise error.TestFail('Baseline mismatch')