Create global seccomp policy.
Enabling seccomp across all processes, rather than just zygote, is
useful for auditing the syscall usage of AOSP. Create a global seccomp
policy that can optionally be enabled by init.
Bug: 37960259
Test: confirm global seccomp by removing finit_module from policy and
observing modprobe fail, confirm regular seccomp unchanged by
comparing length of installed bpf
Change-Id: Iac53a42fa26a80b05126f262dd9525f4f66df558
diff --git a/libc/tools/genseccomp.py b/libc/tools/genseccomp.py
index 79968ae..f3a232e 100755
--- a/libc/tools/genseccomp.py
+++ b/libc/tools/genseccomp.py
@@ -26,7 +26,7 @@
self.names.append(name)
-def get_names(syscall_files, architecture):
+def get_names(syscall_files, architecture, global_policy):
syscall_lists = []
for syscall_file in syscall_files:
parser = SysCallsTxtParser()
@@ -34,6 +34,11 @@
syscall_lists.append(parser.syscalls)
bionic, whitelist, blacklist = syscall_lists[0], syscall_lists[1], syscall_lists[2]
+ if global_policy:
+ global_whitelist = syscall_lists[-1]
+ else:
+ global_whitelist = []
+
for x in blacklist:
if not x in bionic:
raise RuntimeError("Blacklist item not in bionic - aborting " + str(x))
@@ -42,7 +47,7 @@
raise RuntimeError("Blacklist item in whitelist - aborting " + str(x))
bionic_minus_blacklist = [x for x in bionic if x not in blacklist]
- syscalls = bionic_minus_blacklist + whitelist
+ syscalls = bionic_minus_blacklist + whitelist + global_whitelist
# Select only elements matching required architecture
syscalls = [x for x in syscalls if architecture in x and x[architecture]]
@@ -170,7 +175,8 @@
return bpf
-def convert_bpf_to_output(bpf, architecture):
+def convert_bpf_to_output(bpf, architecture, global_policy):
+ suffix = "global_" if global_policy else ""
header = textwrap.dedent("""\
// Autogenerated file - edit at your peril!!
@@ -178,24 +184,25 @@
#include <errno.h>
#include "seccomp_bpfs.h"
- const sock_filter {architecture}_filter[] = {{
- """).format(architecture=architecture)
+ const sock_filter {architecture}_{suffix}filter[] = {{
+ """).format(architecture=architecture,suffix=suffix)
footer = textwrap.dedent("""\
}};
- const size_t {architecture}_filter_size = sizeof({architecture}_filter) / sizeof(struct sock_filter);
- """).format(architecture=architecture)
+ const size_t {architecture}_{suffix}filter_size = sizeof({architecture}_{suffix}filter) / sizeof(struct sock_filter);
+ """).format(architecture=architecture,suffix=suffix)
return header + "\n".join(bpf) + footer
-def construct_bpf(syscall_files, architecture, header_dir, extra_switches):
- names = get_names(syscall_files, architecture)
+def construct_bpf(syscall_files, architecture, header_dir, extra_switches,
+ global_policy):
+ names = get_names(syscall_files, architecture, global_policy)
syscalls = convert_names_to_NRs(names, header_dir, extra_switches)
ranges = convert_NRs_to_ranges(syscalls)
bpf = convert_ranges_to_bpf(ranges)
- return convert_bpf_to_output(bpf, architecture)
+ return convert_bpf_to_output(bpf, architecture, global_policy)
ANDROID_SYSCALL_FILES = ["SYSCALLS.TXT",
@@ -216,15 +223,18 @@
os.chdir(os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libc"))
-def main():
- set_dir()
+def gen_policy(global_policy):
+ if global_policy:
+ ANDROID_SYSCALL_FILES.append("SECCOMP_WHITELIST_GLOBAL.TXT")
+
for arch, header_path, switches in POLICY_CONFIGS:
files = [open(filename) for filename in ANDROID_SYSCALL_FILES]
- output = construct_bpf(files, arch, header_path, switches)
+ output = construct_bpf(files, arch, header_path, switches, global_policy)
# And output policy
existing = ""
- output_path = "seccomp/{}_policy.cpp".format(arch)
+ global_string = "_global" if global_policy else ""
+ output_path = "seccomp/{}{}_policy.cpp".format(arch, global_string)
if os.path.isfile(output_path):
existing = open(output_path).read()
if output == existing:
@@ -234,5 +244,11 @@
output_file.write(output)
print "Generated file " + output_path
+
+def main():
+ set_dir()
+ gen_policy(False)
+ gen_policy(True)
+
if __name__ == "__main__":
main()