summaryrefslogtreecommitdiff
path: root/libc/tools/genseccomp.py
diff options
context:
space:
mode:
Diffstat (limited to 'libc/tools/genseccomp.py')
-rwxr-xr-xlibc/tools/genseccomp.py125
1 files changed, 64 insertions, 61 deletions
diff --git a/libc/tools/genseccomp.py b/libc/tools/genseccomp.py
index f3a232e6e9..dad911331f 100755
--- a/libc/tools/genseccomp.py
+++ b/libc/tools/genseccomp.py
@@ -26,47 +26,18 @@ class SyscallRange(object):
self.names.append(name)
-def get_names(syscall_files, architecture, global_policy):
- syscall_lists = []
- for syscall_file in syscall_files:
- parser = SysCallsTxtParser()
- parser.parse_open_file(syscall_file)
- 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))
-
- if x in whitelist:
- 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 + global_whitelist
-
- # Select only elements matching required architecture
- syscalls = [x for x in syscalls if architecture in x and x[architecture]]
-
- # We only want the name
- names = [x["name"] for x in syscalls]
-
- # Check for duplicates
- dups = [name for name, count in collections.Counter(names).items() if count > 1]
+def load_syscall_names_from_file(file_path, architecture):
+ parser = SysCallsTxtParser()
+ parser.parse_open_file(open(file_path))
+ return set([x["name"] for x in parser.syscalls if x.get(architecture)])
- # x86 has duplicate socketcall entries, so hard code for this
- if architecture == "x86":
- dups.remove("socketcall")
- if len(dups) > 0:
- raise RuntimeError("Duplicate entries found - aborting " + str(dups))
+def merge_names(base_names, whitelist_names, blacklist_names):
+ if bool(blacklist_names - base_names):
+ raise RuntimeError("Blacklist item not in bionic - aborting " + str(
+ blacklist_name - base_names))
- # Remove remaining duplicates
- return list(set(names))
+ return (base_names - blacklist_names) | whitelist_names
def convert_names_to_NRs(names, header_dir, extra_switches):
@@ -175,8 +146,11 @@ def convert_ranges_to_bpf(ranges):
return bpf
-def convert_bpf_to_output(bpf, architecture, global_policy):
- suffix = "global_" if global_policy else ""
+def convert_bpf_to_output(bpf, architecture, name_modifier):
+ if name_modifier:
+ name_modifier = name_modifier + "_"
+ else:
+ name_modifier = ""
header = textwrap.dedent("""\
// Autogenerated file - edit at your peril!!
@@ -185,29 +159,51 @@ def convert_bpf_to_output(bpf, architecture, global_policy):
#include "seccomp_bpfs.h"
const sock_filter {architecture}_{suffix}filter[] = {{
- """).format(architecture=architecture,suffix=suffix)
+ """).format(architecture=architecture,suffix=name_modifier)
footer = textwrap.dedent("""\
}};
const size_t {architecture}_{suffix}filter_size = sizeof({architecture}_{suffix}filter) / sizeof(struct sock_filter);
- """).format(architecture=architecture,suffix=suffix)
+ """).format(architecture=architecture,suffix=name_modifier)
return header + "\n".join(bpf) + footer
-def construct_bpf(syscall_files, architecture, header_dir, extra_switches,
- global_policy):
- names = get_names(syscall_files, architecture, global_policy)
+def construct_bpf(names, architecture, header_dir, extra_switches,
+ name_modifier):
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, global_policy)
-
-
-ANDROID_SYSCALL_FILES = ["SYSCALLS.TXT",
- "SECCOMP_WHITELIST.TXT",
- "SECCOMP_BLACKLIST.TXT"]
+ return convert_bpf_to_output(bpf, architecture, name_modifier)
+
+
+# final syscalls = base - blacklists + whitelists
+ANDROID_SYSTEM_SYSCALL_FILES = {
+ "base": "SYSCALLS.TXT",
+ "whitelists": [
+ "SECCOMP_WHITELIST_COMMON.TXT",
+ "SECCOMP_WHITELIST_SYSTEM.TXT"],
+ "blacklists": ["SECCOMP_BLACKLIST_COMMON.TXT"]
+}
+
+ANDROID_APP_SYSCALL_FILES = {
+ "base": "SYSCALLS.TXT",
+ "whitelists": [
+ "SECCOMP_WHITELIST_COMMON.TXT",
+ "SECCOMP_WHITELIST_APP.TXT"],
+ "blacklists": ["SECCOMP_BLACKLIST_COMMON.TXT"]
+}
+
+ANDROID_GLOBAL_SYSCALL_FILES = {
+ "base": "SYSCALLS.TXT",
+ "whitelists": [
+ "SECCOMP_WHITELIST_COMMON.TXT",
+ "SECCOMP_WHITELIST_SYSTEM.TXT",
+ "SECCOMP_WHITELIST_APP.TXT",
+ "SECCOMP_WHITELIST_GLOBAL.TXT"],
+ "blacklists": ["SECCOMP_BLACKLIST_COMMON.TXT"]
+}
POLICY_CONFIGS = [("arm", "kernel/uapi/asm-arm", []),
@@ -223,18 +219,23 @@ def set_dir():
os.chdir(os.path.join(os.environ["ANDROID_BUILD_TOP"], "bionic/libc"))
-def gen_policy(global_policy):
- if global_policy:
- ANDROID_SYSCALL_FILES.append("SECCOMP_WHITELIST_GLOBAL.TXT")
-
+def gen_policy(syscall_files, name_modifier):
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, global_policy)
+ base_names = load_syscall_names_from_file(syscall_files["base"], arch)
+ whitelist_names = set()
+ for f in syscall_files["whitelists"]:
+ whitelist_names |= load_syscall_names_from_file(f, arch)
+ blacklist_names = set()
+ for f in syscall_files["blacklists"]:
+ blacklist_names |= load_syscall_names_from_file(f, arch)
+
+ names = merge_names(base_names, whitelist_names, blacklist_names)
+ output = construct_bpf(names, arch, header_path, switches, name_modifier)
# And output policy
existing = ""
- global_string = "_global" if global_policy else ""
- output_path = "seccomp/{}{}_policy.cpp".format(arch, global_string)
+ filename_modifier = "_" + name_modifier if name_modifier else ""
+ output_path = "seccomp/{}{}_policy.cpp".format(arch, filename_modifier)
if os.path.isfile(output_path):
existing = open(output_path).read()
if output == existing:
@@ -247,8 +248,10 @@ def gen_policy(global_policy):
def main():
set_dir()
- gen_policy(False)
- gen_policy(True)
+ gen_policy(ANDROID_SYSTEM_SYSCALL_FILES, 'system')
+ gen_policy(ANDROID_APP_SYSCALL_FILES, 'app')
+ gen_policy(ANDROID_GLOBAL_SYSCALL_FILES, 'global')
+
if __name__ == "__main__":
main()