diff options
author | Luis Hector Chavez <lhchavez@google.com> | 2019-03-27 15:50:27 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2019-03-27 15:50:27 -0700 |
commit | 02556c5c9e51cf8208bdc5ffb4fde4ae01667ba8 (patch) | |
tree | 664fbe1c772a3582d94322dc959ee98d03f0fbe4 | |
parent | 0cdc83b4885e39202e180fa33e93a919b116093c (diff) | |
parent | 5d8bf57c9daee30c55af4dbe5dfd737113d1ed15 (diff) | |
download | minijail-02556c5c9e51cf8208bdc5ffb4fde4ae01667ba8.tar.gz |
tools/compile_seccomp_policy: Allow permissive default actions am: 891d355207 am: 59c8ecb17e
am: 5d8bf57c9d
Change-Id: I6386a2c21864b28426136451fc9bb61611157503
-rwxr-xr-x | tools/compile_seccomp_policy.py | 23 | ||||
-rw-r--r-- | tools/compiler.py | 20 | ||||
-rw-r--r-- | tools/parser.py | 19 |
3 files changed, 44 insertions, 18 deletions
diff --git a/tools/compile_seccomp_policy.py b/tools/compile_seccomp_policy.py index 62f8c1f..4278f90 100755 --- a/tools/compile_seccomp_policy.py +++ b/tools/compile_seccomp_policy.py @@ -28,6 +28,7 @@ import sys import arch import bpf import compiler +import parser def parse_args(argv): @@ -41,6 +42,14 @@ def parse_args(argv): parser.add_argument('--include-depth-limit', default=10) parser.add_argument('--arch-json', default='constants.json') 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) ' + 'since it is not valid to specify a permissive action in ' + '.policy files. This is useful for debugging.')) + parser.add_argument( '--use-kill-process', action='store_true', help=('Use SECCOMP_RET_KILL_PROCESS instead of ' @@ -55,19 +64,27 @@ def parse_args(argv): def main(argv): """Main entrypoint.""" opts = parse_args(argv) - policy_compiler = compiler.PolicyCompiler( - arch.Arch.load_from_json(opts.arch_json)) + parsed_arch = arch.Arch.load_from_json(opts.arch_json) + policy_compiler = compiler.PolicyCompiler(parsed_arch) if 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>') + parser_state.set_line(opts.default_action) + override_default_action = parser.PolicyParser( + parsed_arch, kill_action=bpf.KillProcess()).parse_action( + parser_state.tokenize()) with opts.output as outf: outf.write( policy_compiler.compile_file( opts.policy.name, optimization_strategy=opts.optimization_strategy, kill_action=kill_action, - include_depth_limit=opts.include_depth_limit).opcodes) + include_depth_limit=opts.include_depth_limit, + override_default_action=override_default_action).opcodes) return 0 diff --git a/tools/compiler.py b/tools/compiler.py index 9895df8..4e3881a 100644 --- a/tools/compiler.py +++ b/tools/compiler.py @@ -51,10 +51,9 @@ class SyscallPolicyEntry: def __repr__(self): return ('SyscallPolicyEntry<name: %s, number: %d, ' - 'frequency: %d, filter: %r>') % (self.name, self.number, - self.frequency, - self.filter.instructions - if self.filter else None) + 'frequency: %d, filter: %r>') % ( + self.name, self.number, self.frequency, + self.filter.instructions if self.filter else None) def simulate(self, arch, syscall_number, *args): """Simulate the policy with the given arguments.""" @@ -75,8 +74,8 @@ class SyscallPolicyRange: def __repr__(self): return 'SyscallPolicyRange<numbers: %r, frequency: %d, filter: %r>' % ( - self.numbers, self.frequency, self.filter.instructions - if self.filter else None) + self.numbers, self.frequency, + self.filter.instructions if self.filter else None) def simulate(self, arch, syscall_number, *args): """Simulate the policy with the given arguments.""" @@ -221,7 +220,8 @@ def _compile_entries_bst(entries, accept_action, reject_action): # Now recursively go through all possible partitions of the interval # currently being considered. - previous_accumulated = ranges[indices[0]].accumulated - ranges[indices[0]].frequency + previous_accumulated = ranges[indices[0]].accumulated - ranges[ + indices[0]].frequency bst_comparison_cost = ( ranges[indices[1] - 1].accumulated - previous_accumulated) for i, entry in enumerate(ranges[slice(*indices)]): @@ -265,12 +265,14 @@ class PolicyCompiler: *, optimization_strategy, kill_action, - include_depth_limit=10): + include_depth_limit=10, + override_default_action=None): """Return a compiled BPF program from the provided policy file.""" policy_parser = parser.PolicyParser( self._arch, kill_action=kill_action, - include_depth_limit=include_depth_limit) + include_depth_limit=include_depth_limit, + override_default_action=override_default_action) parsed_policy = policy_parser.parse_file(policy_filename) entries = [ self.compile_filter_statement( diff --git a/tools/parser.py b/tools/parser.py index 7179717..f3c5331 100644 --- a/tools/parser.py +++ b/tools/parser.py @@ -207,11 +207,17 @@ ParsedPolicy = collections.namedtuple('ParsedPolicy', class PolicyParser: """A parser for the Minijail seccomp policy file format.""" - def __init__(self, arch, *, kill_action, include_depth_limit=10): + def __init__(self, + arch, + *, + kill_action, + include_depth_limit=10, + override_default_action=None): self._parser_states = [ParserState("<memory>")] self._kill_action = kill_action self._include_depth_limit = include_depth_limit self._default_action = self._kill_action + self._override_default_action = override_default_action self._frequency_mapping = collections.defaultdict(int) self._arch = arch @@ -385,7 +391,7 @@ class PolicyParser: # | 'log' # | 'return' , single-constant # ; - def _parse_action(self, tokens): + def parse_action(self, tokens): if not tokens: self._parser_state.error('missing action') action_token = tokens.pop(0) @@ -425,12 +431,12 @@ class PolicyParser: argument_expression = self.parse_argument_expression(tokens) if tokens and tokens[0].type == 'SEMICOLON': tokens.pop(0) - action = self._parse_action(tokens) + action = self.parse_action(tokens) else: action = bpf.Allow() return Filter(argument_expression, action) else: - return Filter(None, self._parse_action(tokens)) + return Filter(None, self.parse_action(tokens)) # filter = '{' , single-filter , [ { ',' , single-filter } ] , '}' # | single-filter @@ -722,6 +728,7 @@ class PolicyParser: [])) syscall_filter_mapping[syscall] = filter_statements[-1] syscall_filter_mapping[syscall].filters.extend(filters) + default_action = self._override_default_action or self._default_action for filter_statement in filter_statements: unconditional_actions_suffix = list( itertools.dropwhile(lambda filt: filt.expression is not None, @@ -740,5 +747,5 @@ class PolicyParser: line=self._parser_states[-1].line) assert not unconditional_actions_suffix filter_statement.filters.append( - Filter(expression=None, action=self._default_action)) - return ParsedPolicy(self._default_action, filter_statements) + Filter(expression=None, action=default_action)) + return ParsedPolicy(default_action, filter_statements) |