1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * Copyright (C) 2020 Collabora Ltd.
4 */
5 #include <linux/elf.h>
6 #include <linux/entry-common.h>
7 #include <linux/prctl.h>
8 #include <linux/ptrace.h>
9 #include <linux/sched.h>
10 #include <linux/sched/signal.h>
11 #include <linux/sched/task_stack.h>
12 #include <linux/signal.h>
13 #include <linux/syscall_user_dispatch.h>
14 #include <linux/sysctl.h>
15 #include <linux/uaccess.h>
16
17 #include <asm/syscall.h>
18
19 static bool syscall_user_dispatch_allowed __read_mostly = true;
20
trigger_sigsys(struct pt_regs * regs)21 static void trigger_sigsys(struct pt_regs *regs)
22 {
23 struct kernel_siginfo info;
24
25 clear_siginfo(&info);
26 info.si_signo = SIGSYS;
27 info.si_code = SYS_USER_DISPATCH;
28 info.si_call_addr = (void __user *)KSTK_EIP(current);
29 info.si_errno = 0;
30 info.si_arch = syscall_get_arch(current);
31 info.si_syscall = syscall_get_nr(current, regs);
32
33 force_sig_info(&info);
34 }
35
syscall_user_dispatch(struct pt_regs * regs)36 bool syscall_user_dispatch(struct pt_regs *regs)
37 {
38 struct syscall_user_dispatch *sd = ¤t->syscall_dispatch;
39 char state;
40
41 if (likely(instruction_pointer(regs) - sd->offset < sd->len))
42 return false;
43
44 if (unlikely(arch_syscall_is_vdso_sigreturn(regs)))
45 return false;
46
47 if (likely(sd->selector)) {
48 /*
49 * access_ok() is performed once, at prctl time, when
50 * the selector is loaded by userspace.
51 */
52 if (unlikely(__get_user(state, sd->selector))) {
53 force_exit_sig(SIGSEGV);
54 return true;
55 }
56
57 if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW))
58 return false;
59
60 if (state != SYSCALL_DISPATCH_FILTER_BLOCK) {
61 force_exit_sig(SIGSYS);
62 return true;
63 }
64 }
65
66 sd->on_dispatch = true;
67 syscall_rollback(current, regs);
68 trigger_sigsys(regs);
69
70 return true;
71 }
72
task_set_syscall_user_dispatch(struct task_struct * task,unsigned long mode,unsigned long offset,unsigned long len,char __user * selector)73 static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned long mode,
74 unsigned long offset, unsigned long len,
75 char __user *selector)
76 {
77 switch (mode) {
78 case PR_SYS_DISPATCH_OFF:
79 if (offset || len || selector)
80 return -EINVAL;
81 break;
82 case PR_SYS_DISPATCH_EXCLUSIVE_ON:
83 /*
84 * Validate the direct dispatcher region just for basic
85 * sanity against overflow and a 0-sized dispatcher
86 * region. If the user is able to submit a syscall from
87 * an address, that address is obviously valid.
88 */
89 if (offset && offset + len <= offset)
90 return -EINVAL;
91 break;
92 case PR_SYS_DISPATCH_INCLUSIVE_ON:
93 if (len == 0 || offset + len <= offset)
94 return -EINVAL;
95 /*
96 * Invert the range, the check in syscall_user_dispatch()
97 * supports wrap-around.
98 */
99 offset = offset + len;
100 len = -len;
101 break;
102 default:
103 return -EINVAL;
104 }
105
106 /* Arming can be denied at runtime via sysctl, disarming is allowed */
107 if (mode != PR_SYS_DISPATCH_OFF && !syscall_user_dispatch_allowed)
108 return -EPERM;
109
110 /*
111 * access_ok() will clear memory tags for tagged addresses
112 * if current has memory tagging enabled.
113 *
114 * To enable a tracer to set a tracees selector the
115 * selector address must be untagged for access_ok(),
116 * otherwise an untagged tracer will always fail to set a
117 * tagged tracees selector.
118 */
119 if (mode != PR_SYS_DISPATCH_OFF && selector &&
120 !access_ok(untagged_addr(selector), sizeof(*selector)))
121 return -EFAULT;
122
123 task->syscall_dispatch.selector = selector;
124 task->syscall_dispatch.offset = offset;
125 task->syscall_dispatch.len = len;
126 task->syscall_dispatch.on_dispatch = false;
127
128 if (mode != PR_SYS_DISPATCH_OFF)
129 set_task_syscall_work(task, SYSCALL_USER_DISPATCH);
130 else
131 clear_task_syscall_work(task, SYSCALL_USER_DISPATCH);
132
133 return 0;
134 }
135
set_syscall_user_dispatch(unsigned long mode,unsigned long offset,unsigned long len,char __user * selector)136 int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
137 unsigned long len, char __user *selector)
138 {
139 return task_set_syscall_user_dispatch(current, mode, offset, len, selector);
140 }
141
syscall_user_dispatch_get_config(struct task_struct * task,unsigned long size,void __user * data)142 int syscall_user_dispatch_get_config(struct task_struct *task, unsigned long size,
143 void __user *data)
144 {
145 struct syscall_user_dispatch *sd = &task->syscall_dispatch;
146 struct ptrace_sud_config cfg;
147
148 if (size != sizeof(cfg))
149 return -EINVAL;
150
151 if (test_task_syscall_work(task, SYSCALL_USER_DISPATCH))
152 cfg.mode = PR_SYS_DISPATCH_ON;
153 else
154 cfg.mode = PR_SYS_DISPATCH_OFF;
155
156 cfg.offset = sd->offset;
157 cfg.len = sd->len;
158 cfg.selector = (__u64)(uintptr_t)sd->selector;
159
160 if (copy_to_user(data, &cfg, sizeof(cfg)))
161 return -EFAULT;
162
163 return 0;
164 }
165
syscall_user_dispatch_set_config(struct task_struct * task,unsigned long size,void __user * data)166 int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long size,
167 void __user *data)
168 {
169 struct ptrace_sud_config cfg;
170
171 if (size != sizeof(cfg))
172 return -EINVAL;
173
174 if (copy_from_user(&cfg, data, sizeof(cfg)))
175 return -EFAULT;
176
177 return task_set_syscall_user_dispatch(task, cfg.mode, cfg.offset, cfg.len,
178 (char __user *)(uintptr_t)cfg.selector);
179 }
180
181 #ifdef CONFIG_SYSCTL
182 static const struct ctl_table syscall_user_dispatch_sysctls[] = {
183 {
184 .procname = "syscall_user_dispatch",
185 .data = &syscall_user_dispatch_allowed,
186 .maxlen = sizeof(syscall_user_dispatch_allowed),
187 .mode = 0644,
188 .proc_handler = proc_dobool,
189 },
190 };
191
syscall_user_dispatch_sysctl_init(void)192 static int __init syscall_user_dispatch_sysctl_init(void)
193 {
194 register_sysctl_init("kernel", syscall_user_dispatch_sysctls);
195 return 0;
196 }
197 late_initcall(syscall_user_dispatch_sysctl_init);
198 #endif /* CONFIG_SYSCTL */
199