Skip to content

Commit b26b5ef

Browse files
committed
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull more misc uaccess and vfs updates from Al Viro: "The rest of the stuff from -next (more uaccess work) + assorted fixes" * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs: score: traps: Add missing include file to fix build error fs/super.c: don't fool lockdep in freeze_super() and thaw_super() paths fs/super.c: fix race between freeze_super() and thaw_super() overlayfs: Fix setting IOP_XATTR flag iov_iter: kernel-doc import_iovec() and rw_copy_check_uvector() blackfin: no access_ok() for __copy_{to,from}_user() arm64: don't zero in __copy_from_user{,_inatomic} arm: don't zero in __copy_from_user_inatomic()/__copy_from_user() arc: don't leak bits of kernel stack into coredump alpha: get rid of tail-zeroing in __copy_user()
2 parents 87dbe42 + 2692a71 commit b26b5ef

14 files changed

Lines changed: 133 additions & 98 deletions

File tree

arch/alpha/include/asm/uaccess.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -396,11 +396,12 @@ copy_to_user(void __user *to, const void *from, long n)
396396
extern inline long
397397
copy_from_user(void *to, const void __user *from, long n)
398398
{
399+
long res = n;
399400
if (likely(__access_ok((unsigned long)from, n, get_fs())))
400-
n = __copy_tofrom_user_nocheck(to, (__force void *)from, n);
401-
else
402-
memset(to, 0, n);
403-
return n;
401+
res = __copy_from_user_inatomic(to, from, n);
402+
if (unlikely(res))
403+
memset(to + (n - res), 0, res);
404+
return res;
404405
}
405406

406407
extern void __do_clear_user(void);

arch/alpha/lib/copy_user.S

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -126,22 +126,8 @@ $65:
126126
bis $31,$31,$0
127127
$41:
128128
$35:
129-
$exitout:
130-
ret $31,($28),1
131-
132129
$exitin:
133-
/* A stupid byte-by-byte zeroing of the rest of the output
134-
buffer. This cures security holes by never leaving
135-
random kernel data around to be copied elsewhere. */
136-
137-
mov $0,$1
138-
$101:
139-
EXO ( ldq_u $2,0($6) )
140-
subq $1,1,$1
141-
mskbl $2,$6,$2
142-
EXO ( stq_u $2,0($6) )
143-
addq $6,1,$6
144-
bgt $1,$101
130+
$exitout:
145131
ret $31,($28),1
146132

147133
.end __copy_user

arch/alpha/lib/ev6-copy_user.S

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -228,33 +228,12 @@ $dirtyentry:
228228
bgt $0,$onebyteloop # U .. .. .. : U L U L
229229

230230
$zerolength:
231+
$exitin:
231232
$exitout: # Destination for exception recovery(?)
232233
nop # .. .. .. E
233234
nop # .. .. E ..
234235
nop # .. E .. ..
235236
ret $31,($28),1 # L0 .. .. .. : L U L U
236237

237-
$exitin:
238-
239-
/* A stupid byte-by-byte zeroing of the rest of the output
240-
buffer. This cures security holes by never leaving
241-
random kernel data around to be copied elsewhere. */
242-
243-
nop
244-
nop
245-
nop
246-
mov $0,$1
247-
248-
$101:
249-
EXO ( stb $31,0($6) ) # L
250-
subq $1,1,$1 # E
251-
addq $6,1,$6 # E
252-
bgt $1,$101 # U
253-
254-
nop
255-
nop
256-
nop
257-
ret $31,($28),1 # L0
258-
259238
.end __copy_user
260239
EXPORT_SYMBOL(__copy_user)

arch/arc/kernel/signal.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -107,13 +107,13 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf)
107107
struct user_regs_struct uregs;
108108

109109
err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
110-
if (!err)
111-
set_current_blocked(&set);
112-
113110
err |= __copy_from_user(&uregs.scratch,
114111
&(sf->uc.uc_mcontext.regs.scratch),
115112
sizeof(sf->uc.uc_mcontext.regs.scratch));
113+
if (err)
114+
return err;
116115

116+
set_current_blocked(&set);
117117
regs->bta = uregs.scratch.bta;
118118
regs->lp_start = uregs.scratch.lp_start;
119119
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)
138138
regs->r0 = uregs.scratch.r0;
139139
regs->sp = uregs.scratch.sp;
140140

