summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorJonathan Callen <abcd@gentoo.org>2012-07-24 22:45:22 -0400
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2013-01-19 12:03:06 -0500
commit843fc7f7f26a6507fe896a79ed1b474c35c4300f (patch)
treebd465b18a828d0abbc5505f2d63fc7ccb5817208 /src/core
parent25da63b9dac8f166ebf390ca92d1de18fbfc9d11 (diff)
execute: Fix seccomp support on x32
In the x32 ABI, syscall numbers start at 0x40000000. Mask that bit on x32 for lookups in the syscall_names array and syscall_filter and ensure that syscall.h is parsed correctly. [zj: added SYSCALL_TO_INDEX, INDEX_TO_SYSCALL macros.]
Diffstat (limited to 'src/core')
-rw-r--r--src/core/execute.c2
-rw-r--r--src/core/load-fragment.c2
-rw-r--r--src/core/syscall-list.c1
-rw-r--r--src/core/syscall-list.h14
4 files changed, 18 insertions, 1 deletions
diff --git a/src/core/execute.c b/src/core/execute.c
index 65a10af3b0..1413c9110e 100644
--- a/src/core/execute.c
+++ b/src/core/execute.c
@@ -957,7 +957,7 @@ static int apply_seccomp(uint32_t *syscall_filter) {
for (i = 0, n = 0; i < syscall_max(); i++)
if (syscall_filter[i >> 4] & (1 << (i & 31))) {
struct sock_filter item[] = {
- BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, i, 0, 1),
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, INDEX_TO_SYSCALL(i), 0, 1),
BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
};
diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c
index f82ddd530c..8436d4f95e 100644
--- a/src/core/load-fragment.c
+++ b/src/core/load-fragment.c
@@ -2120,10 +2120,12 @@ int config_parse_documentation(
}
static void syscall_set(uint32_t *p, int nr) {
+ nr = SYSCALL_TO_INDEX(nr);
p[nr >> 4] |= 1 << (nr & 31);
}
static void syscall_unset(uint32_t *p, int nr) {
+ nr = SYSCALL_TO_INDEX(nr);
p[nr >> 4] &= ~(1 << (nr & 31));
}
diff --git a/src/core/syscall-list.c b/src/core/syscall-list.c
index 05fad3e158..b608e8582f 100644
--- a/src/core/syscall-list.c
+++ b/src/core/syscall-list.c
@@ -32,6 +32,7 @@ const struct syscall_name *lookup_syscall(register const char *str, register uns
#include "syscall-from-name.h"
const char *syscall_to_name(int id) {
+ id = SYSCALL_TO_INDEX(id);
if (id < 0 || id >= (int) ELEMENTSOF(syscall_names))
return NULL;
diff --git a/src/core/syscall-list.h b/src/core/syscall-list.h
index 0fc6859605..503838b7fb 100644
--- a/src/core/syscall-list.h
+++ b/src/core/syscall-list.h
@@ -22,6 +22,20 @@
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
+#if defined __x86_64__ && defined __ILP32__
+/* The x32 ABI defines all of its syscalls with bit 30 set, which causes
+ issues when attempting to use syscalls as simple indicies into an array.
+ Instead, use the syscall id & ~SYSCALL_MASK as the index, and | the
+ internal id with the syscall mask as needed.
+*/
+#include <asm/unistd.h>
+#define SYSCALL_TO_INDEX(x) ((x) & ~__X32_SYSCALL_BIT)
+#define INDEX_TO_SYSCALL(x) ((x) | __X32_SYSCALL_BIT)
+#else
+#define SYSCALL_TO_INDEX(x) (x)
+#define INDEX_TO_SYSCALL(x) (x)
+#endif
+
const char *syscall_to_name(int id);
int syscall_from_name(const char *name);