1#!/usr/bin/env python3 2# -*- coding: utf-8 -*- 3# 4# Copyright (C) 2018 The Android Open Source Project 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17"""Helper tool to compile a BPF program from a Minijail seccomp filter. 18 19This script will take a Minijail seccomp policy file and compile it into a 20BPF program suitable for use with Minijail in the current architecture. 21""" 22 23from __future__ import print_function 24 25import argparse 26import sys 27 28try: 29 import arch 30 import bpf 31 import compiler 32 import parser 33except ImportError: 34 from minijail import arch 35 from minijail import bpf 36 from minijail import compiler 37 from minijail import parser 38 39 40def parse_args(argv): 41 """Return the parsed CLI arguments for this tool.""" 42 parser = argparse.ArgumentParser(description=__doc__) 43 parser.add_argument( 44 '--optimization-strategy', 45 default=compiler.OptimizationStrategy.BST, 46 type=compiler.OptimizationStrategy, 47 choices=list(compiler.OptimizationStrategy)) 48 parser.add_argument('--include-depth-limit', default=10) 49 parser.add_argument('--arch-json', default='constants.json') 50 parser.add_argument( 51 '--default-action', 52 type=str, 53 help=('Use the specified default action, overriding any @default ' 54 'action found in the .policy files. ' 55 'This allows the use of permissive actions (allow, log, trace) ' 56 'since it is not valid to specify a permissive action in ' 57 '.policy files. This is useful for debugging.')) 58 parser.add_argument( 59 '--use-kill-process', 60 action='store_true', 61 help=('Use SECCOMP_RET_KILL_PROCESS instead of ' 62 'SECCOMP_RET_KILL_THREAD (requires Linux v4.14+).')) 63 parser.add_argument( 64 'policy', help='The seccomp policy.', type=argparse.FileType('r')) 65 parser.add_argument( 66 'output', help='The BPF program.', type=argparse.FileType('wb')) 67 return parser.parse_args(argv) 68 69 70def main(argv=None): 71 """Main entrypoint.""" 72 73 if argv is None: 74 argv = sys.argv[1:] 75 76 opts = parse_args(argv) 77 parsed_arch = arch.Arch.load_from_json(opts.arch_json) 78 policy_compiler = compiler.PolicyCompiler(parsed_arch) 79 if opts.use_kill_process: 80 kill_action = bpf.KillProcess() 81 else: 82 kill_action = bpf.KillThread() 83 override_default_action = None 84 if opts.default_action: 85 parser_state = parser.ParserState('<memory>') 86 override_default_action = parser.PolicyParser( 87 parsed_arch, kill_action=bpf.KillProcess()).parse_action( 88 next(parser_state.tokenize([opts.default_action]))) 89 with opts.output as outf: 90 outf.write( 91 policy_compiler.compile_file( 92 opts.policy.name, 93 optimization_strategy=opts.optimization_strategy, 94 kill_action=kill_action, 95 include_depth_limit=opts.include_depth_limit, 96 override_default_action=override_default_action).opcodes) 97 return 0 98 99 100if __name__ == '__main__': 101 sys.exit(main(sys.argv[1:])) 102