aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@zeniv.linux.org.uk>2016-10-14 20:42:44 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2016-10-14 20:42:44 -0400
commit2692a71bbd40160165e89d5505c5c28144ec5a42 (patch)
treeacaaf0f1a4942486109094acad37c29456aeda98
parent7041c57709efdc1e31aaff663cfe17f0b21f4743 (diff)
parentb065444286bed7ec49ee81c593a46f3031fbfc83 (diff)
Merge branch 'work.uaccess' into for-linus
-rw-r--r--arch/alpha/include/asm/uaccess.h9
-rw-r--r--arch/alpha/lib/copy_user.S16
-rw-r--r--arch/alpha/lib/ev6-copy_user.S23
-rw-r--r--arch/arc/kernel/signal.c8
-rw-r--r--arch/arm/include/asm/uaccess.h11
-rw-r--r--arch/arm/lib/copy_from_user.S9
-rw-r--r--arch/arm64/include/asm/uaccess.h10
-rw-r--r--arch/arm64/lib/copy_from_user.S7
-rw-r--r--arch/blackfin/include/asm/uaccess.h32
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)
396extern inline long 396extern inline long
397copy_from_user(void *to, const void __user *from, long n) 397copy_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
406extern void __do_clear_user(void); 407extern 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
144static inline int is_do_ss_needed(unsigned int magic) 144static 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
534static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) 534static 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
543static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) 544static 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
279static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n) 279static 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
291static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n) 293static 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
829998: 829998: sub x0, end, dst // bytes not copied
83 sub x0, end, dst
849999:
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
171static inline unsigned long __must_check 169static 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
176static 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
184static inline unsigned long __must_check
172copy_from_user(void *to, const void __user *from, unsigned long n) 185copy_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)
182static inline unsigned long __must_check 193static inline unsigned long __must_check
183copy_to_user(void __user *to, const void *from, unsigned long n) 194copy_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/*