Skip to content

Commit bef71f8

Browse files
committed
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: Christian Brauner <[email protected]> Link: https://lore.kernel.org/lkml/20200921075031.j4gruygeugkp2zwd@wittgenstein/ Signed-off-by: Kees Cook <[email protected]>
1 parent 71c87fb commit bef71f8

File tree

1 file changed

+47
-12
lines changed

1 file changed

+47
-12
lines changed

tools/testing/selftests/seccomp/seccomp_bpf.c

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1888,27 +1888,47 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
18881888
}
18891889

18901890
/* Architecture-specific syscall changing routine. */
1891-
void change_syscall(struct __test_metadata *_metadata,
1892-
pid_t tracee, int syscall, int result)
1891+
void __change_syscall(struct __test_metadata *_metadata,
1892+
pid_t tracee, long *syscall, long *ret)
18931893
{
18941894
ARCH_REGS orig, regs;
18951895

1896+
/* Do not get/set registers if we have nothing to do. */
1897+
if (!syscall && !ret)
1898+
return;
1899+
18961900
EXPECT_EQ(0, ARCH_GETREGS(regs)) {
18971901
return;
18981902
}
18991903
orig = regs;
19001904

1901-
SYSCALL_NUM_SET(regs, syscall);
1905+
if (syscall)
1906+
SYSCALL_NUM_SET(regs, *syscall);
19021907

1903-
/* If syscall is skipped, change return value. */
1904-
if (syscall == -1)
1905-
SYSCALL_RET_SET(regs, result);
1908+
if (ret)
1909+
SYSCALL_RET_SET(regs, *ret);
19061910

19071911
/* Flush any register changes made. */
19081912
if (memcmp(&orig, &regs, sizeof(orig)) != 0)
19091913
EXPECT_EQ(0, ARCH_SETREGS(regs));
19101914
}
19111915

1916+
/* Change only syscall number. */
1917+
void change_syscall_nr(struct __test_metadata *_metadata,
1918+
pid_t tracee, long syscall)
1919+
{
1920+
__change_syscall(_metadata, tracee, &syscall, NULL);
1921+
}
1922+
1923+
/* Change syscall return value (and set syscall number to -1). */
1924+
void change_syscall_ret(struct __test_metadata *_metadata,
1925+
pid_t tracee, long ret)
1926+
{
1927+
long syscall = -1;
1928+
1929+
__change_syscall(_metadata, tracee, &syscall, &ret);
1930+
}
1931+
19121932
void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
19131933
int status, void *args)
19141934
{
@@ -1924,17 +1944,17 @@ void tracer_seccomp(struct __test_metadata *_metadata, pid_t tracee,
19241944
case 0x1002:
19251945
/* change getpid to getppid. */
19261946
EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
1927-
change_syscall(_metadata, tracee, __NR_getppid, 0);
1947+
change_syscall_nr(_metadata, tracee, __NR_getppid);
19281948
break;
19291949
case 0x1003:
19301950
/* skip gettid with valid return code. */
19311951
EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
1932-
change_syscall(_metadata, tracee, -1, 45000);
1952+
change_syscall_ret(_metadata, tracee, 45000);
19331953
break;
19341954
case 0x1004:
19351955
/* skip openat with error. */
19361956
EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
1937-
change_syscall(_metadata, tracee, -1, -ESRCH);
1957+
change_syscall_ret(_metadata, tracee, -ESRCH);
19381958
break;
19391959
case 0x1005:
19401960
/* do nothing (allow getppid) */
@@ -1961,6 +1981,8 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
19611981
int ret;
19621982
unsigned long msg;
19631983
static bool entry;
1984+
long syscall_nr_val, syscall_ret_val;
1985+
long *syscall_nr = NULL, *syscall_ret = NULL;
19641986
FIXTURE_DATA(TRACE_syscall) *self = args;
19651987

19661988
/*
@@ -1987,17 +2009,30 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
19872009
else
19882010
return;
19892011

2012+
syscall_nr = &syscall_nr_val;
2013+
syscall_ret = &syscall_ret_val;
2014+
2015+
/* Now handle the actual rewriting cases. */
19902016
switch (self->syscall_nr) {
19912017
case __NR_getpid:
1992-
change_syscall(_metadata, tracee, __NR_getppid, 0);
2018+
syscall_nr_val = __NR_getppid;
2019+
/* Never change syscall return for this case. */
2020+
syscall_ret = NULL;
19932021
break;
19942022
case __NR_gettid:
1995-
change_syscall(_metadata, tracee, -1, 45000);
2023+
syscall_nr_val = -1;
2024+
syscall_ret_val = 45000;
19962025
break;
19972026
case __NR_openat:
1998-
change_syscall(_metadata, tracee, -1, -ESRCH);
2027+
syscall_nr_val = -1;
2028+
syscall_ret_val = -ESRCH;
19992029
break;
2030+
default:
2031+
/* Unhandled, do nothing. */
2032+
return;
20002033
}
2034+
2035+
__change_syscall(_metadata, tracee, syscall_nr, syscall_ret);
20012036
}
20022037

20032038
FIXTURE_VARIANT(TRACE_syscall) {

0 commit comments

Comments
 (0)