# Copyright (c) 2012 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 csv
import logging
import os

from collections import namedtuple, defaultdict

from autotest_lib.client.bin import test
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
from autotest_lib.client.cros import asan


PS_FIELDS = (
    'pid',
    'ppid',
    'comm:32',
    'euser:%(usermax)d',
    'ruser:%(usermax)d',
    'egroup:%(groupmax)d',
    'rgroup:%(groupmax)d',
    'ipcns',
    'mntns',
    'netns',
    'pidns',
    'userns',
    'utsns',
    'args',
)
# These fields aren't available via ps, so we have to get them indirectly.
# Note: Case is significant as the fields match the /proc/PID/status file.
STATUS_FIELDS = (
    'CapInh',
    'CapPrm',
    'CapEff',
    'CapBnd',
    'CapAmb',
    'NoNewPrivs',
    'Seccomp',
)
# These fields are not available via ps or /proc/PID/status.
EXTRA_FIELDS = (
    'mountinfo',
)
PsOutput = namedtuple("PsOutput",
                      ' '.join([field.split(':')[0].lower() for field in
                                PS_FIELDS + STATUS_FIELDS + EXTRA_FIELDS]))

# Constants that match the values in /proc/PID/status Seccomp field.
# See `man 5 proc` for more details.
SECCOMP_MODE_DISABLED = '0'
SECCOMP_MODE_STRICT = '1'
SECCOMP_MODE_FILTER = '2'
# For human readable strings.
SECCOMP_MAP = {
    SECCOMP_MODE_DISABLED: 'disabled',
    SECCOMP_MODE_STRICT: 'strict',
    SECCOMP_MODE_FILTER: 'filter',
}

# These mounts only occur in test images. They should be limited to the init
# mount namespace, so no service should have them.
TEST_IMAGE_MOUNTS = (
    '/usr/local',
    '/var/db/pkg',
    '/var/lib/portage',
)


def get_properties(service, init_process):
    """Returns a dictionary of the properties of a service.

    @param service: the PsOutput of the service.
    @param init_process: the PsOutput of the init process.
    """

    properties = dict(service._asdict())
    properties['exe'] = service.comm
    properties['pidns'] = yes_or_no(service.pidns != init_process.pidns)
    properties['mntns'] = yes_or_no(service.mntns != init_process.mntns)
    properties['caps'] = yes_or_no(service.capeff != init_process.capeff)
    properties['nonewprivs'] = yes_or_no(service.nonewprivs == '1')
    properties['filter'] = yes_or_no(service.seccomp == SECCOMP_MODE_FILTER)
    return properties


def yes_or_no(value):
    """Returns 'Yes' or 'No' based on the truthiness of a value.

    @param value: boolean value.
    """

    return 'Yes' if value else 'No'


def get_mount_info(pid):
    """Returns the contents of /proc/PID/mountinfo.

    @param pid: The process id.
    """
    try:
        return tuple(utils.get_mount_info(process=pid))
    except IOError as e:
        # This process might have died already.
        logging.warning('Failed to read mountinfo for pid %s: %s', pid, e)
        return ()


def has_test_image_mounts(mountinfo):
    """Returns whether a process has test image mounts in its mount namespace.

    @param mountinfo: A list of utils.MountInfo.
    """
    return any(m.mount_point in TEST_IMAGE_MOUNTS for m in mountinfo)


