Merge tag 'ext4_for_linus_stable' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux-block.git] / kernel / entry / syscall_user_dispatch.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) 2020 Collabora Ltd.
4  */
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>
12
13 #include <linux/sched/signal.h>
14 #include <linux/sched/task_stack.h>
15
16 #include <asm/syscall.h>
17
18 #include "common.h"
19
20 static void trigger_sigsys(struct pt_regs *regs)
21 {
22         struct kernel_siginfo info;
23
24         clear_siginfo(&info);
25         info.si_signo = SIGSYS;
26         info.si_code = SYS_USER_DISPATCH;
27         info.si_call_addr = (void __user *)KSTK_EIP(current);
28         info.si_errno = 0;
29         info.si_arch = syscall_get_arch(current);
30         info.si_syscall = syscall_get_nr(current, regs);
31
32         force_sig_info(&info);
33 }
34
35 bool syscall_user_dispatch(struct pt_regs *regs)
36 {
37         struct syscall_user_dispatch *sd = &current->syscall_dispatch;
38         char state;
39
40         if (likely(instruction_pointer(regs) - sd->offset < sd->len))
41                 return false;
42
43         if (unlikely(arch_syscall_is_vdso_sigreturn(regs)))
44                 return false;
45
46         if (likely(sd->selector)) {
47                 /*
48                  * access_ok() is performed once, at prctl time, when
49                  * the selector is loaded by userspace.
50                  */
51                 if (unlikely(__get_user(state, sd->selector))) {
52                         force_exit_sig(SIGSEGV);
53                         return true;
54                 }
55
56                 if (likely(state == SYSCALL_DISPATCH_FILTER_ALLOW))
57                         return false;
58
59                 if (state != SYSCALL_DISPATCH_FILTER_BLOCK) {
60                         force_exit_sig(SIGSYS);
61                         return true;
62                 }
63         }
64
65         sd->on_dispatch = true;
66         syscall_rollback(current, regs);
67         trigger_sigsys(regs);
68
69         return true;
70 }
71
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)
75 {
76         switch (mode) {
77         case PR_SYS_DISPATCH_OFF:
78                 if (offset || len || selector)
79                         return -EINVAL;
80                 break;
81         case PR_SYS_DISPATCH_ON:
82                 /*
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.
87                  */
88                 if (offset && offset + len <= offset)
89                         return -EINVAL;
90
91                 /*
92                  * access_ok() will clear memory tags for tagged addresses
93                  * if current has memory tagging enabled.
94
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.
99                  */
100                 if (selector && !access_ok(untagged_addr(selector), sizeof(*selector)))
101                         return -EFAULT;
102
103                 break;
104         default:
105                 return -EINVAL;
106         }
107
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;
112
113         if (mode == PR_SYS_DISPATCH_ON)
114                 set_task_syscall_work(task, SYSCALL_USER_DISPATCH);
115         else
116                 clear_task_syscall_work(task, SYSCALL_USER_DISPATCH);
117
118         return 0;
119 }
120
121 int set_syscall_user_dispatch(unsigned long mode, unsigned long offset,
122                               unsigned long len, char __user *selector)
123 {
124         return task_set_syscall_user_dispatch(current, mode, offset, len, selector);
125 }
126
127 int syscall_user_dispatch_get_config(struct task_struct *task, unsigned long size,
128                                      void __user *data)
129 {
130         struct syscall_user_dispatch *sd = &task->syscall_dispatch;
131         struct ptrace_sud_config cfg;
132
133         if (size != sizeof(cfg))
134                 return -EINVAL;
135
136         if (test_task_syscall_work(task, SYSCALL_USER_DISPATCH))
137                 cfg.mode = PR_SYS_DISPATCH_ON;
138         else
139                 cfg.mode = PR_SYS_DISPATCH_OFF;
140
141         cfg.offset = sd->offset;
142         cfg.len = sd->len;
143         cfg.selector = (__u64)(uintptr_t)sd->selector;
144
145         if (copy_to_user(data, &cfg, sizeof(cfg)))
146                 return -EFAULT;
147
148         return 0;
149 }
150
151 int syscall_user_dispatch_set_config(struct task_struct *task, unsigned long size,
152                                      void __user *data)
153 {
154         struct ptrace_sud_config cfg;
155
156         if (size != sizeof(cfg))
157                 return -EINVAL;
158
159         if (copy_from_user(&cfg, data, sizeof(cfg)))
160                 return -EFAULT;
161
162         return task_set_syscall_user_dispatch(task, cfg.mode, cfg.offset, cfg.len,
163                                               (char __user *)(uintptr_t)cfg.selector);
164 }