diff options
author | Matt Delco <delco@chromium.org> | 2020-01-10 13:12:55 -0800 |
---|---|---|
committer | Matt Delco <delco@chromium.org> | 2020-01-14 13:46:09 -0800 |
commit | 21db125bec48c8a50fb965efbb92e873639e2a11 (patch) | |
tree | 659d62889498e29da014bbde43acea91250b8312 /tools | |
parent | c90ec15cabe51bcd37767e81d264a8ef7e322b9b (diff) | |
download | minijail-21db125bec48c8a50fb965efbb92e873639e2a11.tar.gz |
generate_seccomp_policy: generate frequency files
The current generate_seccomp_policy.py can only generate policy files that
are sorted by frequency. compile_seccomp_policy.py can accept a frequency file
(via a @frequency line in the policy file), but such a file isn't
created by generate_seccomp_policy.
This change adds a --frequency command-line option that can be used to
genreate a frequency file. For consistency I also added a --policy
option that can be used to specify the destination file for the policy
(normally the file is just sent to standard output and piped to a file).
If --frequency is used then the policy file will be generate syscall
rules in alphabetical order (vs. the frequency of the use). Alphabetic
order makes it easier to see what syscalls are used and facilitates
manual modification.
I was tempted to also output an additional header comment to the
generated policy file (for both modes) that warn the files were
generated by a script (and to either add new syscalls in use order or to
the frequency file, as relevant for the mode that was used to create the
script).
TBD is whether to automatically add a @frequency line to the policy
file. So far I haven't (the relative paths used to create the files
might have no relation to where the files are stored). I thought about
adding a command-line parameter to compile_seccomp_policy.py that permits the
frequency file to be specified (instead of or in addition to @frequency) but
I didn't see a clean & easy way to add this.
Bug: None
Test: make tests
Change-Id: I9e1a5128052a7ae529b2e149c2e7bd4a263907a8
Diffstat (limited to 'tools')
-rwxr-xr-x | tools/generate_seccomp_policy.py | 36 |
1 files changed, 26 insertions, 10 deletions
diff --git a/tools/generate_seccomp_policy.py b/tools/generate_seccomp_policy.py index 38685bb..fe122d5 100755 --- a/tools/generate_seccomp_policy.py +++ b/tools/generate_seccomp_policy.py @@ -62,6 +62,10 @@ ArgInspectionEntry = collections.namedtuple('ArgInspectionEntry', def parse_args(argv): """Returns the parsed CLI arguments for this tool.""" parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument('--frequency', nargs='?', type=argparse.FileType('w'), + help='frequency file') + parser.add_argument('--policy', nargs='?', type=argparse.FileType('w'), + default=sys.stdout, help='policy file') parser.add_argument('traces', nargs='+', help='The strace logs.') return parser.parse_args(argv) @@ -139,22 +143,34 @@ def main(argv): if basic_syscall not in syscalls: syscalls[basic_syscall] = 1 - # Sort the syscalls based on frequency. This way the calls that are used - # more often come first which in turn speeds up the filter slightly. - sorted_syscalls = list( - x[0] for x in sorted(syscalls.items(), key=lambda pair: pair[1], - reverse=True) - ) - - print(NOTICE) + # If a frequency file isn't used then sort the syscalls based on frequency + # to make the common case fast (by checking frequent calls earlier). + # Otherwise, sort alphabetically to make it easier for humans to see which + # calls are in use (and if necessary manually add a new syscall to the + # list). + if opts.frequency is None: + sorted_syscalls = list( + x[0] for x in sorted(syscalls.items(), key=lambda pair: pair[1], + reverse=True) + ) + else: + sorted_syscalls = list( + x[0] for x in sorted(syscalls.items(), key=lambda pair: pair[0]) + ) + + print(NOTICE, file=opts.policy) + if opts.frequency is not None: + print(NOTICE, file=opts.frequency) for syscall in sorted_syscalls: if syscall in arg_inspection: arg_filter = get_seccomp_bpf_filter(syscall, arg_inspection[syscall]) else: arg_filter = ALLOW - print('%s: %s' % (syscall, arg_filter)) - + print('%s: %s' % (syscall, arg_filter), file=opts.policy) + if opts.frequency is not None: + print('%s: %s' % (syscall, syscalls[syscall]), + file=opts.frequency) if __name__ == '__main__': sys.exit(main(sys.argv[1:])) |