xref: /linux/kernel/entry/syscall_user_dispatch.c (revision 12d5fc96ebbb3b948861805b32a4c3a96105ccd9)
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 
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 
36 bool syscall_user_dispatch(struct pt_regs *regs)
37 {
38 	struct syscall_user_dispatch *sd = &current->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 		if (unlikely(get_user(state, untagged_addr(sd->selector)))) {
49 			force_exit_sig(SIGSEGV);
50 			return true;
51 		}
52 
53 		if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW))
54 			return false;
55 
56 		if (state != SYSCALL_DISPATCH_FILTER_BLOCK) {
57 			force_exit_sig(SIGSYS);
58 			return true;
59 		}
60 	}
61 
62 	sd->on_dispatch = true;
63 	syscall_rollback(current, regs);
64 	trigger_sigsys(regs);
65 
66 	return true;
67 }
68 
69 static int task_set_syscall_user_dispatch(struct task_struct *task, unsigned long mode,
70 					  unsigned long offset, unsigned long len,
71 					  char __user *selector)
72 {
73 	switch (mode) {
74 	case PR_SYS_DISPATCH_OFF:
75 		if (offset || len || selector)
76 			return -EINVAL;
77 		break;
78 	case PR_SYS_DISPATCH_EXCLUSIVE_ON:
79 		/*
80 		 * Validate the direct dispatcher region just for basic
81 		 * sanity against overflow and a 0-sized dispatcher
82 		 * region.  If the user is able to submit a syscall from
83 		 * an address, that address is obviously valid.
84 		 */
85 		if (offset && offset + len <= offset)
86 			return -EINVAL;
87 		break;
88 	case PR_SYS_DISPATCH_INCLUSIVE_ON:
89 		if (len == 0 || offset + len <= offset)
90 			return -EINVAL;
91 		/*
92 		 * Invert the range, the check in syscall_user_dispatch()
93 		 * supports wrap-around.
94 		 */
95 		offset = offset + len;
96 		len = -len;
97 		break;
98 	default:
99 		return -EINVAL;
100 	}
101 
102 	/* Arming can be denied at runtime via sysctl, disarming is allowed */
103 	if (mode != PR_SYS_DISPATCH_OFF && !syscall_user_dispatch_allowed)
104 		return -EPERM;
105 
106 	/*
107 	 * access_ok() will clear memory tags for tagged addresses
108 	 * if current has memory tagging enabled.
109 	 *
110 	 * To enable a tracer to set a tracees selector the
111 	 * selector address must be untagged for access_ok(),
112 	 * otherwise an untagged tracer will always fail to set a
113 	 * tagged tracees selector.
114 	 */
115 	if (mode != PR_SYS_DISPATCH_OFF && selector &&
116 		!access_ok(untagged_addr(selector), sizeof(*selector)))
117 		return -EFAULT;
118 
119 	task->syscall_dispatch.selector = selector;
120 	task->syscall_dispatch.offset = offset;
121 	task->syscall_dispatch.len = len;
122 	task->syscall_dispatch.on_dispatch = false;
123 
124 	if (mode != PR_SYS_DISPATCH_OFF)
125 		set_task_syscall_work(task, SYSCALL_USER_DISPATCH);
126 	else
127 		clear_task_syscall_work(task, SYSCALL_USER_DISPATCH);
128 
129 	return 0;
130 }
131 
132 int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
133 			      unsigned long len, char __user *selector)
134 {
135 	return task_set_syscall_user_dispatch(current, mode, offset, len, selector);
136 }
137 
138 int syscall_user_dispatch_get_config(struct task_struct *task, unsigned long size,
139 				     void __user *data)
140 {
141 	struct syscall_user_dispatch *sd = &task->syscall_dispatch;
142 	struct ptrace_sud_config cfg;
143 
144 	if (size != sizeof(cfg))
145 		return -EINVAL;
146 
147 	if (test_task_syscall_work(task, SYSCALL_USER_DISPATCH))
148 		cfg.mode = PR_SYS_DISPATCH_ON;
149 	else
150 		cfg.mode = PR_SYS_DISPATCH_OFF;
151 
152 	cfg.offset = sd->offset;
153 	cfg.len = sd->len;
154 	cfg.selector = (__u64)(uintptr_t)sd->selector;
155 
156 	if (copy_to_user(data, &cfg, sizeof(cfg)))
157 		return -EFAULT;
158 
159 	return 0;
160 }
161 
162 int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long size,
163 				     void __user *data)
164 {
165 	struct ptrace_sud_config cfg;
166 
167 	if (size != sizeof(cfg))
168 		return -EINVAL;
169 
170 	if (copy_from_user(&cfg, data, sizeof(cfg)))
171 		return -EFAULT;
172 
173 	return task_set_syscall_user_dispatch(task, cfg.mode, cfg.offset, cfg.len,
174 					      (char __user *)(uintptr_t)cfg.selector);
175 }
176 
177 #ifdef CONFIG_SYSCTL
178 static const struct ctl_table syscall_user_dispatch_sysctls[] = {
179 	{
180 		.procname	= "syscall_user_dispatch",
181 		.data		= &syscall_user_dispatch_allowed,
182 		.maxlen		= sizeof(syscall_user_dispatch_allowed),
183 		.mode		= 0644,
184 		.proc_handler	= proc_dobool,
185 	},
186 };
187 
188 static int __init syscall_user_dispatch_sysctl_init(void)
189 {
190 	register_sysctl_init("kernel", syscall_user_dispatch_sysctls);
191 	return 0;
192 }
193 late_initcall(syscall_user_dispatch_sysctl_init);
194 #endif /* CONFIG_SYSCTL */
195