[libseccomp-discuss] [PATCH 02/10] arch: provide the basic infrastructure for non-native architectu
High level interface to the Linux Kernel's seccomp filter
Brought to you by:
pcmoore
From: Paul M. <pm...@re...> - 2012-10-02 20:41:31
|
Add the arch_syscall_translate() function which converts the syscall table from the native architecture to the desired architecture. Signed-off-by: Paul Moore <pm...@re...> --- 0 files changed diff --git a/src/Makefile b/src/Makefile index f2386a0..394e21a 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,7 +39,7 @@ LIB_SHARED = libseccomp.so.$(VERSION_RELEASE) OBJS = \ api.o db.o arch.o \ arch-i386.o arch-i386-syscalls.o \ - arch-x86_64-syscalls.o \ + arch-x86_64.o arch-x86_64-syscalls.o \ hash.o \ gen_pfc.o gen_bpf.o diff --git a/src/api.c b/src/api.c index 7d6bf3a..3e7f8d7 100644 --- a/src/api.c +++ b/src/api.c @@ -160,6 +160,10 @@ int seccomp_syscall_priority(scmp_filter_ctx ctx, int syscall, uint8_t priority) return -EINVAL; filter = (struct db_filter *)ctx; + rc = arch_syscall_translate(filter->arch, &syscall); + if (rc < 0) + return rc; + /* if this is a pseudo syscall (syscall < 0) then we need to rewrite * the syscall for some arch specific reason */ if (syscall < 0) { @@ -209,6 +213,10 @@ static int _seccomp_rule_add(struct db_filter *filter, if (action == filter->attr.act_default) return -EPERM; + rc = arch_syscall_translate(filter->arch, &syscall); + if (rc < 0) + return rc; + /* collect the arguments for the filter rule */ chain_len_max = arch_arg_count_max(filter->arch); chain = malloc(sizeof(*chain) * chain_len_max); diff --git a/src/arch-i386.c b/src/arch-i386.c index 7695bfc..577d6c8 100644 --- a/src/arch-i386.c +++ b/src/arch-i386.c @@ -21,6 +21,7 @@ #include <stdlib.h> #include <errno.h> +#include <linux/audit.h> #include "arch.h" #include "arch-i386.h" @@ -29,6 +30,12 @@ #define __i386_NR_socketcall 102 #define __i386_NR_ipc 117 +const struct arch_def arch_def_i386 = { + .token = AUDIT_ARCH_I386, + .size = ARCH_SIZE_32, + .endian = ARCH_ENDIAN_LITTLE, +}; + /** * Rewrite a syscall value to match the architecture * @param arch the architecture definition diff --git a/src/arch-i386.h b/src/arch-i386.h index cea4e9a..bc24dbe 100644 --- a/src/arch-i386.h +++ b/src/arch-i386.h @@ -28,6 +28,7 @@ #define i386_arg_count_max 6 +extern const struct arch_def arch_def_i386; extern const struct arch_syscall_def i386_syscall_table[]; int i386_syscall_rewrite(const struct arch_def *arch, int *syscall); diff --git a/src/arch-x86_64.c b/src/arch-x86_64.c new file mode 100644 index 0000000..9f6af9c --- /dev/null +++ b/src/arch-x86_64.c @@ -0,0 +1,33 @@ +/** + * Enhanced Seccomp x86_64 Specific Code + * + * Copyright (c) 2012 Red Hat <pm...@re...> + * Author: Paul Moore <pm...@re...> + */ + +/* + * This library is free software; you can redistribute it and/or modify it + * under the terms of version 2.1 of the GNU Lesser General Public License as + * published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, see <http://www.gnu.org/licenses>. + */ + +#include <stdlib.h> +#include <errno.h> +#include <linux/audit.h> + +#include "arch.h" +#include "arch-x86_64.h" + +const struct arch_def arch_def_x86_64 = { + .token = AUDIT_ARCH_X86_64, + .size = ARCH_SIZE_64, + .endian = ARCH_ENDIAN_LITTLE, +}; diff --git a/src/arch-x86_64.h b/src/arch-x86_64.h index 3f13c17..73de6db 100644 --- a/src/arch-x86_64.h +++ b/src/arch-x86_64.h @@ -29,6 +29,7 @@ #define x86_64_arg_count_max 6 +extern const struct arch_def arch_def_x86_64; extern const struct arch_syscall_def x86_64_syscall_table[]; #define x86_64_arg_offset_lo(x) (arch_arg_offset(x)) diff --git a/src/arch.c b/src/arch.c index ddd6dce..8ab3c0a 100644 --- a/src/arch.c +++ b/src/arch.c @@ -59,6 +59,27 @@ const struct arch_def arch_def_native = { }; /** + * Lookup the syscall table for an architecture + * @param token the architecure token + * + * Return the architecture's syscall table, returns NULL on failure. + * + */ +const struct arch_syscall_def *_arch_def_lookup(uint32_t token) +{ + switch (token) { + case AUDIT_ARCH_I386: + return i386_syscall_table; + break; + case AUDIT_ARCH_X86_64: + return x86_64_syscall_table; + break; + } + + return NULL; +} + +/** * Determine the maximum number of syscall arguments * @param arch the architecture definition * @@ -133,16 +154,9 @@ int arch_syscall_resolve_name(const struct arch_def *arch, const char *name) unsigned int iter; const struct arch_syscall_def *table; - switch (arch->token) { - case AUDIT_ARCH_I386: - table = i386_syscall_table; - break; - case AUDIT_ARCH_X86_64: - table = x86_64_syscall_table; - break; - default: + table = _arch_def_lookup(arch->token); + if (table == NULL) return __NR_SCMP_ERROR; - } /* XXX - plenty of room for future improvement here */ for (iter = 0; table[iter].name != NULL; iter++) { @@ -168,16 +182,9 @@ const char *arch_syscall_resolve_num(const struct arch_def *arch, int num) unsigned int iter; const struct arch_syscall_def *table; - switch (arch->token) { - case AUDIT_ARCH_I386: - table = i386_syscall_table; - break; - case AUDIT_ARCH_X86_64: - table = x86_64_syscall_table; - break; - default: + table = _arch_def_lookup(arch->token); + if (table == NULL) return NULL; - } /* XXX - plenty of room for future improvement here */ for (iter = 0; table[iter].num != __NR_SCMP_ERROR; iter++) { @@ -189,6 +196,36 @@ const char *arch_syscall_resolve_num(const struct arch_def *arch, int num) } /** + * Translate the syscall number + * @param arch the architecture definition + * @param syscall the syscall number + * + * Translate the syscall number, in the context of the native architecure, to + * the provided architecure. Returns zero on success, negative values on + * failure. + * + */ +int arch_syscall_translate(const struct arch_def *arch, int *syscall) +{ + int sc_num; + const char *sc_name; + + if (arch->token != arch_def_native.token) { + sc_name = arch_syscall_resolve_num(&arch_def_native, *syscall); + if (sc_name == NULL) + return -EFAULT; + + sc_num = arch_syscall_resolve_name(arch, sc_name); + if (sc_num == __NR_SCMP_ERROR) + return -EFAULT; + + *syscall = sc_num; + } + + return 0; +} + +/** * Rewrite a syscall value to match the architecture * @param arch the architecture definition * @param syscall the syscall number diff --git a/src/arch.h b/src/arch.h index 31a965e..4e14ca6 100644 --- a/src/arch.h +++ b/src/arch.h @@ -89,6 +89,7 @@ int arch_arg_offset_hi(const struct arch_def *arch, unsigned int arg); int arch_syscall_resolve_name(const struct arch_def *arch, const char *name); const char *arch_syscall_resolve_num(const struct arch_def *arch, int num); +int arch_syscall_translate(const struct arch_def *arch, int *syscall); int arch_syscall_rewrite(const struct arch_def *arch, int *syscall); int arch_filter_rewrite(const struct arch_def *arch, |