141-
return err;
141+
return 0;
142142
}
143143

144144
static inline int is_do_ss_needed(unsigned int magic)

arch/arm/include/asm/uaccess.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -533,11 +533,12 @@ __clear_user(void __user *addr, unsigned long n)
533533

534534
static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
535535
{
536-
if (access_ok(VERIFY_READ, from, n))
537-
n = __copy_from_user(to, from, n);
538-
else /* security hole - plug it */
539-
memset(to, 0, n);
540-
return n;
536+
unsigned long res = n;
537+
if (likely(access_ok(VERIFY_READ, from, n)))
538+
res = __copy_from_user(to, from, n);
539+
if (unlikely(res))
540+
memset(to + (n - res), 0, res);
541+
return res;
541542
}
542543

543544
static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)

arch/arm/lib/copy_from_user.S

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,12 +100,9 @@ EXPORT_SYMBOL(arm_copy_from_user)
100100
.pushsection .fixup,"ax"
101101
.align 0
102102
copy_abort_preamble
103-
ldmfd sp!, {r1, r2}
104-
sub r3, r0, r1
105-
rsb r1, r3, r2
106-
str r1, [sp]
107-
bl __memzero
108-
ldr r0, [sp], #4
103+
ldmfd sp!, {r1, r2, r3}
104+
sub r0, r0, r1
105+
rsb r0, r0, r2
109106
copy_abort_end
110107
.popsection
111108

arch/arm64/include/asm/uaccess.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,14 +278,16 @@ static inline unsigned long __must_check __copy_to_user(void __user *to, const v
278278

279279
static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
280280
{
281+
unsigned long res = n;
281282
kasan_check_write(to, n);
282283

283284
if (access_ok(VERIFY_READ, from, n)) {
284285
check_object_size(to, n, false);
285-
n = __arch_copy_from_user(to, from, n);
286-
} else /* security hole - plug it */
287-
memset(to, 0, n);
288-
return n;
286+
res = __arch_copy_from_user(to, from, n);
287+
}
288+
if (unlikely(res))
289+
memset(to + (n - res), 0, res);
290+
return res;
289291
}
290292

291293
static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)

arch/arm64/lib/copy_from_user.S

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,11 +79,6 @@ ENDPROC(__arch_copy_from_user)
7979

8080
.section .fixup,"ax"
8181
.align 2
82-
9998:
83-
sub x0, end, dst
84-
9999:
85-
strb wzr, [dst], #1 // zero remaining buffer space
86-
cmp dst, end
87-
b.lo 9999b
82+
9998: sub x0, end, dst // bytes not copied
8883
ret
8984
.previous

arch/blackfin/include/asm/uaccess.h

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,31 +163,39 @@ static inline int bad_user_access_length(void)
163163
: "a" (__ptr(ptr))); \
164164
})
165165

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)
168166
#define __copy_to_user_inatomic __copy_to_user
169167
#define __copy_from_user_inatomic __copy_from_user
170168

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+
171184
static inline unsigned long __must_check
172185
copy_from_user(void *to, const void __user *from, unsigned long n)
173186
{
174-
if (likely(access_ok(VERIFY_READ, from, n))) {
175-
memcpy(to, (const void __force *)from, n);
176-
return 0;
177-
}
187+
if (likely(access_ok(VERIFY_READ, from, n)))
188+
return __copy_from_user(to, from, n);
178189
memset(to, 0, n);
179190
return n;
180191
}
181192

182193
static inline unsigned long __must_check
183194
copy_to_user(void __user *to, const void *from, unsigned long n)
184195
{
185-
if (access_ok(VERIFY_WRITE, to, n))
186-
memcpy((void __force *)to, from, n);
187-
else
188-
return n;
189-
SSYNC();
190-
return 0;
196+
if (likely(access_ok(VERIFY_WRITE, to, n)))
197+
return __copy_to_user(to, from, n);
198+
return n;
191199
}
192200

193201
/*

arch/score/kernel/traps.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include <asm/cacheflush.h>
3030
#include <asm/irq.h>
3131
#include <asm/irq_regs.h>
32+
#include <asm/uaccess.h>
3233

3334
unsigned long exception_handlers[32];
3435

0 commit comments

Comments
 (0)