diff options
Diffstat (limited to 'libc/tools/genseccomp.py')
| -rwxr-xr-x | libc/tools/genseccomp.py | 125 |
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() |
