1 // SPDX-License-Identifier: GPL-2.0-or-later 2 3 #include <linux/compat.h> 4 #include <linux/syscalls.h> 5 #include <linux/time_namespace.h> 6 7 #include "futex.h" 8 9 /* 10 * Support for robust futexes: the kernel cleans up held futexes at 11 * thread exit time. 12 * 13 * Implementation: user-space maintains a per-thread list of locks it 14 * is holding. Upon do_exit(), the kernel carefully walks this list, 15 * and marks all locks that are owned by this thread with the 16 * FUTEX_OWNER_DIED bit, and wakes up a waiter (if any). The list is 17 * always manipulated with the lock held, so the list is private and 18 * per-thread. Userspace also maintains a per-thread 'list_op_pending' 19 * field, to allow the kernel to clean up if the thread dies after 20 * acquiring the lock, but just before it could have added itself to 21 * the list. There can only be one such pending lock. 22 */ 23 24 /** 25 * sys_set_robust_list() - Set the robust-futex list head of a task 26 * @head: pointer to the list-head 27 * @len: length of the list-head, as userspace expects 28 */ 29 SYSCALL_DEFINE2(set_robust_list, struct robust_list_head __user *, head, 30 size_t, len) 31 { 32 if (!futex_cmpxchg_enabled) 33 return -ENOSYS; 34 /* 35 * The kernel knows only one size for now: 36 */ 37 if (unlikely(len != sizeof(*head))) 38 return -EINVAL; 39 40 current->robust_list = head; 41 42 return 0; 43 } 44 45 /** 46 * sys_get_robust_list() - Get the robust-futex list head of a task 47 * @pid: pid of the process [zero for current task] 48 * @head_ptr: pointer to a list-head pointer, the kernel fills it in 49 * @len_ptr: pointer to a length field, the kernel fills in the header size 50 */ 51 SYSCALL_DEFINE3(get_robust_list, int, pid, 52 struct robust_list_head __user * __user *, head_ptr, 53 size_t __user *, len_ptr) 54 { 55 struct robust_list_head __user *head; 56 unsigned long ret; 57 struct task_struct *p; 58 59 if (!futex_cmpxchg_enabled) 60 return -ENOSYS; 61 62 rcu_read_lock(); 63 64 ret = -ESRCH; 65 if (!pid) 66 p = current; 67 else { 68 p = find_task_by_vpid(pid); 69 if (!p) 70 goto err_unlock; 71 } 72 73 ret = -EPERM; 74 if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) 75 goto err_unlock; 76 77 head = p->robust_list; 78 rcu_read_unlock(); 79 80 if (put_user(sizeof(*head), len_ptr)) 81 return -EFAULT; 82 return put_user(head, head_ptr); 83 84 err_unlock: 85 rcu_read_unlock(); 86 87 return ret; 88 } 89 90 long do_futex(u32 __user *uaddr, int op, u32 val, ktime_t *timeout, 91 u32 __user *uaddr2, u32 val2, u32 val3) 92 { 93 int cmd = op & FUTEX_CMD_MASK; 94 unsigned int flags = 0; 95 96 if (!(op & FUTEX_PRIVATE_FLAG)) 97 flags |= FLAGS_SHARED; 98 99 if (op & FUTEX_CLOCK_REALTIME) { 100 flags |= FLAGS_CLOCKRT; 101 if (cmd != FUTEX_WAIT_BITSET && cmd != FUTEX_WAIT_REQUEUE_PI && 102 cmd != FUTEX_LOCK_PI2) 103 return -ENOSYS; 104 } 105 106 switch (cmd) { 107 case FUTEX_LOCK_PI: 108 case FUTEX_LOCK_PI2: 109 case FUTEX_UNLOCK_PI: 110 case FUTEX_TRYLOCK_PI: 111 case FUTEX_WAIT_REQUEUE_PI: 112 case FUTEX_CMP_REQUEUE_PI: 113 if (!futex_cmpxchg_enabled) 114 return -ENOSYS; 115 } 116 117 switch (cmd) { 118 case FUTEX_WAIT: 119 val3 = FUTEX_BITSET_MATCH_ANY; 120 fallthrough; 121 case FUTEX_WAIT_BITSET: 122 return futex_wait(uaddr, flags, val, timeout, val3); 123 case FUTEX_WAKE: 124 val3 = FUTEX_BITSET_MATCH_ANY; 125 fallthrough; 126 case FUTEX_WAKE_BITSET: 127 return futex_wake(uaddr, flags, val, val3); 128 case FUTEX_REQUEUE: 129 return futex_requeue(uaddr, flags, uaddr2, val, val2, NULL, 0); 130 case FUTEX_CMP_REQUEUE: 131 return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 0); 132 case FUTEX_WAKE_OP: 133 return futex_wake_op(uaddr, flags, uaddr2, val, val2, val3); 134 case FUTEX_LOCK_PI: 135 flags |= FLAGS_CLOCKRT; 136 fallthrough; 137 case FUTEX_LOCK_PI2: 138 return futex_lock_pi(uaddr, flags, timeout, 0); 139 case FUTEX_UNLOCK_PI: 140 return futex_unlock_pi(uaddr, flags); 141 case FUTEX_TRYLOCK_PI: 142 return futex_lock_pi(uaddr, flags, NULL, 1); 143 case FUTEX_WAIT_REQUEUE_PI: 144 val3 = FUTEX_BITSET_MATCH_ANY; 145 return futex_wait_requeue_pi(uaddr, flags, val, timeout, val3, 146 uaddr2); 147 case FUTEX_CMP_REQUEUE_PI: 148 return futex_requeue(uaddr, flags, uaddr2, val, val2, &val3, 1); 149 } 150 return -ENOSYS; 151 } 152 153 static __always_inline bool futex_cmd_has_timeout(u32 cmd) 154 { 155 switch (cmd) { 156 case FUTEX_WAIT: 157 case FUTEX_LOCK_PI: 158 case FUTEX_LOCK_PI2: 159 case FUTEX_WAIT_BITSET: 160 case FUTEX_WAIT_REQUEUE_PI: 161 return true; 162 } 163 return false; 164 } 165 166 static __always_inline int 167 futex_init_timeout(u32 cmd, u32 op, struct timespec64 *ts, ktime_t *t) 168 { 169 if (!timespec64_valid(ts)) 170 return -EINVAL; 171 172 *t = timespec64_to_ktime(*ts); 173 if (cmd == FUTEX_WAIT) 174 *t = ktime_add_safe(ktime_get(), *t); 175 else if (cmd != FUTEX_LOCK_PI && !(op & FUTEX_CLOCK_REALTIME)) 176 *t = timens_ktime_to_host(CLOCK_MONOTONIC, *t); 177 return 0; 178 } 179 180 SYSCALL_DEFINE6(futex, u32 __user *, uaddr, int, op, u32, val, 181 const struct __kernel_timespec __user *, utime, 182 u32 __user *, uaddr2, u32, val3) 183 { 184 int ret, cmd = op & FUTEX_CMD_MASK; 185 ktime_t t, *tp = NULL; 186 struct timespec64 ts; 187 188 if (utime && futex_cmd_has_timeout(cmd)) { 189 if (unlikely(should_fail_futex(!(op & FUTEX_PRIVATE_FLAG)))) 190 return -EFAULT; 191 if (get_timespec64(&ts, utime)) 192 return -EFAULT; 193 ret = futex_init_timeout(cmd, op, &ts, &t); 194 if (ret) 195 return ret; 196 tp = &t; 197 } 198 199 return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3); 200 } 201 202 #ifdef CONFIG_COMPAT 203 COMPAT_SYSCALL_DEFINE2(set_robust_list, 204 struct compat_robust_list_head __user *, head, 205 compat_size_t, len) 206 { 207 if (!futex_cmpxchg_enabled) 208 return -ENOSYS; 209 210 if (unlikely(len != sizeof(*head))) 211 return -EINVAL; 212 213 current->compat_robust_list = head; 214 215 return 0; 216 } 217 218 COMPAT_SYSCALL_DEFINE3(get_robust_list, int, pid, 219 compat_uptr_t __user *, head_ptr, 220 compat_size_t __user *, len_ptr) 221 { 222 struct compat_robust_list_head __user *head; 223 unsigned long ret; 224 struct task_struct *p; 225 226 if (!futex_cmpxchg_enabled) 227 return -ENOSYS; 228 229 rcu_read_lock(); 230 231 ret = -ESRCH; 232 if (!pid) 233 p = current; 234 else { 235 p = find_task_by_vpid(pid); 236 if (!p) 237 goto err_unlock; 238 } 239 240 ret = -EPERM; 241 if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS)) 242 goto err_unlock; 243 244 head = p->compat_robust_list; 245 rcu_read_unlock(); 246 247 if (put_user(sizeof(*head), len_ptr)) 248 return -EFAULT; 249 return put_user(ptr_to_compat(head), head_ptr); 250 251 err_unlock: 252 rcu_read_unlock(); 253 254 return ret; 255 } 256 #endif /* CONFIG_COMPAT */ 257 258 #ifdef CONFIG_COMPAT_32BIT_TIME 259 SYSCALL_DEFINE6(futex_time32, u32 __user *, uaddr, int, op, u32, val, 260 const struct old_timespec32 __user *, utime, u32 __user *, uaddr2, 261 u32, val3) 262 { 263 int ret, cmd = op & FUTEX_CMD_MASK; 264 ktime_t t, *tp = NULL; 265 struct timespec64 ts; 266 267 if (utime && futex_cmd_has_timeout(cmd)) { 268 if (get_old_timespec32(&ts, utime)) 269 return -EFAULT; 270 ret = futex_init_timeout(cmd, op, &ts, &t); 271 if (ret) 272 return ret; 273 tp = &t; 274 } 275 276 return do_futex(uaddr, op, val, tp, uaddr2, (unsigned long)utime, val3); 277 } 278 #endif /* CONFIG_COMPAT_32BIT_TIME */ 279 280