summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2012-08-27 14:37:20 -0400
committerPaul Moore <pmoore@redhat.com>2012-11-12 15:49:07 -0500
commit46525415c603c8b7eef6a26eb017e2c3f61a8e2a (patch)
tree5b79112c3b56685d2c967722223c34dce2ef5c1c
parenta8bba8ef5946a5f6f41fa82ddabf35e49e8128bb (diff)
downloadlibseccomp-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/Makefile2
-rw-r--r--src/api.c8
-rw-r--r--src/arch-i386.c7
-rw-r--r--src/arch-i386.h1
-rw-r--r--src/arch-x86_64.c33
-rw-r--r--src/arch-x86_64.h1
-rw-r--r--src/arch.c73
-rw-r--r--src/arch.h1
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
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 <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))
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,