Skip to content

Commit 9b01491

Browse files
committed
Handle PR_SET_USER_SYSCALL_DISPATCH by emulating a kernel that doesn't support it.
Fixes #4064
1 parent 45274f1 commit 9b01491

File tree

5 files changed

+62
-0
lines changed

5 files changed

+62
-0
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1278,6 +1278,7 @@ set(BASIC_TESTS
12781278
prctl_name
12791279
prctl_short_name
12801280
prctl_speculation_ctrl
1281+
prctl_syscall_user_dispatch
12811282
privileged_net_ioctl
12821283
proc_fds
12831284
proc_mem

src/kernel_supplement.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ enum {
547547
#define MREMAP_DONTUNMAP 4
548548
#endif
549549

550+
// New in the 5.11 kernel
551+
#ifndef PR_SET_SYSCALL_USER_DISPATCH
552+
#define PR_SET_SYSCALL_USER_DISPATCH 59
553+
#endif
554+
550555
// New in the 5.13 kernel
551556
#ifndef OTPERASE
552557
#define OTPERASE _IOW('M', 25, struct otp_info)

src/record_syscall.cc

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4936,6 +4936,16 @@ static Switchable rec_prepare_syscall_arch(RecordTask* t,
49364936
break;
49374937
}
49384938

4939+
case PR_SET_SYSCALL_USER_DISPATCH: {
4940+
// Prevent any PR_SET_SYSCALL_USER_DISPATCH call and pretend it's not
4941+
// supported.
4942+
Registers r = regs;
4943+
r.set_arg1(intptr_t(-1));
4944+
t->set_regs(r);
4945+
syscall_state.emulate_result(-EINVAL);
4946+
break;
4947+
}
4948+
49394949
default:
49404950
syscall_state.expect_errno = EINVAL;
49414951
break;
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
2+
3+
#include "util.h"
4+
5+
static int8_t control = SYSCALL_DISPATCH_FILTER_BLOCK;
6+
7+
static void handler(int sig, siginfo_t* si, void*) {
8+
control = SYSCALL_DISPATCH_FILTER_ALLOW;
9+
test_assert(sig == SIGSYS);
10+
test_assert(si->si_code == SYS_USER_DISPATCH);
11+
atomic_puts("Not running under rr apparently");
12+
}
13+
14+
int main(void) {
15+
struct sigaction sa;
16+
17+
sa.sa_sigaction = handler;
18+
sigemptyset(&sa.sa_mask);
19+
sa.sa_flags = SA_SIGINFO;
20+
sigaction(SIGSYS, &sa, NULL);
21+
22+
int ret = prctl(PR_SET_SYSCALL_USER_DISPATCH, PR_SYS_DISPATCH_ON, 0, 0, &control);
23+
if (ret == -1 && errno == EINVAL) {
24+
atomic_puts("PR_SET_SYSCALL_USER_DISPATCH not supported, skipping test");
25+
atomic_puts("EXIT-SUCCESS");
26+
return 0;
27+
}
28+
test_assert(ret >= 0);
29+
atomic_puts("EXIT-SUCCESS");
30+
return 0;
31+
}

src/test/util.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,21 @@ struct rr_open_how {
563563
#ifndef PR_GET_AUXV
564564
#define PR_GET_AUXV 0x41555856
565565
#endif
566+
#ifndef PR_SET_SYSCALL_USER_DISPATCH
567+
#define PR_SET_SYSCALL_USER_DISPATCH 59
568+
#endif
569+
#ifndef PR_SYS_DISPATCH_ON
570+
#define PR_SYS_DISPATCH_ON 1
571+
#endif
572+
#ifndef SYSCALL_DISPATCH_FILTER_ALLOW
573+
#define SYSCALL_DISPATCH_FILTER_ALLOW 0
574+
#endif
575+
#ifndef SYSCALL_DISPATCH_FILTER_BLOCK
576+
#define SYSCALL_DISPATCH_FILTER_BLOCK 1
577+
#endif
578+
#ifndef SYS_USER_DISPATCH
579+
#define SYS_USER_DISPATCH 2
580+
#endif
566581

567582
#ifndef BLKGETDISKSEQ
568583
#define BLKGETDISKSEQ _IOR(0x12,128,__u64)

0 commit comments

Comments
 (0)