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); !! 87 struct rseq __user *rseq = t->rseq; 93 u32 mm_cid = task_mm_cid(t); << 94 88 95 WARN_ON_ONCE((int) mm_cid < 0); !! 89 if (!user_write_access_begin(rseq, sizeof(*rseq))) 96 if (!user_write_access_begin(rseq, t-> << 97 goto efault; 90 goto efault; 98 unsafe_put_user(cpu_id, &rseq->cpu_id_ 91 unsafe_put_user(cpu_id, &rseq->cpu_id_start, efault_end); 99 unsafe_put_user(cpu_id, &rseq->cpu_id, 92 unsafe_put_user(cpu_id, &rseq->cpu_id, efault_end); 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(); 93 user_write_access_end(); 108 trace_rseq_update(t); 94 trace_rseq_update(t); 109 return 0; 95 return 0; 110 96 111 efault_end: 97 efault_end: 112 user_write_access_end(); 98 user_write_access_end(); 113 efault: 99 efault: 114 return -EFAULT; 100 return -EFAULT; 115 } 101 } 116 102 117 static int rseq_reset_rseq_cpu_node_id(struct !! 103 static int rseq_reset_rseq_cpu_id(struct task_struct *t) 118 { 104 { 119 u32 cpu_id_start = 0, cpu_id = RSEQ_CP !! 105 u32 cpu_id_start = 0, cpu_id = RSEQ_CPU_ID_UNINITIALIZED; 120 mm_cid = 0; << 121 106 122 /* 107 /* 123 * Reset cpu_id_start to its initial s 108 * Reset cpu_id_start to its initial state (0). 124 */ 109 */ 125 if (put_user(cpu_id_start, &t->rseq->c 110 if (put_user(cpu_id_start, &t->rseq->cpu_id_start)) 126 return -EFAULT; 111 return -EFAULT; 127 /* 112 /* 128 * Reset cpu_id to RSEQ_CPU_ID_UNINITI 113 * Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming 129 * in after unregistration can figure 114 * in after unregistration can figure out that rseq needs to be 130 * registered again. 115 * registered again. 131 */ 116 */ 132 if (put_user(cpu_id, &t->rseq->cpu_id) 117 if (put_user(cpu_id, &t->rseq->cpu_id)) 133 return -EFAULT; 118 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; 119 return 0; 150 } 120 } 151 121 152 static int rseq_get_rseq_cs(struct task_struct 122 static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs) 153 { 123 { 154 struct rseq_cs __user *urseq_cs; 124 struct rseq_cs __user *urseq_cs; 155 u64 ptr; 125 u64 ptr; 156 u32 __user *usig; 126 u32 __user *usig; 157 u32 sig; 127 u32 sig; 158 int ret; 128 int ret; 159 129 160 #ifdef CONFIG_64BIT 130 #ifdef CONFIG_64BIT 161 if (get_user(ptr, &t->rseq->rseq_cs)) 131 if (get_user(ptr, &t->rseq->rseq_cs)) 162 return -EFAULT; 132 return -EFAULT; 163 #else 133 #else 164 if (copy_from_user(&ptr, &t->rseq->rse 134 if (copy_from_user(&ptr, &t->rseq->rseq_cs, sizeof(ptr))) 165 return -EFAULT; 135 return -EFAULT; 166 #endif 136 #endif 167 if (!ptr) { 137 if (!ptr) { 168 memset(rseq_cs, 0, sizeof(*rse 138 memset(rseq_cs, 0, sizeof(*rseq_cs)); 169 return 0; 139 return 0; 170 } 140 } 171 if (ptr >= TASK_SIZE) 141 if (ptr >= TASK_SIZE) 172 return -EINVAL; 142 return -EINVAL; 173 urseq_cs = (struct rseq_cs __user *)(u 143 urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr; 174 if (copy_from_user(rseq_cs, urseq_cs, 144 if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs))) 175 return -EFAULT; 145 return -EFAULT; 176 146 177 if (rseq_cs->start_ip >= TASK_SIZE || 147 if (rseq_cs->start_ip >= TASK_SIZE || 178 rseq_cs->start_ip + rseq_cs->post_ 148 rseq_cs->start_ip + rseq_cs->post_commit_offset >= TASK_SIZE || 179 rseq_cs->abort_ip >= TASK_SIZE || 149 rseq_cs->abort_ip >= TASK_SIZE || 180 rseq_cs->version > 0) 150 rseq_cs->version > 0) 181 return -EINVAL; 151 return -EINVAL; 182 /* Check for overflow. */ 152 /* Check for overflow. */ 183 if (rseq_cs->start_ip + rseq_cs->post_ 153 if (rseq_cs->start_ip + rseq_cs->post_commit_offset < rseq_cs->start_ip) 184 return -EINVAL; 154 return -EINVAL; 185 /* Ensure that abort_ip is not in the 155 /* Ensure that abort_ip is not in the critical section. */ 186 if (rseq_cs->abort_ip - rseq_cs->start 156 if (rseq_cs->abort_ip - rseq_cs->start_ip < rseq_cs->post_commit_offset) 187 return -EINVAL; 157 return -EINVAL; 188 158 189 usig = (u32 __user *)(unsigned long)(r 159 usig = (u32 __user *)(unsigned long)(rseq_cs->abort_ip - sizeof(u32)); 190 ret = get_user(sig, usig); 160 ret = get_user(sig, usig); 191 if (ret) 161 if (ret) 192 return ret; 162 return ret; 193 163 194 if (current->rseq_sig != sig) { 164 if (current->rseq_sig != sig) { 195 printk_ratelimited(KERN_WARNIN 165 printk_ratelimited(KERN_WARNING 196 "Possible attack attem 166 "Possible attack attempt. Unexpected rseq signature 0x%x, expecting 0x%x (pid=%d, addr=%p).\n", 197 sig, current->rseq_sig 167 sig, current->rseq_sig, current->pid, usig); 198 return -EINVAL; 168 return -EINVAL; 199 } 169 } 200 return 0; 170 return 0; 201 } 171 } 202 172 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 173 static int rseq_need_restart(struct task_struct *t, u32 cs_flags) 219 { 174 { 220 u32 flags, event_mask; 175 u32 flags, event_mask; 221 int ret; 176 int ret; 222 177 223 if (rseq_warn_flags("rseq_cs", cs_flag << 224 return -EINVAL; << 225 << 226 /* Get thread flags. */ 178 /* Get thread flags. */ 227 ret = get_user(flags, &t->rseq->flags) 179 ret = get_user(flags, &t->rseq->flags); 228 if (ret) 180 if (ret) 229 return ret; 181 return ret; 230 182 231 if (rseq_warn_flags("rseq", flags)) !! 183 /* Take critical section flags into account. */ >> 184 flags |= cs_flags; >> 185 >> 186 /* >> 187 * Restart on signal can only be inhibited when restart on >> 188 * preempt and restart on migrate are inhibited too. Otherwise, >> 189 * a preempted signal handler could fail to restart the prior >> 190 * execution context on sigreturn. >> 191 */ >> 192 if (unlikely((flags & RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL) && >> 193 (flags & RSEQ_CS_PREEMPT_MIGRATE_FLAGS) != >> 194 RSEQ_CS_PREEMPT_MIGRATE_FLAGS)) 232 return -EINVAL; 195 return -EINVAL; 233 196 234 /* 197 /* 235 * Load and clear event mask atomicall 198 * Load and clear event mask atomically with respect to 236 * scheduler preemption. 199 * scheduler preemption. 237 */ 200 */ 238 preempt_disable(); 201 preempt_disable(); 239 event_mask = t->rseq_event_mask; 202 event_mask = t->rseq_event_mask; 240 t->rseq_event_mask = 0; 203 t->rseq_event_mask = 0; 241 preempt_enable(); 204 preempt_enable(); 242 205 243 return !!event_mask; !! 206 return !!(event_mask & ~flags); 244 } 207 } 245 208 246 static int clear_rseq_cs(struct task_struct *t 209 static int clear_rseq_cs(struct task_struct *t) 247 { 210 { 248 /* 211 /* 249 * The rseq_cs field is set to NULL on 212 * The rseq_cs field is set to NULL on preemption or signal 250 * delivery on top of rseq assembly bl 213 * delivery on top of rseq assembly block, as well as on top 251 * of code outside of the rseq assembl 214 * of code outside of the rseq assembly block. This performs 252 * a lazy clear of the rseq_cs field. 215 * a lazy clear of the rseq_cs field. 253 * 216 * 254 * Set rseq_cs to NULL. 217 * Set rseq_cs to NULL. 255 */ 218 */ 256 #ifdef CONFIG_64BIT 219 #ifdef CONFIG_64BIT 257 return put_user(0UL, &t->rseq->rseq_cs 220 return put_user(0UL, &t->rseq->rseq_cs); 258 #else 221 #else 259 if (clear_user(&t->rseq->rseq_cs, size 222 if (clear_user(&t->rseq->rseq_cs, sizeof(t->rseq->rseq_cs))) 260 return -EFAULT; 223 return -EFAULT; 261 return 0; 224 return 0; 262 #endif 225 #endif 263 } 226 } 264 227 265 /* 228 /* 266 * Unsigned comparison will be true when ip >= 229 * Unsigned comparison will be true when ip >= start_ip, and when 267 * ip < start_ip + post_commit_offset. 230 * ip < start_ip + post_commit_offset. 268 */ 231 */ 269 static bool in_rseq_cs(unsigned long ip, struc 232 static bool in_rseq_cs(unsigned long ip, struct rseq_cs *rseq_cs) 270 { 233 { 271 return ip - rseq_cs->start_ip < rseq_c 234 return ip - rseq_cs->start_ip < rseq_cs->post_commit_offset; 272 } 235 } 273 236 274 static int rseq_ip_fixup(struct pt_regs *regs) 237 static int rseq_ip_fixup(struct pt_regs *regs) 275 { 238 { 276 unsigned long ip = instruction_pointer 239 unsigned long ip = instruction_pointer(regs); 277 struct task_struct *t = current; 240 struct task_struct *t = current; 278 struct rseq_cs rseq_cs; 241 struct rseq_cs rseq_cs; 279 int ret; 242 int ret; 280 243 281 ret = rseq_get_rseq_cs(t, &rseq_cs); 244 ret = rseq_get_rseq_cs(t, &rseq_cs); 282 if (ret) 245 if (ret) 283 return ret; 246 return ret; 284 247 285 /* 248 /* 286 * Handle potentially not being within 249 * Handle potentially not being within a critical section. 287 * If not nested over a rseq critical 250 * If not nested over a rseq critical section, restart is useless. 288 * Clear the rseq_cs pointer and retur 251 * Clear the rseq_cs pointer and return. 289 */ 252 */ 290 if (!in_rseq_cs(ip, &rseq_cs)) 253 if (!in_rseq_cs(ip, &rseq_cs)) 291 return clear_rseq_cs(t); 254 return clear_rseq_cs(t); 292 ret = rseq_need_restart(t, rseq_cs.fla 255 ret = rseq_need_restart(t, rseq_cs.flags); 293 if (ret <= 0) 256 if (ret <= 0) 294 return ret; 257 return ret; 295 ret = clear_rseq_cs(t); 258 ret = clear_rseq_cs(t); 296 if (ret) 259 if (ret) 297 return ret; 260 return ret; 298 trace_rseq_ip_fixup(ip, rseq_cs.start_ 261 trace_rseq_ip_fixup(ip, rseq_cs.start_ip, rseq_cs.post_commit_offset, 299 rseq_cs.abort_ip); 262 rseq_cs.abort_ip); 300 instruction_pointer_set(regs, (unsigne 263 instruction_pointer_set(regs, (unsigned long)rseq_cs.abort_ip); 301 return 0; 264 return 0; 302 } 265 } 303 266 304 /* 267 /* 305 * This resume handler must always be executed 268 * This resume handler must always be executed between any of: 306 * - preemption, 269 * - preemption, 307 * - signal delivery, 270 * - signal delivery, 308 * and return to user-space. 271 * and return to user-space. 309 * 272 * 310 * This is how we can ensure that the entire r 273 * This is how we can ensure that the entire rseq critical section 311 * will issue the commit instruction only if e 274 * will issue the commit instruction only if executed atomically with 312 * respect to other threads scheduled on the s 275 * respect to other threads scheduled on the same CPU, and with respect 313 * to signal handlers. 276 * to signal handlers. 314 */ 277 */ 315 void __rseq_handle_notify_resume(struct ksigna 278 void __rseq_handle_notify_resume(struct ksignal *ksig, struct pt_regs *regs) 316 { 279 { 317 struct task_struct *t = current; 280 struct task_struct *t = current; 318 int ret, sig; 281 int ret, sig; 319 282 320 if (unlikely(t->flags & PF_EXITING)) 283 if (unlikely(t->flags & PF_EXITING)) 321 return; 284 return; 322 285 323 /* 286 /* 324 * regs is NULL if and only if the cal 287 * regs is NULL if and only if the caller is in a syscall path. Skip 325 * fixup and leave rseq_cs as is so th 288 * fixup and leave rseq_cs as is so that rseq_sycall() will detect and 326 * kill a misbehaving userspace on deb 289 * kill a misbehaving userspace on debug kernels. 327 */ 290 */ 328 if (regs) { 291 if (regs) { 329 ret = rseq_ip_fixup(regs); 292 ret = rseq_ip_fixup(regs); 330 if (unlikely(ret < 0)) 293 if (unlikely(ret < 0)) 331 goto error; 294 goto error; 332 } 295 } 333 if (unlikely(rseq_update_cpu_node_id(t !! 296 if (unlikely(rseq_update_cpu_id(t))) 334 goto error; 297 goto error; 335 return; 298 return; 336 299 337 error: 300 error: 338 sig = ksig ? ksig->sig : 0; 301 sig = ksig ? ksig->sig : 0; 339 force_sigsegv(sig); 302 force_sigsegv(sig); 340 } 303 } 341 304 342 #ifdef CONFIG_DEBUG_RSEQ 305 #ifdef CONFIG_DEBUG_RSEQ 343 306 344 /* 307 /* 345 * Terminate the process if a syscall is issue 308 * Terminate the process if a syscall is issued within a restartable 346 * sequence. 309 * sequence. 347 */ 310 */ 348 void rseq_syscall(struct pt_regs *regs) 311 void rseq_syscall(struct pt_regs *regs) 349 { 312 { 350 unsigned long ip = instruction_pointer 313 unsigned long ip = instruction_pointer(regs); 351 struct task_struct *t = current; 314 struct task_struct *t = current; 352 struct rseq_cs rseq_cs; 315 struct rseq_cs rseq_cs; 353 316 354 if (!t->rseq) 317 if (!t->rseq) 355 return; 318 return; 356 if (rseq_get_rseq_cs(t, &rseq_cs) || i 319 if (rseq_get_rseq_cs(t, &rseq_cs) || in_rseq_cs(ip, &rseq_cs)) 357 force_sig(SIGSEGV); 320 force_sig(SIGSEGV); 358 } 321 } 359 322 360 #endif 323 #endif 361 324 362 /* 325 /* 363 * sys_rseq - setup restartable sequences for 326 * sys_rseq - setup restartable sequences for caller thread. 364 */ 327 */ 365 SYSCALL_DEFINE4(rseq, struct rseq __user *, rs 328 SYSCALL_DEFINE4(rseq, struct rseq __user *, rseq, u32, rseq_len, 366 int, flags, u32, sig) 329 int, flags, u32, sig) 367 { 330 { 368 int ret; 331 int ret; 369 332 370 if (flags & RSEQ_FLAG_UNREGISTER) { 333 if (flags & RSEQ_FLAG_UNREGISTER) { 371 if (flags & ~RSEQ_FLAG_UNREGIS 334 if (flags & ~RSEQ_FLAG_UNREGISTER) 372 return -EINVAL; 335 return -EINVAL; 373 /* Unregister rseq for current 336 /* Unregister rseq for current thread. */ 374 if (current->rseq != rseq || ! 337 if (current->rseq != rseq || !current->rseq) 375 return -EINVAL; 338 return -EINVAL; 376 if (rseq_len != current->rseq_ !! 339 if (rseq_len != sizeof(*rseq)) 377 return -EINVAL; 340 return -EINVAL; 378 if (current->rseq_sig != sig) 341 if (current->rseq_sig != sig) 379 return -EPERM; 342 return -EPERM; 380 ret = rseq_reset_rseq_cpu_node !! 343 ret = rseq_reset_rseq_cpu_id(current); 381 if (ret) 344 if (ret) 382 return ret; 345 return ret; 383 current->rseq = NULL; 346 current->rseq = NULL; 384 current->rseq_sig = 0; 347 current->rseq_sig = 0; 385 current->rseq_len = 0; << 386 return 0; 348 return 0; 387 } 349 } 388 350 389 if (unlikely(flags)) 351 if (unlikely(flags)) 390 return -EINVAL; 352 return -EINVAL; 391 353 392 if (current->rseq) { 354 if (current->rseq) { 393 /* 355 /* 394 * If rseq is already register 356 * If rseq is already registered, check whether 395 * the provided address differ 357 * the provided address differs from the prior 396 * one. 358 * one. 397 */ 359 */ 398 if (current->rseq != rseq || r !! 360 if (current->rseq != rseq || rseq_len != sizeof(*rseq)) 399 return -EINVAL; 361 return -EINVAL; 400 if (current->rseq_sig != sig) 362 if (current->rseq_sig != sig) 401 return -EPERM; 363 return -EPERM; 402 /* Already registered. */ 364 /* Already registered. */ 403 return -EBUSY; 365 return -EBUSY; 404 } 366 } 405 367 406 /* 368 /* 407 * If there was no rseq previously reg !! 369 * If there was no rseq previously registered, 408 * is properly aligned, as communcated !! 370 * 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 */ 371 */ 416 if (rseq_len < ORIG_RSEQ_SIZE || !! 372 if (!IS_ALIGNED((unsigned long)rseq, __alignof__(*rseq)) || 417 (rseq_len == ORIG_RSEQ_SIZE && !IS !! 373 rseq_len != sizeof(*rseq)) 418 (rseq_len != ORIG_RSEQ_SIZE && (!I << 419 rs << 420 return -EINVAL; 374 return -EINVAL; 421 if (!access_ok(rseq, rseq_len)) 375 if (!access_ok(rseq, rseq_len)) 422 return -EFAULT; 376 return -EFAULT; 423 current->rseq = rseq; 377 current->rseq = rseq; 424 current->rseq_len = rseq_len; << 425 current->rseq_sig = sig; 378 current->rseq_sig = sig; 426 /* 379 /* 427 * If rseq was previously inactive, an 380 * If rseq was previously inactive, and has just been 428 * registered, ensure the cpu_id_start 381 * registered, ensure the cpu_id_start and cpu_id fields 429 * are updated before returning to use 382 * are updated before returning to user-space. 430 */ 383 */ 431 rseq_set_notify_resume(current); 384 rseq_set_notify_resume(current); 432 385 433 return 0; 386 return 0; 434 } 387 } 435 388
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.