class security_SandboxedServices(test.test):
    """Enforces sandboxing restrictions on the processes running
    on the system.
    """

    version = 1


    def get_running_processes(self):
        """Returns a list of running processes as PsOutput objects."""

        usermax = utils.system_output("cut -d: -f1 /etc/passwd | wc -L",
                                      ignore_status=True)
        groupmax = utils.system_output('cut -d: -f1 /etc/group | wc -L',
                                       ignore_status=True)
        # Even if the names are all short, make sure we have enough space
        # to hold numeric 32-bit ids too (can come up with userns).
        usermax = max(int(usermax), 10)
        groupmax = max(int(groupmax), 10)
        fields = {
            'usermax': usermax,
            'groupmax': groupmax,
        }
        ps_cmd = ('ps --no-headers -ww -eo ' +
                  (','.join(PS_FIELDS) % fields))
        ps_fields_len = len(PS_FIELDS)

        output = utils.system_output(ps_cmd)
        logging.debug('output of ps:\n%s', output)

        # Fill in fields that `ps` doesn't support but are in /proc/PID/status.
        # Example line output:
        # Pid:1 CapInh:0000000000000000 CapPrm:0000001fffffffff CapEff:0000001fffffffff CapBnd:0000001fffffffff Seccomp:0
        cmd = (
            "for f in /proc/[1-9]*/status ; do awk '$1 ~ \"^(Pid|%s):\" "
            "{printf \"%%s%%s \", $1, $NF; if ($1 == \"%s:\") printf \"\\n\"}'"
            " $f ; done"
        ) % ('|'.join(STATUS_FIELDS), STATUS_FIELDS[-1])
        # Processes might exit while awk is running, so ignore its exit status.
        status_output = utils.system_output(cmd, ignore_status=True)
        # Turn each line into a dict.
        # [
        #   {'pid': '1', 'CapInh': '0000000000000000', 'Seccomp': '0', ...},
        #   {'pid': '10', ...},
        #   ...,
        # ]
        status_list = list(dict(attr.split(':', 1) for attr in line.split())
                           for line in status_output.splitlines())
        # Create a dict mapping a pid to its extended status data.
        # {
        #   '1': {'pid': '1', 'CapInh': '0000000000000000', ...},
        #   '2': {'pid': '2', ...},
        #   ...,
        # }
        status_data = dict((x['Pid'], x) for x in status_list)
        logging.debug('output of awk:\n%s', status_output)

        # Now merge the two sets of process data.
        running_processes = []
        for line in output.splitlines():
            # crbug.com/422700: Filter out zombie processes.
            if '<defunct>' in line:
                continue

            fields = line.split(None, ps_fields_len - 1)
            pid = fields[0]
            # The process lists might not be exactly the same (since we gathered
            # data with multiple commands), and not all fields might exist (e.g.
            # older kernels might not have all the fields).
            pid_data = status_data.get(pid, {})
            status_fields = [pid_data.get(key) for key in STATUS_FIELDS]
            extra_fields = [get_mount_info(pid)]
            running_processes.append(
                PsOutput(*fields + status_fields + extra_fields))

        return running_processes


    def load_baseline(self):
        """The baseline file lists the services we know and
        whether (and how) they are sandboxed.
        """

        def load(path):
            """Load baseline from |path| and return its fields and dictionary.

            @param path: The baseline to load.
            """
            logging.info('Loading baseline %s', path)
            reader = csv.DictReader(open(path))
            return reader.fieldnames, dict((d['exe'], d) for d in reader
                                           if not d['exe'].startswith('#'))

        baseline_path = os.path.join(self.bindir, 'baseline')
        fields, ret = load(baseline_path)

        board = utils.get_current_board()
        baseline_path += '.' + board
        if os.path.exists(baseline_path):
            new_fields, new_entries = load(baseline_path)
            if new_fields != fields:
                raise error.TestError('header mismatch in %s' % baseline_path)
            ret.update(new_entries)

        return fields, ret


    def load_exclusions(self):
        """The exclusions file lists running programs
        that we don't care about (for now).
        """

        exclusions_path = os.path.join(self.bindir, 'exclude')
        return set(line.strip() for line in open(exclusions_path)
                   if not line.startswith('#'))


    def dump_services(self, fieldnames, running_services_properties):
        """Leaves a list of running services in the results dir
        so that we can update the baseline file if necessary.

        @param fieldnames: list of fields to be written.
        @param running_services_properties: list of services to be logged.
        """

        file_path = os.path.join(self.resultsdir, 'running_services')
        with open(file_path, 'w') as output_file:
            writer = csv.DictWriter(output_file, fieldnames=fieldnames,
                                    extrasaction='ignore')
            writer.writeheader()
            for service_properties in running_services_properties:
                writer.writerow(service_properties)


    def run_once(self):
        """Inspects the process list, looking for root and sandboxed processes
        (with some exclusions). If we have a baseline entry for a given process,
        confirms it's an exact match. Warns if we see root or sandboxed
        processes that we have no baseline for, and warns if we have
        baselines for processes not seen running.
        """

        fieldnames, baseline = self.load_baseline()
        exclusions = self.load_exclusions()
        running_processes = self.get_running_processes()
        is_asan = asan.running_on_asan()
        if is_asan:
            logging.info('ASAN image detected -> skipping seccomp checks')

        kthreadd_pid = -1

        init_process = None
        running_services = {}

        # Filter running processes list.
        for process in running_processes:
            exe = process.comm

            if exe == "kthreadd":
                kthreadd_pid = process.pid
                continue
            elif process.pid == "1":
                init_process = process
                continue

            # Don't worry about kernel threads.
            if process.ppid == kthreadd_pid:
                continue

            if exe in exclusions:
                continue

            running_services[exe] = process

        if not init_process:
            raise error.TestFail("Cannot find init process")

        # Find differences between running services and baseline.
        services_set = set(running_services.keys())
        baseline_set = set(baseline.keys())

        new_services = services_set.difference(baseline_set)
        stale_baselines = defaultdict(list)

        for exe in baseline_set.difference(services_set):
            stale_baselines[exe].append('unused')

        # Check baseline.
        sandbox_delta = defaultdict(list)
        for exe in services_set.intersection(baseline_set):
            process = running_services[exe]
            stale_flags = []
            errors = []

            # If the process is not running as the correct user.
            if process.euser != baseline[exe]["euser"]:
                errors.append('bad user: wanted "%s" but got "%s"' %
                              (baseline[exe]['euser'], process.euser))

            # If the process is not running as the correct group.
            if process.egroup != baseline[exe]['egroup']:
                errors.append('bad group: wanted "%s" but got "%s"' %
                              baseline[exe]['egroup'], process.egroup)

            # Check the various sandbox settings.
            if process.pidns == init_process.pidns:
                if baseline[exe]['pidns'] == 'Yes':
                    errors.append('missing pid ns usage')
            elif baseline[exe]['pidns'] != 'Yes':
                stale_flags.append('pidns')

            if process.mntns == init_process.mntns:
                if baseline[exe]['mntns'] == 'Yes':
                    errors.append('missing mount ns usage')
            elif has_test_image_mounts(process.mountinfo):
                if baseline[exe]['mntns'] == 'Yes':
                    errors.append('did not call pivot_root(2)')
            elif baseline[exe]['mntns'] != 'Yes':
                stale_flags.append('mntns')

            if process.capeff == init_process.capeff:
                if baseline[exe]['caps'] == 'Yes':
                    errors.append('missing caps usage')
            elif baseline[exe]['caps'] != 'Yes':
                stale_flags.append('caps')

            if process.nonewprivs != '1':
                if baseline[exe]['nonewprivs'] == 'Yes':
                    errors.append('missing NoNewPrivs')
            elif baseline[exe]['nonewprivs'] != 'Yes':
                stale_flags.append('nonewprivs')

            if not is_asan:
                # Since Minijail disables seccomp at runtime when ASAN is
                # active, we can't enforce it on ASAN bots.  Just ignore
                # the test entirely.  (Comment applies to "is_asan" above.)
                if process.seccomp != SECCOMP_MODE_FILTER:
                    if baseline[exe]['filter'] == 'Yes':
                        errors.append(
                            'missing seccomp usage: '
                            'wanted %s (%s) but got %s (%s)' %
                            (SECCOMP_MODE_FILTER,
                             SECCOMP_MAP[SECCOMP_MODE_FILTER], process.seccomp,
                             SECCOMP_MAP.get(process.seccomp, '???')))
                elif baseline[exe]['filter'] != 'Yes':
                    stale_flags.append('filter')

            if stale_flags:
                stale_baselines[exe].append('potentially missing flags: %s' %
                                            ','.join(stale_flags))
            if errors:
                sandbox_delta[exe].extend(errors)

        # Save current run to results dir.
        running_services_properties = [get_properties(s, init_process)
                                       for s in running_services.values()]
        self.dump_services(fieldnames, running_services_properties)

        if len(stale_baselines) > 0:
            logging.warn('Stale baselines: %r', stale_baselines)

        if len(new_services) > 0:
            logging.warn('New services: %r', new_services)

            # We won't complain about new non-root services (on the assumption
            # that they've already somewhat sandboxed things), but we'll fail
            # with new root services (on the assumption they haven't done any
            # sandboxing work).  If they really need to run as root, they can
            # update the baseline to whitelist it.
            for exe in new_services:
                if running_services[exe].euser == 'root':
                    sandbox_delta[exe].append('missing euser')

        if len(sandbox_delta) > 0:
            for delta_entry in sandbox_delta:
                logging.error('Failed sandboxing: %s', delta_entry)
            raise error.TestFail('One or more processes failed sandboxing: %r' %
                                 sandbox_delta)
