aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuis Hector Chavez <lhchavez@google.com>2019-03-27 15:50:27 -0700
committerandroid-build-merger <android-build-merger@google.com>2019-03-27 15:50:27 -0700
commit02556c5c9e51cf8208bdc5ffb4fde4ae01667ba8 (patch)
tree664fbe1c772a3582d94322dc959ee98d03f0fbe4
parent0cdc83b4885e39202e180fa33e93a919b116093c (diff)
parent5d8bf57c9daee30c55af4dbe5dfd737113d1ed15 (diff)
downloadminijail-02556c5c9e51cf8208bdc5ffb4fde4ae01667ba8.tar.gz
tools/compile_seccomp_policy: Allow permissive default actions am: 891d355207 am: 59c8ecb17e
am: 5d8bf57c9d Change-Id: I6386a2c21864b28426136451fc9bb61611157503
-rwxr-xr-xtools/compile_seccomp_policy.py23
-rw-r--r--tools/compiler.py20
-rw-r--r--tools/parser.py19
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)