1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020 Collabora Ltd.
5 #include <linux/sched.h>
6 #include <linux/prctl.h>
7 #include <linux/ptrace.h>
8 #include <linux/syscall_user_dispatch.h>
9 #include <linux/uaccess.h>
10 #include <linux/signal.h>
11 #include <linux/elf.h>
13 #include <linux/sched/signal.h>
14 #include <linux/sched/task_stack.h>
16 #include <asm/syscall.h>
20 static void trigger_sigsys(struct pt_regs
*regs
)
22 struct kernel_siginfo info
;
25 info
.si_signo
= SIGSYS
;
26 info
.si_code
= SYS_USER_DISPATCH
;
27 info
.si_call_addr
= (void __user
*)KSTK_EIP(current
);
29 info
.si_arch
= syscall_get_arch(current
);
30 info
.si_syscall
= syscall_get_nr(current
, regs
);
32 force_sig_info(&info
);
35 bool syscall_user_dispatch(struct pt_regs
*regs
)
37 struct syscall_user_dispatch
*sd
= ¤t
->syscall_dispatch
;
40 if (likely(instruction_pointer(regs
) - sd
->offset
< sd
->len
))
43 if (unlikely(arch_syscall_is_vdso_sigreturn(regs
)))
46 if (likely(sd
->selector
)) {
48 * access_ok() is performed once, at prctl time, when
49 * the selector is loaded by userspace.
51 if (unlikely(__get_user(state
, sd
->selector
))) {
52 force_exit_sig(SIGSEGV
);
56 if (likely(state
== SYSCALL_DISPATCH_FILTER_ALLOW
))
59 if (state
!= SYSCALL_DISPATCH_FILTER_BLOCK
) {
60 force_exit_sig(SIGSYS
);
65 sd
->on_dispatch
= true;
66 syscall_rollback(current
, regs
);
72 static int task_set_syscall_user_dispatch(struct task_struct
*task
, unsigned long mode
,
73 unsigned long offset
, unsigned long len
,
74 char __user
*selector
)
77 case PR_SYS_DISPATCH_OFF
:
78 if (offset
|| len
|| selector
)
81 case PR_SYS_DISPATCH_ON
:
83 * Validate the direct dispatcher region just for basic
84 * sanity against overflow and a 0-sized dispatcher
85 * region. If the user is able to submit a syscall from
86 * an address, that address is obviously valid.
88 if (offset
&& offset
+ len
<= offset
)
92 * access_ok() will clear memory tags for tagged addresses
93 * if current has memory tagging enabled.
95 * To enable a tracer to set a tracees selector the
96 * selector address must be untagged for access_ok(),
97 * otherwise an untagged tracer will always fail to set a
98 * tagged tracees selector.
100 if (selector
&& !access_ok(untagged_addr(selector
), sizeof(*selector
)))
108 task
->syscall_dispatch
.selector
= selector
;
109 task
->syscall_dispatch
.offset
= offset
;
110 task
->syscall_dispatch
.len
= len
;
111 task
->syscall_dispatch
.on_dispatch
= false;
113 if (mode
== PR_SYS_DISPATCH_ON
)
114 set_task_syscall_work(task
, SYSCALL_USER_DISPATCH
);
116 clear_task_syscall_work(task
, SYSCALL_USER_DISPATCH
);
121 int set_syscall_user_dispatch(unsigned long mode
, unsigned long offset
,
122 unsigned long len
, char __user
*selector
)
124 return task_set_syscall_user_dispatch(current
, mode
, offset
, len
, selector
);
127 int syscall_user_dispatch_get_config(struct task_struct
*task
, unsigned long size
,
130 struct syscall_user_dispatch
*sd
= &task
->syscall_dispatch
;
131 struct ptrace_sud_config cfg
;
133 if (size
!= sizeof(cfg
))
136 if (test_task_syscall_work(task
, SYSCALL_USER_DISPATCH
))
137 cfg
.mode
= PR_SYS_DISPATCH_ON
;
139 cfg
.mode
= PR_SYS_DISPATCH_OFF
;
141 cfg
.offset
= sd
->offset
;
143 cfg
.selector
= (__u64
)(uintptr_t)sd
->selector
;
145 if (copy_to_user(data
, &cfg
, sizeof(cfg
)))
151 int syscall_user_dispatch_set_config(struct task_struct
*task
, unsigned long size
,
154 struct ptrace_sud_config cfg
;
156 if (size
!= sizeof(cfg
))
159 if (copy_from_user(&cfg
, data
, sizeof(cfg
)))
162 return task_set_syscall_user_dispatch(task
, cfg
.mode
, cfg
.offset
, cfg
.len
,
163 (char __user
*)(uintptr_t)cfg
.selector
);