1 // SPDX-License-Identifier: GPL-2.0+ 1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 2 /* 3 * Restartable sequences system call 3 * Restartable sequences system call 4 * 4 * 5 * Copyright (C) 2015, Google, Inc., 5 * Copyright (C) 2015, Google, Inc., 6 * Paul Turner <pjt@google.com> and Andrew Hun 6 * Paul Turner <pjt@google.com> and Andrew Hunter <ahh@google.com> 7 * Copyright (C) 2015-2018, EfficiOS Inc., 7 * Copyright (C) 2015-2018, EfficiOS Inc., 8 * Mathieu Desnoyers <mathieu.desnoyers@effici 8 * Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 9 */ 9 */ 10 10 11 #include <linux/sched.h> 11 #include <linux/sched.h> 12 #include <linux/uaccess.h> 12 #include <linux/uaccess.h> 13 #include <linux/syscalls.h> 13 #include <linux/syscalls.h> 14 #include <linux/rseq.h> 14 #include <linux/rseq.h> 15 #include <linux/types.h> 15 #include <linux/types.h> 16 #include <asm/ptrace.h> 16 #include <asm/ptrace.h> 17 17 18 #define CREATE_TRACE_POINTS 18 #define CREATE_TRACE_POINTS 19 #include <trace/events/rseq.h> 19 #include <trace/events/rseq.h> 20 20 21 /* The original rseq structure size (including !! 21 #define RSEQ_CS_PREEMPT_MIGRATE_FLAGS (RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE | \ 22 #define ORIG_RSEQ_SIZE 32 !! 22 RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT) 23 << 24 #define RSEQ_CS_NO_RESTART_FLAGS (RSEQ_CS_FLAG << 25 RSEQ_CS_FLAG << 26 RSEQ_CS_FLAG << 27 23 28 /* 24 /* 29 * 25 * 30 * Restartable sequences are a lightweight int 26 * Restartable sequences are a lightweight interface that allows 31 * user-level code to be executed atomically r 27 * user-level code to be executed atomically relative to scheduler 32 * preemption and signal delivery. Typically u 28 * preemption and signal delivery. Typically used for implementing 33 * per-cpu operations. 29 * per-cpu operations. 34 * 30 * 35 * It allows user-space to perform update oper 31 * It allows user-space to perform update operations on per-cpu data 36 * without requiring heavy-weight atomic opera 32 * without requiring heavy-weight atomic operations. 37 * 33 * 38 * Detailed algorithm of rseq user-space assem 34 * Detailed algorithm of rseq user-space assembly sequences: 39 * 35 * 40 * init(rseq_cs) 36 * init(rseq_cs) 41 * cpu = TLS->rseq::cpu_id 37 * cpu = TLS->rseq::cpu_id_start 42 * [1] TLS->rseq::rseq_cs = rs 38 * [1] TLS->rseq::rseq_cs = rseq_cs 43 * [start_ip] ----------------------- 39 * [start_ip] ---------------------------- 44 * [2] if (cpu != TLS->rseq::c 40 * [2] if (cpu != TLS->rseq::cpu_id) 45 * goto abort_ip; 41 * goto abort_ip; 46 * [3] <last_instruction_in_cs 42 * [3] <last_instruction_in_cs> 47 * [post_commit_ip] ----------------------- 43 * [post_commit_ip] ---------------------------- 48 * 44 * 49 * The address of jump target abort_ip must 45 * The address of jump target abort_ip must be outside the critical 50 * region, i.e.: 46 * region, i.e.: 51 * 47 * 52 * [abort_ip] < [start_ip] || [abort_ip] 48 * [abort_ip] < [start_ip] || [abort_ip] >= [post_commit_ip] 53 * 49 * 54 * Steps [2]-[3] (inclusive) need to be a se 50 * Steps [2]-[3] (inclusive) need to be a sequence of instructions in 55 * userspace that can handle being interrupt 51 * userspace that can handle being interrupted between any of those 56 * instructions, and then resumed to the abo 52 * instructions, and then resumed to the abort_ip. 57 * 53 * 58 * 1. Userspace stores the address of the s 54 * 1. Userspace stores the address of the struct rseq_cs assembly 59 * block descriptor into the rseq_cs fie 55 * block descriptor into the rseq_cs field of the registered 60 * struct rseq TLS area. This update is 56 * struct rseq TLS area. This update is performed through a single 61 * store within the inline assembly inst 57 * store within the inline assembly instruction sequence. 62 * [start_ip] 58 * [start_ip] 63 * 59 * 64 * 2. Userspace tests to check whether the 60 * 2. Userspace tests to check whether the current cpu_id field match 65 * the cpu number loaded before start_ip 61 * the cpu number loaded before start_ip, branching to abort_ip 66 * in case of a mismatch. 62 * in case of a mismatch. 67 * 63 * 68 * If the sequence is preempted or inter 64 * If the sequence is preempted or interrupted by a signal 69 * at or after start_ip and before post_ 65 * at or after start_ip and before post_commit_ip, then the kernel 70 * clears TLS->__rseq_abi::rseq_cs, and 66 * clears TLS->__rseq_abi::rseq_cs, and sets the user-space return 71 * ip to abort_ip before returning to us 67 * ip to abort_ip before returning to user-space, so the preempted 72 * execution resumes at abort_ip. 68 * execution resumes at abort_ip. 73 * 69 * 74 * 3. Userspace critical section final inst 70 * 3. Userspace critical section final instruction before 75 * post_commit_ip is the commit. The cri 71 * post_commit_ip is the commit. The critical section is 76 * self-terminating. 72 * self-terminating. 77 * [post_commit_ip] 73 * [post_commit_ip] 78 * 74 * 79 * 4. <success> 75 * 4. <success> 80 * 76 * 81 * On failure at [2], or if interrupted by p 77 * On failure at [2], or if interrupted by preempt or signal delivery 82 * between [1] and [3]: 78 * between [1] and [3]: 83 * 79 * 84 * [abort_ip] 80 * [abort_ip] 85 * F1. <failure> 81 * F1. <failure> 86 */ 82 */ 87 83 88 static int rseq_update_cpu_node_id(struct task !! 84 static int rseq_update_cpu_id(struct task_struct *t) 89 { 85 { 90 struct rseq __user *rseq = t->rseq; << 91 u32 cpu_id = raw_smp_processor_id(); 86 u32 cpu_id = raw_smp_processor_id(); 92 u32 node_id = cpu_to_node(cpu_id); << 93 u32 mm_cid = task_mm_cid(t); << 94 87 95 WARN_ON_ONCE((int) mm_cid < 0); !! 88 if (put_user(cpu_id, &t->rseq->cpu_id_start)) 96 if (!user_write_access_begin(rseq, t-> !! 89 return -EFAULT; 97 goto efault; !! 90 if (put_user(cpu_id, &t->rseq->cpu_id)) 98 unsafe_put_user(cpu_id, &rseq->cpu_id_ !! 91 return -EFAULT; 99 unsafe_put_user(cpu_id, &rseq->cpu_id, << 100 unsafe_put_user(node_id, &rseq->node_i << 101 unsafe_put_user(mm_cid, &rseq->mm_cid, << 102 /* << 103 * Additional feature fields added aft << 104 * need to be conditionally updated on << 105 * t->rseq_len != ORIG_RSEQ_SIZE. << 106 */ << 107 user_write_access_end(); << 108 trace_rseq_update(t); 92 trace_rseq_update(t); 109 return 0; 93 return 0; 110 << 111 efault_end: << 112 user_write_access_end(); << 113 efault: << 114 return -EFAULT; << 115 } 94 } 116 95 117 static int rseq_reset_rseq_cpu_node_id(struct !! 96 static int rseq_reset_rseq_cpu_id(struct task_struct *t) 118 { 97 { 119 u32 cpu_id_start = 0, cpu_id = RSEQ_CP !! 98 u32 cpu_id_start = 0, cpu_id = RSEQ_CPU_ID_UNINITIALIZED; 120 mm_cid = 0; << 121 99 122 /* 100 /* 123 * Reset cpu_id_start to its initial s 101 * Reset cpu_id_start to its initial state (0). 124 */ 102 */ 125 if (put_user(cpu_id_start, &t->rseq->c 103 if (put_user(cpu_id_start, &t->rseq->cpu_id_start)) 126 return -EFAULT; 104 return -EFAULT; 127 /* 105 /* 128 * Reset cpu_id to RSEQ_CPU_ID_UNINITI 106 * Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming 129 * in after unregistration can figure 107 * in after unregistration can figure out that rseq needs to be 130 * registered again. 108 * registered again. 131 */ 109 */ 132 if (put_user(cpu_id, &t->rseq->cpu_id) 110 if (put_user(cpu_id, &t->rseq->cpu_id)) 133 return -EFAULT; 111 return -EFAULT; 134 /* << 135 * Reset node_id to its initial state << 136 */ << 137 if (put_user(node_id, &t->rseq->node_i << 138 return -EFAULT; << 139 /* << 140 * Reset mm_cid to its initial state ( << 141 */ << 142 if (put_user(mm_cid, &t->rseq->mm_cid) << 143 return -EFAULT; << 144 /* << 145 * Additional feature fields added aft << 146 * need to be conditionally reset only << 147 * t->rseq_len != ORIG_RSEQ_SIZE. << 148 */ << 149 return 0; 112 return 0; 150 } 113 } 151 114 152 static int rseq_get_rseq_cs(struct task_struct 115 static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs) 153 { 116 { 154 struct rseq_cs __user *urseq_cs; 117 struct rseq_cs __user *urseq_cs; 155 u64 ptr; 118 u64 ptr; 156 u32 __user *usig; 119 u32 __user *usig; 157 u32 sig; 120 u32 sig; 158 int ret; 121 int ret; 159 122 160 #ifdef CONFIG_64BIT !! 123 if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr))) 161 if (get_user(ptr, &t->rseq->rseq_cs)) << 162 return -EFAULT; << 163 #else << 164 if (copy_from_user(&ptr, &t->rseq->rse << 165 return -EFAULT; 124 return -EFAULT; 166 #endif << 167 if (!ptr) { 125 if (!ptr) { 168 memset(rseq_cs, 0, sizeof(*rse 126 memset(rseq_cs, 0, sizeof(*rseq_cs)); 169 return 0; 127 return 0; 170 } 128 } 171 if (ptr >= TASK_SIZE) 129 if (ptr >= TASK_SIZE) 172 return -EINVAL; 130 return -EINVAL; 173 urseq_cs = (struct rseq_cs __user *)(u 131 urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr; 174 if (copy_from_user(rseq_cs, urseq_cs, 132 if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs))) 175 return -EFAULT; 133 return -EFAULT; 176 134 177 if (rseq_cs->start_ip >= TASK_SIZE || 135 if (rseq_cs->start_ip >= TASK_SIZE || 178 rseq_cs->start_ip + rseq_cs->post_ 136 rseq_cs->start_ip + rseq_cs->post_commit_offset >= TASK_SIZE || 179 rseq_cs->abort_ip >= TASK_SIZE || 137 rseq_cs->abort_ip >= TASK_SIZE || 180 rseq_cs->version > 0) 138 rseq_cs->version > 0) 181 return -EINVAL; 139 return -EINVAL; 182 /* Check for overflow. */ 140 /* Check for overflow. */ 183 if (rseq_cs->start_ip + rseq_cs->post_ 141 if (rseq_cs->start_ip + rseq_cs->post_commit_offset < rseq_cs->start_ip) 184 return -EINVAL; 142 return -EINVAL; 185 /* Ensure that abort_ip is not in the 143 /* Ensure that abort_ip is not in the critical section. */ 186 if (rseq_cs->abort_ip - rseq_cs->start 144 if (rseq_cs->abort_ip - rseq_cs->start_ip < rseq_cs->post_commit_offset) 187 return -EINVAL; 145 return -EINVAL; 188 146 189 usig = (u32 __user *)(unsigned long)(r 147 usig = (u32 __user *)(unsigned long)(rseq_cs->abort_ip - sizeof(u32)); 190 ret = get_user(sig, usig); 148 ret = get_user(sig, usig); 191 if (ret) 149 if (ret) 192 return ret; 150 return ret; 193 151 194 if (current->rseq_sig != sig) { 152 if (current->rseq_sig != sig) { 195 printk_ratelimited(KERN_WARNIN 153 printk_ratelimited(KERN_WARNING 196 "Possible attack attem 154 "Possible attack attempt. Unexpected rseq signature 0x%x, expecting 0x%x (pid=%d, addr=%p).\n", 197 sig, current->rseq_sig 155 sig, current->rseq_sig, current->pid, usig); 198 return -EINVAL; 156 return -EINVAL; 199 } 157 } 200 return 0; 158 return 0; 201 } 159 } 202 160 203 static bool rseq_warn_flags(const char *str, u << 204 { << 205 u32 test_flags; << 206 << 207 if (!flags) << 208 return false; << 209 test_flags = flags & RSEQ_CS_NO_RESTAR << 210 if (test_flags) << 211 pr_warn_once("Deprecated flags << 212 test_flags = flags & ~RSEQ_CS_NO_RESTA << 213 if (test_flags) << 214 pr_warn_once("Unknown flags (% << 215 return true; << 216 } << 217 << 218 static int rseq_need_restart(struct task_struc 161 static int rseq_need_restart(struct task_struct *t, u32 cs_flags) 219 { 162 { 220 u32 flags, event_mask; 163 u32 flags, event_mask; 221 int ret; 164 int ret; 222 165 223 if (rseq_warn_flags("rseq_cs", cs_flag << 224 return -EINVAL; << 225 << 226 /* Get thread flags. */ 166 /* Get thread flags. */ 227 ret = get_user(flags, &t->rseq->flags) 167 ret = get_user(flags, &t->rseq->flags); 228 if (ret) 168 if (ret) 229 return ret; 169 return ret; 230 170 231 if (rseq_warn_flags("rseq", flags)) !! 171 /* Take critical section flags into account. */ >> 172 flags |= cs_flags; >> 173 >> 174 /* >> 175 * Restart on signal can only be inhibited when restart on >> 176 * preempt and restart on migrate are inhibited too. Otherwise, >> 177 * a preempted signal handler could fail to restart the prior >> 178 * execution context on sigreturn. >> 179 */ >> 180 if (unlikely((flags & RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL) && >> 181 (flags & RSEQ_CS_PREEMPT_MIGRATE_FLAGS) != >> 182 RSEQ_CS_PREEMPT_MIGRATE_FLAGS)) 232 return -EINVAL; 183 return -EINVAL; 233 184 234 /* 185 /* 235 * Load and clear event mask atomicall 186 * Load and clear event mask atomically with respect to 236 * scheduler preemption. 187 * scheduler preemption. 237 */ 188 */ 238 preempt_disable(); 189 preempt_disable(); 239 event_mask = t->rseq_event_mask; 190 event_mask = t->rseq_event_mask; 240 t->rseq_event_mask = 0; 191 t->rseq_event_mask = 0; 241 preempt_enable(); 192 preempt_enable(); 242 193 243 return !!event_mask; !! 194 return !!(event_mask & ~flags); 244 } 195 } 245 196 246 static int clear_rseq_cs(struct task_struct *t 197 static int clear_rseq_cs(struct task_struct *t) 247 { 198 { 248 /* 199 /* 249 * The rseq_cs field is set to NULL on 200 * The rseq_cs field is set to NULL on preemption or signal 250 * delivery on top of rseq assembly bl 201 * delivery on top of rseq assembly block, as well as on top 251 * of code outside of the rseq assembl 202 * of code outside of the rseq assembly block. This performs 252 * a lazy clear of the rseq_cs field. 203 * a lazy clear of the rseq_cs field. 253 * 204 * 254 * Set rseq_cs to NULL. 205 * Set rseq_cs to NULL. 255 */ 206 */ 256 #ifdef CONFIG_64BIT !! 207 if (clear_user(&t->rseq->rseq_cs.ptr64, sizeof(t->rseq->rseq_cs.ptr64))) 257 return put_user(0UL, &t->rseq->rseq_cs << 258 #else << 259 if (clear_user(&t->rseq->rseq_cs, size << 260 return -EFAULT; 208 return -EFAULT; 261 return 0; 209 return 0; 262 #endif << 263 } 210 } 264 211 265 /* 212 /* 266 * Unsigned comparison will be true when ip >= 213 * Unsigned comparison will be true when ip >= start_ip, and when 267 * ip < start_ip + post_commit_offset. 214 * ip < start_ip + post_commit_offset. 268 */ 215 */ 269 static bool in_rseq_cs(unsigned long ip, struc 216 static bool in_rseq_cs(unsigned long ip, struct rseq_cs *rseq_cs) 270 { 217 { 271 return ip - rseq_cs->start_ip < rseq_c 218 return ip - rseq_cs->start_ip < rseq_cs->post_commit_offset; 272 } 219 } 273 220 274 static int rseq_ip_fixup(struct pt_regs *regs) 221 static int rseq_ip_fixup(struct pt_regs *regs) 275 { 222 { 276 unsigned long ip = instruction_pointer 223 unsigned long ip = instruction_pointer(regs); 277 struct task_struct *t = current; 224 struct task_struct *t = current; 278 struct rseq_cs rseq_cs; 225 struct rseq_cs rseq_cs; 279 int ret; 226 int ret; 280 227 281 ret = rseq_get_rseq_cs(t, &rseq_cs); 228 ret = rseq_get_rseq_cs(t, &rseq_cs); 282 if (ret) 229 if (ret) 283 return ret; 230 return ret; 284 231 285 /* 232 /* 286 * Handle potentially not being within 233 * Handle potentially not being within a critical section. 287 * If not nested over a rseq critical 234 * If not nested over a rseq critical section, restart is useless. 288 * Clear the rseq_cs pointer and retur 235 * Clear the rseq_cs pointer and return. 289 */ 236 */ 290 if (!in_rseq_cs(ip, &rseq_cs)) 237 if (!in_rseq_cs(ip, &rseq_cs)) 291 return clear_rseq_cs(t); 238 return clear_rseq_cs(t); 292 ret = rseq_need_restart(t, rseq_cs.fla 239 ret = rseq_need_restart(t, rseq_cs.flags); 293 if (ret <= 0) 240 if (ret <= 0) 294 return ret; 241 return ret; 295 ret = clear_rseq_cs(t); 242 ret = clear_rseq_cs(t); 296 if (ret) 243 if (ret) 297 return ret; 244 return ret; 298 trace_rseq_ip_fixup(ip, rseq_cs.start_ 245 trace_rseq_ip_fixup(ip, rseq_cs.start_ip, rseq_cs.post_commit_offset, 299 rseq_cs.abort_ip); 246 rseq_cs.abort_ip); 300 instruction_pointer_set(regs, (unsigne 247 instruction_pointer_set(regs, (unsigned long)rseq_cs.abort_ip); 301 return 0; 248 return 0; 302 } 249 } 303 250 304 /* 251 /* 305 * This resume handler must always be executed 252 * This resume handler must always be executed between any of: 306 * - preemption, 253 * - preemption, 307 * - signal delivery, 254 * - signal delivery, 308 * and return to user-space. 255 * and return to user-space. 309 * 256 * 310 * This is how we can ensure that the entire r !! 257 * This is how we can ensure that the entire rseq critical section, >> 258 * consisting of both the C part and the assembly instruction sequence, 311 * will issue the commit instruction only if e 259 * will issue the commit instruction only if executed atomically with 312 * respect to other threads scheduled on the s 260 * respect to other threads scheduled on the same CPU, and with respect 313 * to signal handlers. 261 * to signal handlers. 314 */ 262 */ 315 void __rseq_handle_notify_resume(struct ksigna 263 void __rseq_handle_notify_resume(struct ksignal *ksig, struct pt_regs *regs) 316 { 264 { 317 struct task_struct *t = current; 265 struct task_struct *t = current; 318 int ret, sig; 266 int ret, sig; 319 267 320 if (unlikely(t->flags & PF_EXITING)) 268 if (unlikely(t->flags & PF_EXITING)) 321 return; 269 return; 322 !! 270 if (unlikely(!access_ok(VERIFY_WRITE, t->rseq, sizeof(*t->rseq)))) 323 /* !! 271 goto error; 324 * regs is NULL if and only if the cal !! 272 ret = rseq_ip_fixup(regs); 325 * fixup and leave rseq_cs as is so th !! 273 if (unlikely(ret < 0)) 326 * kill a misbehaving userspace on deb !! 274 goto error; 327 */ !! 275 if (unlikely(rseq_update_cpu_id(t))) 328 if (regs) { << 329 ret = rseq_ip_fixup(regs); << 330 if (unlikely(ret < 0)) << 331 goto error; << 332 } << 333 if (unlikely(rseq_update_cpu_node_id(t << 334 goto error; 276 goto error; 335 return; 277 return; 336 278 337 error: 279 error: 338 sig = ksig ? ksig->sig : 0; 280 sig = ksig ? ksig->sig : 0; 339 force_sigsegv(sig); !! 281 force_sigsegv(sig, t); 340 } 282 } 341 283 342 #ifdef CONFIG_DEBUG_RSEQ 284 #ifdef CONFIG_DEBUG_RSEQ 343 285 344 /* 286 /* 345 * Terminate the process if a syscall is issue 287 * Terminate the process if a syscall is issued within a restartable 346 * sequence. 288 * sequence. 347 */ 289 */ 348 void rseq_syscall(struct pt_regs *regs) 290 void rseq_syscall(struct pt_regs *regs) 349 { 291 { 350 unsigned long ip = instruction_pointer 292 unsigned long ip = instruction_pointer(regs); 351 struct task_struct *t = current; 293 struct task_struct *t = current; 352 struct rseq_cs rseq_cs; 294 struct rseq_cs rseq_cs; 353 295 354 if (!t->rseq) 296 if (!t->rseq) 355 return; 297 return; 356 if (rseq_get_rseq_cs(t, &rseq_cs) || i !! 298 if (!access_ok(VERIFY_READ, t->rseq, sizeof(*t->rseq)) || 357 force_sig(SIGSEGV); !! 299 rseq_get_rseq_cs(t, &rseq_cs) || in_rseq_cs(ip, &rseq_cs)) >> 300 force_sig(SIGSEGV, t); 358 } 301 } 359 302 360 #endif 303 #endif 361 304 362 /* 305 /* 363 * sys_rseq - setup restartable sequences for 306 * sys_rseq - setup restartable sequences for caller thread. 364 */ 307 */ 365 SYSCALL_DEFINE4(rseq, struct rseq __user *, rs 308 SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, 366 int, flags, u32, sig) 309 int, flags, u32, sig) 367 { 310 { 368 int ret; 311 int ret; 369 312 370 if (flags & RSEQ_FLAG_UNREGISTER) { 313 if (flags & RSEQ_FLAG_UNREGISTER) { 371 if (flags & ~RSEQ_FLAG_UNREGIS << 372 return -EINVAL; << 373 /* Unregister rseq for current 314 /* Unregister rseq for current thread. */ 374 if (current->rseq != rseq || ! 315 if (current->rseq != rseq || !current->rseq) 375 return -EINVAL; 316 return -EINVAL; 376 if (rseq_len != current->rseq_ !! 317 if (current->rseq_len != rseq_len) 377 return -EINVAL; 318 return -EINVAL; 378 if (current->rseq_sig != sig) 319 if (current->rseq_sig != sig) 379 return -EPERM; 320 return -EPERM; 380 ret = rseq_reset_rseq_cpu_node !! 321 ret = rseq_reset_rseq_cpu_id(current); 381 if (ret) 322 if (ret) 382 return ret; 323 return ret; 383 current->rseq = NULL; 324 current->rseq = NULL; 384 current->rseq_sig = 0; << 385 current->rseq_len = 0; 325 current->rseq_len = 0; >> 326 current->rseq_sig = 0; 386 return 0; 327 return 0; 387 } 328 } 388 329 389 if (unlikely(flags)) 330 if (unlikely(flags)) 390 return -EINVAL; 331 return -EINVAL; 391 332 392 if (current->rseq) { 333 if (current->rseq) { 393 /* 334 /* 394 * If rseq is already register 335 * If rseq is already registered, check whether 395 * the provided address differ 336 * the provided address differs from the prior 396 * one. 337 * one. 397 */ 338 */ 398 if (current->rseq != rseq || r !! 339 if (current->rseq != rseq || current->rseq_len != rseq_len) 399 return -EINVAL; 340 return -EINVAL; 400 if (current->rseq_sig != sig) 341 if (current->rseq_sig != sig) 401 return -EPERM; 342 return -EPERM; 402 /* Already registered. */ 343 /* Already registered. */ 403 return -EBUSY; 344 return -EBUSY; 404 } 345 } 405 346 406 /* 347 /* 407 * If there was no rseq previously reg !! 348 * If there was no rseq previously registered, 408 * is properly aligned, as communcated !! 349 * ensure the provided rseq is properly aligned and valid. 409 * auxiliary vector AT_RSEQ_ALIGN. If << 410 * size, the required alignment is the << 411 * << 412 * In order to be valid, rseq_len is e << 413 * large enough to contain all support << 414 * user-space through the ELF auxiliar << 415 */ 350 */ 416 if (rseq_len < ORIG_RSEQ_SIZE || !! 351 if (!IS_ALIGNED((unsigned long)rseq, __alignof__(*rseq)) || 417 (rseq_len == ORIG_RSEQ_SIZE && !IS !! 352 rseq_len != sizeof(*rseq)) 418 (rseq_len != ORIG_RSEQ_SIZE && (!I << 419 rs << 420 return -EINVAL; 353 return -EINVAL; 421 if (!access_ok(rseq, rseq_len)) !! 354 if (!access_ok(VERIFY_WRITE, rseq, rseq_len)) 422 return -EFAULT; 355 return -EFAULT; 423 current->rseq = rseq; 356 current->rseq = rseq; 424 current->rseq_len = rseq_len; 357 current->rseq_len = rseq_len; 425 current->rseq_sig = sig; 358 current->rseq_sig = sig; 426 /* 359 /* 427 * If rseq was previously inactive, an 360 * If rseq was previously inactive, and has just been 428 * registered, ensure the cpu_id_start 361 * registered, ensure the cpu_id_start and cpu_id fields 429 * are updated before returning to use 362 * are updated before returning to user-space. 430 */ 363 */ 431 rseq_set_notify_resume(current); 364 rseq_set_notify_resume(current); 432 365 433 return 0; 366 return 0; 434 } 367 } 435 368
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.