diff options
author | Paul Moore <pmoore@redhat.com> | 2012-08-27 14:37:20 -0400 |
---|---|---|
committer | Paul Moore <pmoore@redhat.com> | 2012-11-12 15:49:07 -0500 |
commit | 46525415c603c8b7eef6a26eb017e2c3f61a8e2a (patch) | |
tree | 5b79112c3b56685d2c967722223c34dce2ef5c1c | |
parent | a8bba8ef5946a5f6f41fa82ddabf35e49e8128bb (diff) | |
download | libseccomp-46525415c603c8b7eef6a26eb017e2c3f61a8e2a.tar.gz |
arch: provide the basic infrastructure for non-native architecture support
Add the arch_syscall_translate() function which converts the syscall
table from the native architecture to the desired architecture.
Signed-off-by: Paul Moore <pmoore@redhat.com>
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/api.c | 8 | ||||
-rw-r--r-- | src/arch-i386.c | 7 | ||||
-rw-r--r-- | src/arch-i386.h | 1 | ||||
-rw-r--r-- | src/arch-x86_64.c | 33 | ||||
-rw-r--r-- | src/arch-x86_64.h | 1 | ||||
-rw-r--r-- | src/arch.c | 73 | ||||
-rw-r--r-- | src/arch.h | 1 |
8 files changed, 107 insertions, 19 deletions
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 @@ -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 <pmoore@redhat.com> + * Author: Paul Moore <pmoore@redhat.com> + */ + +/* + * 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)) @@ -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 @@ -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, |