diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2016-10-14 20:42:44 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2016-10-14 20:42:44 -0400 |
commit | 2692a71bbd40160165e89d5505c5c28144ec5a42 (patch) | |
tree | acaaf0f1a4942486109094acad37c29456aeda98 | |
parent | 7041c57709efdc1e31aaff663cfe17f0b21f4743 (diff) | |
parent | b065444286bed7ec49ee81c593a46f3031fbfc83 (diff) |
Merge branch 'work.uaccess' into for-linus
-rw-r--r-- | arch/alpha/include/asm/uaccess.h | 9 | ||||
-rw-r--r-- | arch/alpha/lib/copy_user.S | 16 | ||||
-rw-r--r-- | arch/alpha/lib/ev6-copy_user.S | 23 | ||||
-rw-r--r-- | arch/arc/kernel/signal.c | 8 | ||||
-rw-r--r-- | arch/arm/include/asm/uaccess.h | 11 | ||||
-rw-r--r-- | arch/arm/lib/copy_from_user.S | 9 | ||||
-rw-r--r-- | arch/arm64/include/asm/uaccess.h | 10 | ||||
-rw-r--r-- | arch/arm64/lib/copy_from_user.S | 7 | ||||
-rw-r--r-- | arch/blackfin/include/asm/uaccess.h | 32 |
9 files changed, 47 insertions, 78 deletions
diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 466e42e96bfa..94f587535dee 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h | |||
@@ -396,11 +396,12 @@ copy_to_user(void __user *to, const void *from, long n) | |||
396 | extern inline long | 396 | extern inline long |
397 | copy_from_user(void *to, const void __user *from, long n) | 397 | copy_from_user(void *to, const void __user *from, long n) |
398 | { | 398 | { |
399 | long res = n; | ||
399 | if (likely(__access_ok((unsigned long)from, n, get_fs()))) | 400 | if (likely(__access_ok((unsigned long)from, n, get_fs()))) |
400 | n = __copy_tofrom_user_nocheck(to, (__force void *)from, n); | 401 | res = __copy_from_user_inatomic(to, from, n); |
401 | else | 402 | if (unlikely(res)) |
402 | memset(to, 0, n); | 403 | memset(to + (n - res), 0, res); |
403 | return n; | 404 | return res; |
404 | } | 405 | } |
405 | 406 | ||
406 | extern void __do_clear_user(void); | 407 | extern void __do_clear_user(void); |
diff --git a/arch/alpha/lib/copy_user.S b/arch/alpha/lib/copy_user.S index 6f3fab9eb434..ac9c3766ba8c 100644 --- a/arch/alpha/lib/copy_user.S +++ b/arch/alpha/lib/copy_user.S | |||
@@ -124,22 +124,8 @@ $65: | |||
124 | bis $31,$31,$0 | 124 | bis $31,$31,$0 |
125 | $41: | 125 | $41: |
126 | $35: | 126 | $35: |
127 | $exitout: | ||
128 | ret $31,($28),1 | ||
129 | |||
130 | $exitin: | 127 | $exitin: |
131 | /* A stupid byte-by-byte zeroing of the rest of the output | 128 | $exitout: |
132 | buffer. This cures security holes by never leaving | ||
133 | random kernel data around to be copied elsewhere. */ | ||
134 | |||
135 | mov $0,$1 | ||
136 | $101: | ||
137 | EXO ( ldq_u $2,0($6) ) | ||
138 | subq $1,1,$1 | ||
139 | mskbl $2,$6,$2 | ||
140 | EXO ( stq_u $2,0($6) ) | ||
141 | addq $6,1,$6 | ||
142 | bgt $1,$101 | ||
143 | ret $31,($28),1 | 129 | ret $31,($28),1 |
144 | 130 | ||
145 | .end __copy_user | 131 | .end __copy_user |
diff --git a/arch/alpha/lib/ev6-copy_user.S b/arch/alpha/lib/ev6-copy_user.S index db42ffe9c350..c4d0689c3d26 100644 --- a/arch/alpha/lib/ev6-copy_user.S +++ b/arch/alpha/lib/ev6-copy_user.S | |||
@@ -227,33 +227,12 @@ $dirtyentry: | |||
227 | bgt $0,$onebyteloop # U .. .. .. : U L U L | 227 | bgt $0,$onebyteloop # U .. .. .. : U L U L |
228 | 228 | ||
229 | $zerolength: | 229 | $zerolength: |
230 | $exitin: | ||
230 | $exitout: # Destination for exception recovery(?) | 231 | $exitout: # Destination for exception recovery(?) |
231 | nop # .. .. .. E | 232 | nop # .. .. .. E |
232 | nop # .. .. E .. | 233 | nop # .. .. E .. |
233 | nop # .. E .. .. | 234 | nop # .. E .. .. |
234 | ret $31,($28),1 # L0 .. .. .. : L U L U | 235 | ret $31,($28),1 # L0 .. .. .. : L U L U |
235 | 236 | ||
236 | $exitin: | ||
237 | |||
238 | /* A stupid byte-by-byte zeroing of the rest of the output | ||
239 | buffer. This cures security holes by never leaving | ||
240 | random kernel data around to be copied elsewhere. */ | ||
241 | |||
242 | nop | ||
243 | nop | ||
244 | nop | ||
245 | mov $0,$1 | ||
246 | |||
247 | $101: | ||
248 | EXO ( stb $31,0($6) ) # L | ||
249 | subq $1,1,$1 # E | ||
250 | addq $6,1,$6 # E | ||
251 | bgt $1,$101 # U | ||
252 | |||
253 | nop | ||
254 | nop | ||
255 | nop | ||
256 | ret $31,($28),1 # L0 | ||
257 | |||
258 | .end __copy_user | 237 | .end __copy_user |
259 | 238 | ||
diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index 6cb3736b6b83..d347bbc086fe 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c | |||
@@ -107,13 +107,13 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) | |||
107 | struct user_regs_struct uregs; | 107 | struct user_regs_struct uregs; |
108 | 108 | ||
109 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); | 109 | err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set)); |
110 | if (!err) | ||
111 | set_current_blocked(&set); | ||
112 | |||
113 | err |= __copy_from_user(&uregs.scratch, | 110 | err |= __copy_from_user(&uregs.scratch, |
114 | &(sf->uc.uc_mcontext.regs.scratch), | 111 | &(sf->uc.uc_mcontext.regs.scratch), |
115 | sizeof(sf->uc.uc_mcontext.regs.scratch)); | 112 | sizeof(sf->uc.uc_mcontext.regs.scratch)); |
113 | if (err) | ||
114 | return err; | ||
116 | 115 | ||
116 | set_current_blocked(&set); | ||
117 | regs->bta = uregs.scratch.bta; | 117 | regs->bta = uregs.scratch.bta; |
118 | regs->lp_start = uregs.scratch.lp_start; | 118 | regs->lp_start = uregs.scratch.lp_start; |
119 | regs->lp_end = uregs.scratch.lp_end; | 119 | regs->lp_end = uregs.scratch.lp_end; |
@@ -138,7 +138,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) | |||
138 | regs->r0 = uregs.scratch.r0; | 138 | regs->r0 = uregs.scratch.r0; |
139 | regs->sp = uregs.scratch.sp; | 139 | regs->sp = uregs.scratch.sp; |
140 | 140 | ||
141 | return err; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static inline int is_do_ss_needed(unsigned int magic) | 144 | static inline int is_do_ss_needed(unsigned int magic) |
diff --git a/arch/arm/include/asm/uaccess.h b/arch/arm/include/asm/uaccess.h index a93c0f99acf7..1f59ea051bab 100644 --- a/arch/arm/include/asm/uaccess.h +++ b/arch/arm/include/asm/uaccess.h | |||
@@ -533,11 +533,12 @@ __clear_user(void __user *addr, unsigned long n) | |||
533 | 533 | ||
534 | static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) | 534 | static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) |
535 | { | 535 | { |
536 | if (access_ok(VERIFY_READ, from, n)) | 536 | unsigned long res = n; |
537 | n = __copy_from_user(to, from, n); | 537 | if (likely(access_ok(VERIFY_READ, from, n))) |
538 | else /* security hole - plug it */ | 538 | res = __copy_from_user(to, from, n); |
539 | memset(to, 0, n); | 539 | if (unlikely(res)) |
540 | return n; | 540 | memset(to + (n - res), 0, res); |
541 | return res; | ||
541 | } | 542 | } |
542 | 543 | ||
543 | static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) | 544 | static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) |
diff --git a/arch/arm/lib/copy_from_user.S b/arch/arm/lib/copy_from_user.S index 1512bebfbf1b..7a4b06049001 100644 --- a/arch/arm/lib/copy_from_user.S +++ b/arch/arm/lib/copy_from_user.S | |||
@@ -98,12 +98,9 @@ ENDPROC(arm_copy_from_user) | |||
98 | .pushsection .fixup,"ax" | 98 | .pushsection .fixup,"ax" |
99 | .align 0 | 99 | .align 0 |
100 | copy_abort_preamble | 100 | copy_abort_preamble |
101 | ldmfd sp!, {r1, r2} | 101 | ldmfd sp!, {r1, r2, r3} |
102 | sub r3, r0, r1 | 102 | sub r0, r0, r1 |
103 | rsb r1, r3, r2 | 103 | rsb r0, r0, r2 |
104 | str r1, [sp] | ||
105 | bl __memzero | ||
106 | ldr r0, [sp], #4 | ||
107 | copy_abort_end | 104 | copy_abort_end |
108 | .popsection | 105 | .popsection |
109 | 106 | ||
diff --git a/arch/arm64/include/asm/uaccess.h b/arch/arm64/include/asm/uaccess.h index c47257c91b77..bcaf6fba1b65 100644 --- a/arch/arm64/include/asm/uaccess.h +++ b/arch/arm64/include/asm/uaccess.h | |||
@@ -278,14 +278,16 @@ static inline unsigned long __must_check __copy_to_user(void __user *to, const v | |||
278 | 278 | ||
279 | static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) | 279 | static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) |
280 | { | 280 | { |
281 | unsigned long res = n; | ||
281 | kasan_check_write(to, n); | 282 | kasan_check_write(to, n); |
282 | 283 | ||
283 | if (access_ok(VERIFY_READ, from, n)) { | 284 | if (access_ok(VERIFY_READ, from, n)) { |
284 | check_object_size(to, n, false); | 285 | check_object_size(to, n, false); |
285 | n = __arch_copy_from_user(to, from, n); | 286 | res = __arch_copy_from_user(to, from, n); |
286 | } else /* security hole - plug it */ | 287 | } |
287 | memset(to, 0, n); | 288 | if (unlikely(res)) |
288 | return n; | 289 | memset(to + (n - res), 0, res); |
290 | return res; | ||
289 | } | 291 | } |
290 | 292 | ||
291 | static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) | 293 | static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) |
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S index 0b90497d4424..4fd67ea03bb0 100644 --- a/arch/arm64/lib/copy_from_user.S +++ b/arch/arm64/lib/copy_from_user.S | |||
@@ -79,11 +79,6 @@ ENDPROC(__arch_copy_from_user) | |||
79 | 79 | ||
80 | .section .fixup,"ax" | 80 | .section .fixup,"ax" |
81 | .align 2 | 81 | .align 2 |
82 | 9998: | 82 | 9998: sub x0, end, dst // bytes not copied |
83 | sub x0, end, dst | ||
84 | 9999: | ||
85 | strb wzr, [dst], #1 // zero remaining buffer space | ||
86 | cmp dst, end | ||
87 | b.lo 9999b | ||
88 | ret | 83 | ret |
89 | .previous | 84 | .previous |
diff --git a/arch/blackfin/include/asm/uaccess.h b/arch/blackfin/include/asm/uaccess.h index 0a2a70096d8b..0eff88aa6d6a 100644 --- a/arch/blackfin/include/asm/uaccess.h +++ b/arch/blackfin/include/asm/uaccess.h | |||
@@ -163,18 +163,29 @@ static inline int bad_user_access_length(void) | |||
163 | : "a" (__ptr(ptr))); \ | 163 | : "a" (__ptr(ptr))); \ |
164 | }) | 164 | }) |
165 | 165 | ||
166 | #define __copy_from_user(to, from, n) copy_from_user(to, from, n) | ||
167 | #define __copy_to_user(to, from, n) copy_to_user(to, from, n) | ||
168 | #define __copy_to_user_inatomic __copy_to_user | 166 | #define __copy_to_user_inatomic __copy_to_user |
169 | #define __copy_from_user_inatomic __copy_from_user | 167 | #define __copy_from_user_inatomic __copy_from_user |
170 | 168 | ||
171 | static inline unsigned long __must_check | 169 | static inline unsigned long __must_check |
170 | __copy_from_user(void *to, const void __user *from, unsigned long n) | ||
171 | { | ||
172 | memcpy(to, (const void __force *)from, n); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | static inline unsigned long __must_check | ||
177 | __copy_to_user(void __user *to, const void *from, unsigned long n) | ||
178 | { | ||
179 | memcpy((void __force *)to, from, n); | ||
180 | SSYNC(); | ||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static inline unsigned long __must_check | ||
172 | copy_from_user(void *to, const void __user *from, unsigned long n) | 185 | copy_from_user(void *to, const void __user *from, unsigned long n) |
173 | { | 186 | { |
174 | if (likely(access_ok(VERIFY_READ, from, n))) { | 187 | if (likely(access_ok(VERIFY_READ, from, n))) |
175 | memcpy(to, (const void __force *)from, n); | 188 | return __copy_from_user(to, from, n); |
176 | return 0; | ||
177 | } | ||
178 | memset(to, 0, n); | 189 | memset(to, 0, n); |
179 | return n; | 190 | return n; |
180 | } | 191 | } |
@@ -182,12 +193,9 @@ copy_from_user(void *to, const void __user *from, unsigned long n) | |||
182 | static inline unsigned long __must_check | 193 | static inline unsigned long __must_check |
183 | copy_to_user(void __user *to, const void *from, unsigned long n) | 194 | copy_to_user(void __user *to, const void *from, unsigned long n) |
184 | { | 195 | { |
185 | if (access_ok(VERIFY_WRITE, to, n)) | 196 | if (likely(access_ok(VERIFY_WRITE, to, n))) |
186 | memcpy((void __force *)to, from, n); | 197 | return __copy_to_user(to, from, n); |
187 | else | 198 | return n; |
188 | return n; | ||
189 | SSYNC(); | ||
190 | return 0; | ||
191 | } | 199 | } |
192 | 200 | ||
193 | /* | 201 | /* |