#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Helper tool to compile a BPF program from a Minijail seccomp filter.

This script will take a Minijail seccomp policy file and compile it into a
BPF program suitable for use with Minijail in the current architecture.
"""

from __future__ import print_function

import argparse
import os
import sys

try:
    import arch
    import bpf
    import compiler
    import parser
except ImportError:
    from minijail import arch
    from minijail import bpf
    from minijail import compiler
    from minijail import parser

CONSTANTS_ERR_MSG = """Could not find 'constants.json' file.
See 'generate_constants_json.py -h'."""

HEADER_TEMPLATE = """/* DO NOT EDIT GENERATED FILE */
#ifndef MJ_SECCOMP_%(upper_name)s_H
#define MJ_SECCOMP_%(upper_name)s_H
#include <stdint.h>

static const unsigned char %(name)s_binary_seccomp_policy[] = {
    %(program)s
};

static const struct {
    uint16_t cnt;
    const void *bpf;
} %(name)s_seccomp_bpf_program = {
    .cnt = sizeof(%(name)s_binary_seccomp_policy) / 8,
    .bpf = %(name)s_binary_seccomp_policy,
};

#endif
"""

def parse_args(argv):
    """Return the parsed CLI arguments for this tool."""
    arg_parser = argparse.ArgumentParser(description=__doc__)
    arg_parser.add_argument('--optimization-strategy',
                            default=compiler.OptimizationStrategy.BST,
                            type=compiler.OptimizationStrategy,
                            choices=list(compiler.OptimizationStrategy))
    arg_parser.add_argument('--include-depth-limit', default=10)
    arg_parser.add_argument('--arch-json', default='constants.json')
    arg_parser.add_argument(
        '--denylist',
        action='store_true',
        help='Compile as a denylist policy rather than the default allowlist.')
    arg_parser.add_argument(
        '--default-action',
        type=str,
        help=('Use the specified default action, overriding any @default '
              'action found in the .policy files. '
              'This allows the use of permissive actions (allow, log, trace, '
              'user-notify) since it is not valid to specify a permissive '
              'action in .policy files. This is useful for debugging.'))
    arg_parser.add_argument(
        '--use-kill-process',
        action='store_true',
        help=('Use SECCOMP_RET_KILL_PROCESS instead of '
              'SECCOMP_RET_KILL_THREAD (requires Linux v4.14+).'))
    arg_parser.add_argument(
        '--use-ret-log',
        action='store_true',
        help=('Change all seccomp failures to return SECCOMP_RET_LOG instead '
              'of killing (requires SECCOMP_RET_LOG kernel support).'))
    arg_parser.add_argument(
        '--output-header-file',
        action='store_true',
        help=('Output the compiled bpf to a constant variable in a C header '
              'file instead of a binary file (output should not have a .h '
              'extension, one will be added).'))
    arg_parser.add_argument('policy',
                            help='The seccomp policy.',
                            type=argparse.FileType('r'))
    arg_parser.add_argument('output',
                            help='The BPF program.')
    return arg_parser.parse_args(argv), arg_parser


def main(argv=None):
    """Main entrypoint."""

    if argv is None:
        argv = sys.argv[1:]

    opts, arg_parser = parse_args(argv)
    if not os.path.exists(opts.arch_json):
        arg_parser.error(CONSTANTS_ERR_MSG)

    parsed_arch = arch.Arch.load_from_json(opts.arch_json)
    policy_compiler = compiler.PolicyCompiler(parsed_arch)
    # Set ret_log to true if the MINIJAIL_DEFAULT_RET_LOG environment variable
    # is present.
    if 'MINIJAIL_DEFAULT_RET_LOG' in os.environ:
        print("""
            \n**********************
Warning: MINJAIL_DEFAULT_RET_LOG is on, policy will not have any effect
**********************\n
""")
        opts.use_ret_log = True
    if opts.use_ret_log:
        kill_action = bpf.Log()
    elif opts.denylist:
        # Default action for a denylist policy is return EPERM
        kill_action = bpf.ReturnErrno(parsed_arch.constants['EPERM'])
    elif opts.use_kill_process:
        kill_action = bpf.KillProcess()
    else:
        kill_action = bpf.KillThread()
    override_default_action = None
    if opts.default_action:
        parser_state = parser.ParserState('<memory>')
        override_default_action = parser.PolicyParser(
            parsed_arch, kill_action=bpf.KillProcess()).parse_action(
                next(parser_state.tokenize([opts.default_action])))

    compiled_policy = policy_compiler.compile_file(
        opts.policy.name,
        optimization_strategy=opts.optimization_strategy,
        kill_action=kill_action,
        include_depth_limit=opts.include_depth_limit,
        override_default_action=override_default_action,
        denylist=opts.denylist,
        ret_log=opts.use_ret_log)
    # Outputs the bpf binary to a c header file instead of a binary file.
    if opts.output_header_file:
        output_file_base = opts.output
        with open(output_file_base + '.h', 'w') as output_file:
            program = ', '.join('%i' % x for x in compiled_policy.opcodes)
            output_file.write(HEADER_TEMPLATE % {
                'upper_name': output_file_base.upper(),
                'name': output_file_base,
                'program': program,
            })

    else:
        with open(opts.output, 'wb') as outf:
            outf.write(compiled_policy.opcodes)
    return 0


if __name__ == '__main__':
    sys.exit(main(sys.argv[1:]))
