提交 bef71f86 编写于 作者: K Kees Cook

selftests/seccomp: Allow syscall nr and ret value to be set separately

In preparation for setting syscall nr and ret values separately, refactor
the helpers to take a pointer to a value, so that a NULL can indicate
"do not change this respective value". This is done to keep the regset
read/write happening once and in one code path.
Acked-by: NChristian Brauner <christian.brauner@ubuntu.com>
Link: https://lore.kernel.org/lkml/20200921075031.j4gruygeugkp2zwd@wittgenstein/Signed-off-by: NKees Cook <keescook@chromium.org>
上级 71c87fbe
......@@ -1888,27 +1888,47 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
}
/* Architecture-specific syscall changing routine. */
void change_syscall(struct __test_metadata *_metadata,
pid_t tracee, int syscall, int result)
void __change_syscall(struct __test_metadata *_metadata,
pid_t tracee, long *syscall, long *ret)
{
ARCH_REGS orig, regs;
/* Do not get/set registers if we have nothing to do. */
if (!syscall && !ret)
return;
EXPECT_EQ(0, ARCH_GETREGS(regs)) {
return;
}
orig = regs;
SYSCALL_NUM_SET(regs, syscall);
if (syscall)
SYSCALL_NUM_SET(regs, *syscall);
/* If syscall is skipped, change return value. */
if (syscall == -1)
SYSCALL_RET_SET(regs, result);
if (ret)
SYSCALL_RET_SET(regs, *ret);
/* Flush any register changes made. */
if (memcmp(&orig, &regs, sizeof(orig)) != 0)
EXPECT_EQ(0, ARCH_SETREGS(regs));
}
/* Change only syscall number. */
void change_syscall_nr(struct __test_metadata *_metadata,
pid_t tracee, long syscall)
{
__change_syscall(_metadata, tracee, &syscall, NULL);
}
/* Change syscall return value (and set syscall number to -1). */
void change_syscall_ret(struct __test_metadata *_metadata,
pid_t tracee, long ret)
{
long syscall = -1;
__change_syscall(_metadata, tracee, &syscall, &ret);
}
void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
int status, void *args)
{
......@@ -1924,17 +1944,17 @@ void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
case 0x1002:
/* change getpid to getppid. */
EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
change_syscall(_metadata, tracee, __NR_getppid, 0);
change_syscall_nr(_metadata, tracee, __NR_getppid);
break;
case 0x1003:
/* skip gettid with valid return code. */
EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
change_syscall(_metadata, tracee, -1, 45000);
change_syscall_ret(_metadata, tracee, 45000);
break;
case 0x1004:
/* skip openat with error. */
EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
change_syscall(_metadata, tracee, -1, -ESRCH);
change_syscall_ret(_metadata, tracee, -ESRCH);
break;
case 0x1005:
/* do nothing (allow getppid) */
......@@ -1961,6 +1981,8 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
int ret;
unsigned long msg;
static bool entry;
long syscall_nr_val, syscall_ret_val;
long *syscall_nr = NULL, *syscall_ret = NULL;
FIXTURE_DATA(TRACE_syscall) *self = args;
/*
......@@ -1987,17 +2009,30 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
else
return;
syscall_nr = &syscall_nr_val;
syscall_ret = &syscall_ret_val;
/* Now handle the actual rewriting cases. */
switch (self->syscall_nr) {
case __NR_getpid:
change_syscall(_metadata, tracee, __NR_getppid, 0);
syscall_nr_val = __NR_getppid;
/* Never change syscall return for this case. */
syscall_ret = NULL;
break;
case __NR_gettid:
change_syscall(_metadata, tracee, -1, 45000);
syscall_nr_val = -1;
syscall_ret_val = 45000;
break;
case __NR_openat:
change_syscall(_metadata, tracee, -1, -ESRCH);
syscall_nr_val = -1;
syscall_ret_val = -ESRCH;
break;
default:
/* Unhandled, do nothing. */
return;
}
__change_syscall(_metadata, tracee, syscall_nr, syscall_ret);
}
FIXTURE_VARIANT(TRACE_syscall) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册