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 19 This script will take a Minijail seccomp policy file and compile it into a 20 BPF program suitable for use with Minijail in the current architecture. 21 """ 22 23 from __future__ import print_function 24 25 import argparse 26 import sys 27 28 import arch 29 import bpf 30 import compiler 31 import parser 32 33 34 def parse_args(argv): 35 """Return the parsed CLI arguments for this tool.""" 36 parser = argparse.ArgumentParser(description=__doc__) 37 parser.add_argument( 38 '--optimization-strategy', 39 default=compiler.OptimizationStrategy.BST, 40 type=compiler.OptimizationStrategy, 41 choices=list(compiler.OptimizationStrategy)) 42 parser.add_argument('--include-depth-limit', default=10) 43 parser.add_argument('--arch-json', default='constants.json') 44 parser.add_argument( 45 '--default-action', 46 type=str, 47 help=('Use the specified default action, overriding any @default ' 48 'action found in the .policy files. ' 49 'This allows the use of permissive actions (allow, log, trace) ' 50 'since it is not valid to specify a permissive action in ' 51 '.policy files. This is useful for debugging.')) 52 parser.add_argument( 53 '--use-kill-process', 54 action='store_true', 55 help=('Use SECCOMP_RET_KILL_PROCESS instead of ' 56 'SECCOMP_RET_KILL_THREAD (requires Linux v4.14+).')) 57 parser.add_argument( 58 'policy', help='The seccomp policy.', type=argparse.FileType('r')) 59 parser.add_argument( 60 'output', help='The BPF program.', type=argparse.FileType('wb')) 61 return parser.parse_args(argv) 62 63 64 def main(argv): 65 """Main entrypoint.""" 66 opts = parse_args(argv) 67 parsed_arch = arch.Arch.load_from_json(opts.arch_json) 68 policy_compiler = compiler.PolicyCompiler(parsed_arch) 69 if opts.use_kill_process: 70 kill_action = bpf.KillProcess() 71 else: 72 kill_action = bpf.KillThread() 73 override_default_action = None 74 if opts.default_action: 75 parser_state = parser.ParserState('<memory>') 76 parser_state.set_line(opts.default_action) 77 override_default_action = parser.PolicyParser( 78 parsed_arch, kill_action=bpf.KillProcess()).parse_action( 79 parser_state.tokenize()) 80 with opts.output as outf: 81 outf.write( 82 policy_compiler.compile_file( 83 opts.policy.name, 84 optimization_strategy=opts.optimization_strategy, 85 kill_action=kill_action, 86 include_depth_limit=opts.include_depth_limit, 87 override_default_action=override_default_action).opcodes) 88 return 0 89 90 91 if __name__ == '__main__': 92 sys.exit(main(sys.argv[1:])) 93