Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull rseq fixes from Ingo Molnar:
"Various rseq ABI fixes and cleanups: use get_user()/put_user(),
validate parameters and use proper uapi types, etc"

* 'core-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
rseq/selftests: cleanup: Update comment above rseq_prepare_unload
rseq: Remove unused types_32_64.h uapi header
rseq: uapi: Declare rseq_cs field as union, update includes
rseq: uapi: Update uapi comments
rseq: Use get_user/put_user rather than __get_user/__put_user
rseq: Use __u64 for rseq_cs fields, validate user inputs

+100 -117
+58 -44
include/uapi/linux/rseq.h
··· 10 10 * Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 11 11 */ 12 12 13 - #ifdef __KERNEL__ 14 - # include <linux/types.h> 15 - #else 16 - # include <stdint.h> 17 - #endif 18 - 19 - #include <linux/types_32_64.h> 13 + #include <linux/types.h> 14 + #include <asm/byteorder.h> 20 15 21 16 enum rseq_cpu_id_state { 22 17 RSEQ_CPU_ID_UNINITIALIZED = -1, ··· 47 52 __u32 version; 48 53 /* enum rseq_cs_flags */ 49 54 __u32 flags; 50 - LINUX_FIELD_u32_u64(start_ip); 55 + __u64 start_ip; 51 56 /* Offset from start_ip. */ 52 - LINUX_FIELD_u32_u64(post_commit_offset); 53 - LINUX_FIELD_u32_u64(abort_ip); 57 + __u64 post_commit_offset; 58 + __u64 abort_ip; 54 59 } __attribute__((aligned(4 * sizeof(__u64)))); 55 60 56 61 /* ··· 62 67 struct rseq { 63 68 /* 64 69 * Restartable sequences cpu_id_start field. Updated by the 65 - * kernel, and read by user-space with single-copy atomicity 66 - * semantics. Aligned on 32-bit. Always contains a value in the 67 - * range of possible CPUs, although the value may not be the 68 - * actual current CPU (e.g. if rseq is not initialized). This 69 - * CPU number value should always be compared against the value 70 - * of the cpu_id field before performing a rseq commit or 71 - * returning a value read from a data structure indexed using 72 - * the cpu_id_start value. 70 + * kernel. Read by user-space with single-copy atomicity 71 + * semantics. This field should only be read by the thread which 72 + * registered this data structure. Aligned on 32-bit. Always 73 + * contains a value in the range of possible CPUs, although the 74 + * value may not be the actual current CPU (e.g. if rseq is not 75 + * initialized). This CPU number value should always be compared 76 + * against the value of the cpu_id field before performing a rseq 77 + * commit or returning a value read from a data structure indexed 78 + * using the cpu_id_start value. 73 79 */ 74 80 __u32 cpu_id_start; 75 81 /* 76 - * Restartable sequences cpu_id field. Updated by the kernel, 77 - * and read by user-space with single-copy atomicity semantics. 78 - * Aligned on 32-bit. Values RSEQ_CPU_ID_UNINITIALIZED and 79 - * RSEQ_CPU_ID_REGISTRATION_FAILED have a special semantic: the 80 - * former means "rseq uninitialized", and latter means "rseq 81 - * initialization failed". This value is meant to be read within 82 - * rseq critical sections and compared with the cpu_id_start 83 - * value previously read, before performing the commit instruction, 84 - * or read and compared with the cpu_id_start value before returning 85 - * a value loaded from a data structure indexed using the 86 - * cpu_id_start value. 82 + * Restartable sequences cpu_id field. Updated by the kernel. 83 + * Read by user-space with single-copy atomicity semantics. This 84 + * field should only be read by the thread which registered this 85 + * data structure. Aligned on 32-bit. Values 86 + * RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED 87 + * have a special semantic: the former means "rseq uninitialized", 88 + * and latter means "rseq initialization failed". This value is 89 + * meant to be read within rseq critical sections and compared 90 + * with the cpu_id_start value previously read, before performing 91 + * the commit instruction, or read and compared with the 92 + * cpu_id_start value before returning a value loaded from a data 93 + * structure indexed using the cpu_id_start value. 87 94 */ 88 95 __u32 cpu_id; 89 96 /* ··· 102 105 * targeted by the rseq_cs. Also needs to be set to NULL by user-space 103 106 * before reclaiming memory that contains the targeted struct rseq_cs. 104 107 * 105 - * Read and set by the kernel with single-copy atomicity semantics. 106 - * Set by user-space with single-copy atomicity semantics. Aligned 107 - * on 64-bit. 108 + * Read and set by the kernel. Set by user-space with single-copy 109 + * atomicity semantics. This field should only be updated by the 110 + * thread which registered this data structure. Aligned on 64-bit. 108 111 */ 109 - LINUX_FIELD_u32_u64(rseq_cs); 112 + union { 113 + __u64 ptr64; 114 + #ifdef __LP64__ 115 + __u64 ptr; 116 + #else 117 + struct { 118 + #if (defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)) || defined(__BIG_ENDIAN) 119 + __u32 padding; /* Initialized to zero. */ 120 + __u32 ptr32; 121 + #else /* LITTLE */ 122 + __u32 ptr32; 123 + __u32 padding; /* Initialized to zero. */ 124 + #endif /* ENDIAN */ 125 + } ptr; 126 + #endif 127 + } rseq_cs; 128 + 110 129 /* 111 - * - RSEQ_DISABLE flag: 130 + * Restartable sequences flags field. 112 131 * 113 - * Fallback fast-track flag for single-stepping. 114 - * Set by user-space if lack of progress is detected. 115 - * Cleared by user-space after rseq finish. 116 - * Read by the kernel. 132 + * This field should only be updated by the thread which 133 + * registered this data structure. Read by the kernel. 134 + * Mainly used for single-stepping through rseq critical sections 135 + * with debuggers. 136 + * 117 137 * - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT 118 - * Inhibit instruction sequence block restart and event 119 - * counter increment on preemption for this thread. 138 + * Inhibit instruction sequence block restart on preemption 139 + * for this thread. 120 140 * - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL 121 - * Inhibit instruction sequence block restart and event 122 - * counter increment on signal delivery for this thread. 141 + * Inhibit instruction sequence block restart on signal 142 + * delivery for this thread. 123 143 * - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE 124 - * Inhibit instruction sequence block restart and event 125 - * counter increment on migration for this thread. 144 + * Inhibit instruction sequence block restart on migration for 145 + * this thread. 126 146 */ 127 147 __u32 flags; 128 148 } __attribute__((aligned(4 * sizeof(__u64))));
-50
include/uapi/linux/types_32_64.h
··· 1 - /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ 2 - #ifndef _UAPI_LINUX_TYPES_32_64_H 3 - #define _UAPI_LINUX_TYPES_32_64_H 4 - 5 - /* 6 - * linux/types_32_64.h 7 - * 8 - * Integer type declaration for pointers across 32-bit and 64-bit systems. 9 - * 10 - * Copyright (c) 2015-2018 Mathieu Desnoyers <mathieu.desnoyers@efficios.com> 11 - */ 12 - 13 - #ifdef __KERNEL__ 14 - # include <linux/types.h> 15 - #else 16 - # include <stdint.h> 17 - #endif 18 - 19 - #include <asm/byteorder.h> 20 - 21 - #ifdef __BYTE_ORDER 22 - # if (__BYTE_ORDER == __BIG_ENDIAN) 23 - # define LINUX_BYTE_ORDER_BIG_ENDIAN 24 - # else 25 - # define LINUX_BYTE_ORDER_LITTLE_ENDIAN 26 - # endif 27 - #else 28 - # ifdef __BIG_ENDIAN 29 - # define LINUX_BYTE_ORDER_BIG_ENDIAN 30 - # else 31 - # define LINUX_BYTE_ORDER_LITTLE_ENDIAN 32 - # endif 33 - #endif 34 - 35 - #ifdef __LP64__ 36 - # define LINUX_FIELD_u32_u64(field) __u64 field 37 - # define LINUX_FIELD_u32_u64_INIT_ONSTACK(field, v) field = (intptr_t)v 38 - #else 39 - # ifdef LINUX_BYTE_ORDER_BIG_ENDIAN 40 - # define LINUX_FIELD_u32_u64(field) __u32 field ## _padding, field 41 - # define LINUX_FIELD_u32_u64_INIT_ONSTACK(field, v) \ 42 - field ## _padding = 0, field = (intptr_t)v 43 - # else 44 - # define LINUX_FIELD_u32_u64(field) __u32 field, field ## _padding 45 - # define LINUX_FIELD_u32_u64_INIT_ONSTACK(field, v) \ 46 - field = (intptr_t)v, field ## _padding = 0 47 - # endif 48 - #endif 49 - 50 - #endif /* _UAPI_LINUX_TYPES_32_64_H */
+25 -16
kernel/rseq.c
··· 85 85 { 86 86 u32 cpu_id = raw_smp_processor_id(); 87 87 88 - if (__put_user(cpu_id, &t->rseq->cpu_id_start)) 88 + if (put_user(cpu_id, &t->rseq->cpu_id_start)) 89 89 return -EFAULT; 90 - if (__put_user(cpu_id, &t->rseq->cpu_id)) 90 + if (put_user(cpu_id, &t->rseq->cpu_id)) 91 91 return -EFAULT; 92 92 trace_rseq_update(t); 93 93 return 0; ··· 100 100 /* 101 101 * Reset cpu_id_start to its initial state (0). 102 102 */ 103 - if (__put_user(cpu_id_start, &t->rseq->cpu_id_start)) 103 + if (put_user(cpu_id_start, &t->rseq->cpu_id_start)) 104 104 return -EFAULT; 105 105 /* 106 106 * Reset cpu_id to RSEQ_CPU_ID_UNINITIALIZED, so any user coming 107 107 * in after unregistration can figure out that rseq needs to be 108 108 * registered again. 109 109 */ 110 - if (__put_user(cpu_id, &t->rseq->cpu_id)) 110 + if (put_user(cpu_id, &t->rseq->cpu_id)) 111 111 return -EFAULT; 112 112 return 0; 113 113 } ··· 115 115 static int rseq_get_rseq_cs(struct task_struct *t, struct rseq_cs *rseq_cs) 116 116 { 117 117 struct rseq_cs __user *urseq_cs; 118 - unsigned long ptr; 118 + u64 ptr; 119 119 u32 __user *usig; 120 120 u32 sig; 121 121 int ret; 122 122 123 - ret = __get_user(ptr, &t->rseq->rseq_cs); 124 - if (ret) 125 - return ret; 123 + if (copy_from_user(&ptr, &t->rseq->rseq_cs.ptr64, sizeof(ptr))) 124 + return -EFAULT; 126 125 if (!ptr) { 127 126 memset(rseq_cs, 0, sizeof(*rseq_cs)); 128 127 return 0; 129 128 } 130 - urseq_cs = (struct rseq_cs __user *)ptr; 129 + if (ptr >= TASK_SIZE) 130 + return -EINVAL; 131 + urseq_cs = (struct rseq_cs __user *)(unsigned long)ptr; 131 132 if (copy_from_user(rseq_cs, urseq_cs, sizeof(*rseq_cs))) 132 133 return -EFAULT; 133 - if (rseq_cs->version > 0) 134 - return -EINVAL; 135 134 135 + if (rseq_cs->start_ip >= TASK_SIZE || 136 + rseq_cs->start_ip + rseq_cs->post_commit_offset >= TASK_SIZE || 137 + rseq_cs->abort_ip >= TASK_SIZE || 138 + rseq_cs->version > 0) 139 + return -EINVAL; 140 + /* Check for overflow. */ 141 + if (rseq_cs->start_ip + rseq_cs->post_commit_offset < rseq_cs->start_ip) 142 + return -EINVAL; 136 143 /* Ensure that abort_ip is not in the critical section. */ 137 144 if (rseq_cs->abort_ip - rseq_cs->start_ip < rseq_cs->post_commit_offset) 138 145 return -EINVAL; 139 146 140 - usig = (u32 __user *)(rseq_cs->abort_ip - sizeof(u32)); 147 + usig = (u32 __user *)(unsigned long)(rseq_cs->abort_ip - sizeof(u32)); 141 148 ret = get_user(sig, usig); 142 149 if (ret) 143 150 return ret; ··· 153 146 printk_ratelimited(KERN_WARNING 154 147 "Possible attack attempt. Unexpected rseq signature 0x%x, expecting 0x%x (pid=%d, addr=%p).\n", 155 148 sig, current->rseq_sig, current->pid, usig); 156 - return -EPERM; 149 + return -EINVAL; 157 150 } 158 151 return 0; 159 152 } ··· 164 157 int ret; 165 158 166 159 /* Get thread flags. */ 167 - ret = __get_user(flags, &t->rseq->flags); 160 + ret = get_user(flags, &t->rseq->flags); 168 161 if (ret) 169 162 return ret; 170 163 ··· 202 195 * of code outside of the rseq assembly block. This performs 203 196 * a lazy clear of the rseq_cs field. 204 197 * 205 - * Set rseq_cs to NULL with single-copy atomicity. 198 + * Set rseq_cs to NULL. 206 199 */ 207 - return __put_user(0UL, &t->rseq->rseq_cs); 200 + if (clear_user(&t->rseq->rseq_cs.ptr64, sizeof(t->rseq->rseq_cs.ptr64))) 201 + return -EFAULT; 202 + return 0; 208 203 } 209 204 210 205 /*
+17 -7
tools/testing/selftests/rseq/rseq.h
··· 133 133 return cpu; 134 134 } 135 135 136 + static inline void rseq_clear_rseq_cs(void) 137 + { 138 + #ifdef __LP64__ 139 + __rseq_abi.rseq_cs.ptr = 0; 140 + #else 141 + __rseq_abi.rseq_cs.ptr.ptr32 = 0; 142 + #endif 143 + } 144 + 136 145 /* 137 - * rseq_prepare_unload() should be invoked by each thread using rseq_finish*() 138 - * at least once between their last rseq_finish*() and library unload of the 139 - * library defining the rseq critical section (struct rseq_cs). This also 140 - * applies to use of rseq in code generated by JIT: rseq_prepare_unload() 141 - * should be invoked at least once by each thread using rseq_finish*() before 142 - * reclaim of the memory holding the struct rseq_cs. 146 + * rseq_prepare_unload() should be invoked by each thread executing a rseq 147 + * critical section at least once between their last critical section and 148 + * library unload of the library defining the rseq critical section 149 + * (struct rseq_cs). This also applies to use of rseq in code generated by 150 + * JIT: rseq_prepare_unload() should be invoked at least once by each 151 + * thread executing a rseq critical section before reclaim of the memory 152 + * holding the struct rseq_cs. 143 153 */ 144 154 static inline void rseq_prepare_unload(void) 145 155 { 146 - __rseq_abi.rseq_cs = 0; 156 + rseq_clear_rseq_cs(); 147 157 } 148 158 149 159 #endif /* RSEQ_H_ */