# 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)
