diff options
32 files changed, 508 insertions, 821 deletions
diff --git a/arch/mips/include/asm/compat-signal.h b/arch/mips/include/asm/compat-signal.h index e87cd243b0f4..c3b7a2550d1d 100644 --- a/arch/mips/include/asm/compat-signal.h +++ b/arch/mips/include/asm/compat-signal.h | |||
@@ -14,45 +14,16 @@ | |||
14 | static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, | 14 | static inline int __copy_conv_sigset_to_user(compat_sigset_t __user *d, |
15 | const sigset_t *s) | 15 | const sigset_t *s) |
16 | { | 16 | { |
17 | int err; | 17 | BUILD_BUG_ON(sizeof(*d) != sizeof(*s)); |
18 | BUILD_BUG_ON(_NSIG_WORDS != 2); | ||
18 | 19 | ||
19 | BUG_ON(sizeof(*d) != sizeof(*s)); | 20 | return put_compat_sigset(d, s, sizeof(*d)); |
20 | BUG_ON(_NSIG_WORDS != 2); | ||
21 | |||
22 | err = __put_user(s->sig[0], &d->sig[0]); | ||
23 | err |= __put_user(s->sig[0] >> 32, &d->sig[1]); | ||
24 | err |= __put_user(s->sig[1], &d->sig[2]); | ||
25 | err |= __put_user(s->sig[1] >> 32, &d->sig[3]); | ||
26 | |||
27 | return err; | ||
28 | } | 21 | } |
29 | 22 | ||
30 | static inline int __copy_conv_sigset_from_user(sigset_t *d, | 23 | static inline int __copy_conv_sigset_from_user(sigset_t *d, |
31 | const compat_sigset_t __user *s) | 24 | const compat_sigset_t __user *s) |
32 | { | 25 | { |
33 | int err; | 26 | return get_compat_sigset(d, s); |
34 | union sigset_u { | ||
35 | sigset_t s; | ||
36 | compat_sigset_t c; | ||
37 | } *u = (union sigset_u *) d; | ||
38 | |||
39 | BUG_ON(sizeof(*d) != sizeof(*s)); | ||
40 | BUG_ON(_NSIG_WORDS != 2); | ||
41 | |||
42 | #ifdef CONFIG_CPU_BIG_ENDIAN | ||
43 | err = __get_user(u->c.sig[1], &s->sig[0]); | ||
44 | err |= __get_user(u->c.sig[0], &s->sig[1]); | ||
45 | err |= __get_user(u->c.sig[3], &s->sig[2]); | ||
46 | err |= __get_user(u->c.sig[2], &s->sig[3]); | ||
47 | #endif | ||
48 | #ifdef CONFIG_CPU_LITTLE_ENDIAN | ||
49 | err = __get_user(u->c.sig[0], &s->sig[0]); | ||
50 | err |= __get_user(u->c.sig[1], &s->sig[1]); | ||
51 | err |= __get_user(u->c.sig[2], &s->sig[2]); | ||
52 | err |= __get_user(u->c.sig[3], &s->sig[3]); | ||
53 | #endif | ||
54 | |||
55 | return err; | ||
56 | } | 27 | } |
57 | 28 | ||
58 | #endif /* __ASM_COMPAT_SIGNAL_H */ | 29 | #endif /* __ASM_COMPAT_SIGNAL_H */ |
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c index f2a4038e275b..342073f44d3f 100644 --- a/arch/parisc/kernel/signal.c +++ b/arch/parisc/kernel/signal.c | |||
@@ -93,7 +93,6 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
93 | unsigned long usp = (regs->gr[30] & ~(0x01UL)); | 93 | unsigned long usp = (regs->gr[30] & ~(0x01UL)); |
94 | unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE; | 94 | unsigned long sigframe_size = PARISC_RT_SIGFRAME_SIZE; |
95 | #ifdef CONFIG_64BIT | 95 | #ifdef CONFIG_64BIT |
96 | compat_sigset_t compat_set; | ||
97 | struct compat_rt_sigframe __user * compat_frame; | 96 | struct compat_rt_sigframe __user * compat_frame; |
98 | 97 | ||
99 | if (is_compat_task()) | 98 | if (is_compat_task()) |
@@ -114,9 +113,8 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall) | |||
114 | 113 | ||
115 | if (is_compat_task()) { | 114 | if (is_compat_task()) { |
116 | DBG(2,"sys_rt_sigreturn: ELF32 process.\n"); | 115 | DBG(2,"sys_rt_sigreturn: ELF32 process.\n"); |
117 | if (__copy_from_user(&compat_set, &compat_frame->uc.uc_sigmask, sizeof(compat_set))) | 116 | if (get_compat_sigset(&set, &compat_frame->uc.uc_sigmask)) |
118 | goto give_sigsegv; | 117 | goto give_sigsegv; |
119 | sigset_32to64(&set,&compat_set); | ||
120 | } else | 118 | } else |
121 | #endif | 119 | #endif |
122 | { | 120 | { |
@@ -238,7 +236,6 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, | |||
238 | int err = 0; | 236 | int err = 0; |
239 | #ifdef CONFIG_64BIT | 237 | #ifdef CONFIG_64BIT |
240 | struct compat_rt_sigframe __user * compat_frame; | 238 | struct compat_rt_sigframe __user * compat_frame; |
241 | compat_sigset_t compat_set; | ||
242 | #endif | 239 | #endif |
243 | 240 | ||
244 | usp = (regs->gr[30] & ~(0x01UL)); | 241 | usp = (regs->gr[30] & ~(0x01UL)); |
@@ -261,8 +258,8 @@ setup_rt_frame(struct ksignal *ksig, sigset_t *set, struct pt_regs *regs, | |||
261 | DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext); | 258 | DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &compat_frame->uc.uc_mcontext); |
262 | err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, | 259 | err |= setup_sigcontext32(&compat_frame->uc.uc_mcontext, |
263 | &compat_frame->regs, regs, in_syscall); | 260 | &compat_frame->regs, regs, in_syscall); |
264 | sigset_64to32(&compat_set,set); | 261 | err |= put_compat_sigset(&compat_frame->uc.uc_sigmask, set, |
265 | err |= __copy_to_user(&compat_frame->uc.uc_sigmask, &compat_set, sizeof(compat_set)); | 262 | sizeof(compat_sigset_t)); |
266 | } else | 263 | } else |
267 | #endif | 264 | #endif |
268 | { | 265 | { |
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c index 9e0cb6a577d6..41afa9cd1f55 100644 --- a/arch/parisc/kernel/signal32.c +++ b/arch/parisc/kernel/signal32.c | |||
@@ -46,19 +46,6 @@ | |||
46 | #define DBG(LEVEL, ...) | 46 | #define DBG(LEVEL, ...) |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | inline void | ||
50 | sigset_32to64(sigset_t *s64, compat_sigset_t *s32) | ||
51 | { | ||
52 | s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32); | ||
53 | } | ||
54 | |||
55 | inline void | ||
56 | sigset_64to32(compat_sigset_t *s32, sigset_t *s64) | ||
57 | { | ||
58 | s32->sig[0] = s64->sig[0] & 0xffffffffUL; | ||
59 | s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL; | ||
60 | } | ||
61 | |||
62 | long | 49 | long |
63 | restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, | 50 | restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, |
64 | struct pt_regs *regs) | 51 | struct pt_regs *regs) |
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h index af51d4ccee42..719e7417732c 100644 --- a/arch/parisc/kernel/signal32.h +++ b/arch/parisc/kernel/signal32.h | |||
@@ -79,8 +79,6 @@ struct compat_rt_sigframe { | |||
79 | #define FUNCTIONCALLFRAME32 48 | 79 | #define FUNCTIONCALLFRAME32 48 |
80 | #define PARISC_RT_SIGFRAME_SIZE32 (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32) | 80 | #define PARISC_RT_SIGFRAME_SIZE32 (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32) |
81 | 81 | ||
82 | void sigset_32to64(sigset_t *s64, compat_sigset_t *s32); | ||
83 | void sigset_64to32(compat_sigset_t *s32, sigset_t *s64); | ||
84 | long restore_sigcontext32(struct compat_sigcontext __user *sc, | 82 | long restore_sigcontext32(struct compat_sigcontext __user *sc, |
85 | struct compat_regfile __user *rf, | 83 | struct compat_regfile __user *rf, |
86 | struct pt_regs *regs); | 84 | struct pt_regs *regs); |
diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 16d16583cf11..9ffd73296f64 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c | |||
@@ -94,40 +94,13 @@ | |||
94 | */ | 94 | */ |
95 | static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) | 95 | static inline int put_sigset_t(compat_sigset_t __user *uset, sigset_t *set) |
96 | { | 96 | { |
97 | compat_sigset_t cset; | 97 | return put_compat_sigset(uset, set, sizeof(*uset)); |
98 | |||
99 | switch (_NSIG_WORDS) { | ||
100 | case 4: cset.sig[6] = set->sig[3] & 0xffffffffull; | ||
101 | cset.sig[7] = set->sig[3] >> 32; | ||
102 | case 3: cset.sig[4] = set->sig[2] & 0xffffffffull; | ||
103 | cset.sig[5] = set->sig[2] >> 32; | ||
104 | case 2: cset.sig[2] = set->sig[1] & 0xffffffffull; | ||
105 | cset.sig[3] = set->sig[1] >> 32; | ||
106 | case 1: cset.sig[0] = set->sig[0] & 0xffffffffull; | ||
107 | cset.sig[1] = set->sig[0] >> 32; | ||
108 | } | ||
109 | return copy_to_user(uset, &cset, sizeof(*uset)); | ||
110 | } | 98 | } |
111 | 99 | ||
112 | static inline int get_sigset_t(sigset_t *set, | 100 | static inline int get_sigset_t(sigset_t *set, |
113 | const compat_sigset_t __user *uset) | 101 | const compat_sigset_t __user *uset) |
114 | { | 102 | { |
115 | compat_sigset_t s32; | 103 | return get_compat_sigset(set, uset); |
116 | |||
117 | if (copy_from_user(&s32, uset, sizeof(*uset))) | ||
118 | return -EFAULT; | ||
119 | |||
120 | /* | ||
121 | * Swap the 2 words of the 64-bit sigset_t (they are stored | ||
122 | * in the "wrong" endian in 32-bit user storage). | ||
123 | */ | ||
124 | switch (_NSIG_WORDS) { | ||
125 | case 4: set->sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32); | ||
126 | case 3: set->sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32); | ||
127 | case 2: set->sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32); | ||
128 | case 1: set->sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32); | ||
129 | } | ||
130 | return 0; | ||
131 | } | 104 | } |
132 | 105 | ||
133 | #define to_user_ptr(p) ptr_to_compat(p) | 106 | #define to_user_ptr(p) ptr_to_compat(p) |
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c index a4a1208e3df3..ef246940b44c 100644 --- a/arch/s390/kernel/compat_signal.c +++ b/arch/s390/kernel/compat_signal.c | |||
@@ -50,19 +50,6 @@ typedef struct | |||
50 | struct ucontext32 uc; | 50 | struct ucontext32 uc; |
51 | } rt_sigframe32; | 51 | } rt_sigframe32; |
52 | 52 | ||
53 | static inline void sigset_to_sigset32(unsigned long *set64, | ||
54 | compat_sigset_word *set32) | ||
55 | { | ||
56 | set32[0] = (compat_sigset_word) set64[0]; | ||
57 | set32[1] = (compat_sigset_word)(set64[0] >> 32); | ||
58 | } | ||
59 | |||
60 | static inline void sigset32_to_sigset(compat_sigset_word *set32, | ||
61 | unsigned long *set64) | ||
62 | { | ||
63 | set64[0] = (unsigned long) set32[0] | ((unsigned long) set32[1] << 32); | ||
64 | } | ||
65 | |||
66 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) | 53 | int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from) |
67 | { | 54 | { |
68 | int err; | 55 | int err; |
@@ -294,12 +281,10 @@ COMPAT_SYSCALL_DEFINE0(sigreturn) | |||
294 | { | 281 | { |
295 | struct pt_regs *regs = task_pt_regs(current); | 282 | struct pt_regs *regs = task_pt_regs(current); |
296 | sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; | 283 | sigframe32 __user *frame = (sigframe32 __user *)regs->gprs[15]; |
297 | compat_sigset_t cset; | ||
298 | sigset_t set; | 284 | sigset_t set; |
299 | 285 | ||
300 | if (__copy_from_user(&cset.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32)) | 286 | if (get_compat_sigset(&set, (compat_sigset_t __user *)frame->sc.oldmask)) |
301 | goto badframe; | 287 | goto badframe; |
302 | sigset32_to_sigset(cset.sig, set.sig); | ||
303 | set_current_blocked(&set); | 288 | set_current_blocked(&set); |
304 | save_fpu_regs(); | 289 | save_fpu_regs(); |
305 | if (restore_sigregs32(regs, &frame->sregs)) | 290 | if (restore_sigregs32(regs, &frame->sregs)) |
@@ -317,12 +302,10 @@ COMPAT_SYSCALL_DEFINE0(rt_sigreturn) | |||
317 | { | 302 | { |
318 | struct pt_regs *regs = task_pt_regs(current); | 303 | struct pt_regs *regs = task_pt_regs(current); |
319 | rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; | 304 | rt_sigframe32 __user *frame = (rt_sigframe32 __user *)regs->gprs[15]; |
320 | compat_sigset_t cset; | ||
321 | sigset_t set; | 305 | sigset_t set; |
322 | 306 | ||
323 | if (__copy_from_user(&cset, &frame->uc.uc_sigmask, sizeof(cset))) | 307 | if (get_compat_sigset(&set, &frame->uc.uc_sigmask)) |
324 | goto badframe; | 308 | goto badframe; |
325 | sigset32_to_sigset(cset.sig, set.sig); | ||
326 | set_current_blocked(&set); | 309 | set_current_blocked(&set); |
327 | if (compat_restore_altstack(&frame->uc.uc_stack)) | 310 | if (compat_restore_altstack(&frame->uc.uc_stack)) |
328 | goto badframe; | 311 | goto badframe; |
@@ -372,7 +355,6 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, | |||
372 | { | 355 | { |
373 | int sig = ksig->sig; | 356 | int sig = ksig->sig; |
374 | sigframe32 __user *frame; | 357 | sigframe32 __user *frame; |
375 | struct sigcontext32 sc; | ||
376 | unsigned long restorer; | 358 | unsigned long restorer; |
377 | size_t frame_size; | 359 | size_t frame_size; |
378 | 360 | ||
@@ -394,9 +376,10 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, | |||
394 | return -EFAULT; | 376 | return -EFAULT; |
395 | 377 | ||
396 | /* Create struct sigcontext32 on the signal stack */ | 378 | /* Create struct sigcontext32 on the signal stack */ |
397 | sigset_to_sigset32(set->sig, sc.oldmask); | 379 | if (put_compat_sigset((compat_sigset_t __user *)frame->sc.oldmask, |
398 | sc.sregs = (__u32)(unsigned long __force) &frame->sregs; | 380 | set, sizeof(compat_sigset_t))) |
399 | if (__copy_to_user(&frame->sc, &sc, sizeof(frame->sc))) | 381 | return -EFAULT; |
382 | if (__put_user(ptr_to_compat(&frame->sc), &frame->sc.sregs)) | ||
400 | return -EFAULT; | 383 | return -EFAULT; |
401 | 384 | ||
402 | /* Store registers needed to create the signal frame */ | 385 | /* Store registers needed to create the signal frame */ |
@@ -455,7 +438,6 @@ static int setup_frame32(struct ksignal *ksig, sigset_t *set, | |||
455 | static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, | 438 | static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, |
456 | struct pt_regs *regs) | 439 | struct pt_regs *regs) |
457 | { | 440 | { |
458 | compat_sigset_t cset; | ||
459 | rt_sigframe32 __user *frame; | 441 | rt_sigframe32 __user *frame; |
460 | unsigned long restorer; | 442 | unsigned long restorer; |
461 | size_t frame_size; | 443 | size_t frame_size; |
@@ -502,12 +484,11 @@ static int setup_rt_frame32(struct ksignal *ksig, sigset_t *set, | |||
502 | store_sigregs(); | 484 | store_sigregs(); |
503 | 485 | ||
504 | /* Create ucontext on the signal stack. */ | 486 | /* Create ucontext on the signal stack. */ |
505 | sigset_to_sigset32(set->sig, cset.sig); | ||
506 | if (__put_user(uc_flags, &frame->uc.uc_flags) || | 487 | if (__put_user(uc_flags, &frame->uc.uc_flags) || |
507 | __put_user(0, &frame->uc.uc_link) || | 488 | __put_user(0, &frame->uc.uc_link) || |
508 | __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) || | 489 | __compat_save_altstack(&frame->uc.uc_stack, regs->gprs[15]) || |
509 | save_sigregs32(regs, &frame->uc.uc_mcontext) || | 490 | save_sigregs32(regs, &frame->uc.uc_mcontext) || |
510 | __copy_to_user(&frame->uc.uc_sigmask, &cset, sizeof(cset)) || | 491 | put_compat_sigset(&frame->uc.uc_sigmask, set, sizeof(compat_sigset_t)) || |
511 | save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext)) | 492 | save_sigregs_ext32(regs, &frame->uc.uc_mcontext_ext)) |
512 | return -EFAULT; | 493 | return -EFAULT; |
513 | 494 | ||
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 5c572de64c74..54a6159b9cd8 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c | |||
@@ -249,7 +249,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) | |||
249 | compat_uptr_t fpu_save; | 249 | compat_uptr_t fpu_save; |
250 | compat_uptr_t rwin_save; | 250 | compat_uptr_t rwin_save; |
251 | sigset_t set; | 251 | sigset_t set; |
252 | compat_sigset_t seta; | ||
253 | int err, i; | 252 | int err, i; |
254 | 253 | ||
255 | /* Always make any pending restarted system calls return -EINTR */ | 254 | /* Always make any pending restarted system calls return -EINTR */ |
@@ -312,7 +311,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) | |||
312 | err |= __get_user(fpu_save, &sf->fpu_save); | 311 | err |= __get_user(fpu_save, &sf->fpu_save); |
313 | if (!err && fpu_save) | 312 | if (!err && fpu_save) |
314 | err |= restore_fpu_state(regs, compat_ptr(fpu_save)); | 313 | err |= restore_fpu_state(regs, compat_ptr(fpu_save)); |
315 | err |= copy_from_user(&seta, &sf->mask, sizeof(compat_sigset_t)); | 314 | err |= get_compat_sigset(&set, &sf->mask); |
316 | err |= compat_restore_altstack(&sf->stack); | 315 | err |= compat_restore_altstack(&sf->stack); |
317 | if (err) | 316 | if (err) |
318 | goto segv; | 317 | goto segv; |
@@ -323,7 +322,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) | |||
323 | goto segv; | 322 | goto segv; |
324 | } | 323 | } |
325 | 324 | ||
326 | set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); | ||
327 | set_current_blocked(&set); | 325 | set_current_blocked(&set); |
328 | return; | 326 | return; |
329 | segv: | 327 | segv: |
@@ -555,7 +553,6 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs, | |||
555 | void __user *tail; | 553 | void __user *tail; |
556 | int sigframe_size; | 554 | int sigframe_size; |
557 | u32 psr; | 555 | u32 psr; |
558 | compat_sigset_t seta; | ||
559 | 556 | ||
560 | /* 1. Make sure everything is clean */ | 557 | /* 1. Make sure everything is clean */ |
561 | synchronize_user_stack(); | 558 | synchronize_user_stack(); |
@@ -625,9 +622,7 @@ static int setup_rt_frame32(struct ksignal *ksig, struct pt_regs *regs, | |||
625 | /* Setup sigaltstack */ | 622 | /* Setup sigaltstack */ |
626 | err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]); | 623 | err |= __compat_save_altstack(&sf->stack, regs->u_regs[UREG_FP]); |
627 | 624 | ||
628 | seta.sig[1] = (oldset->sig[0] >> 32); | 625 | err |= put_compat_sigset(&sf->mask, oldset, sizeof(compat_sigset_t)); |
629 | seta.sig[0] = oldset->sig[0]; | ||
630 | err |= __copy_to_user(&sf->mask, &seta, sizeof(compat_sigset_t)); | ||
631 | 626 | ||
632 | if (!wsaved) { | 627 | if (!wsaved) { |
633 | err |= copy_in_user((u32 __user *)sf, | 628 | err |= copy_in_user((u32 __user *)sf, |
diff --git a/arch/sparc/kernel/sys_sparc32.c b/arch/sparc/kernel/sys_sparc32.c index b4e1478413a1..6d964bdefbaa 100644 --- a/arch/sparc/kernel/sys_sparc32.c +++ b/arch/sparc/kernel/sys_sparc32.c | |||
@@ -160,7 +160,6 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, | |||
160 | { | 160 | { |
161 | struct k_sigaction new_ka, old_ka; | 161 | struct k_sigaction new_ka, old_ka; |
162 | int ret; | 162 | int ret; |
163 | compat_sigset_t set32; | ||
164 | 163 | ||
165 | /* XXX: Don't preclude handling different sized sigset_t's. */ | 164 | /* XXX: Don't preclude handling different sized sigset_t's. */ |
166 | if (sigsetsize != sizeof(compat_sigset_t)) | 165 | if (sigsetsize != sizeof(compat_sigset_t)) |
@@ -172,8 +171,7 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, | |||
172 | new_ka.ka_restorer = restorer; | 171 | new_ka.ka_restorer = restorer; |
173 | ret = get_user(u_handler, &act->sa_handler); | 172 | ret = get_user(u_handler, &act->sa_handler); |
174 | new_ka.sa.sa_handler = compat_ptr(u_handler); | 173 | new_ka.sa.sa_handler = compat_ptr(u_handler); |
175 | ret |= copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)); | 174 | ret |= get_compat_sigset(&new_ka.sa.sa_mask, &act->sa_mask); |
176 | sigset_from_compat(&new_ka.sa.sa_mask, &set32); | ||
177 | ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); | 175 | ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); |
178 | ret |= get_user(u_restorer, &act->sa_restorer); | 176 | ret |= get_user(u_restorer, &act->sa_restorer); |
179 | new_ka.sa.sa_restorer = compat_ptr(u_restorer); | 177 | new_ka.sa.sa_restorer = compat_ptr(u_restorer); |
@@ -184,9 +182,9 @@ COMPAT_SYSCALL_DEFINE5(rt_sigaction, int, sig, | |||
184 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | 182 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); |
185 | 183 | ||
186 | if (!ret && oact) { | 184 | if (!ret && oact) { |
187 | sigset_to_compat(&set32, &old_ka.sa.sa_mask); | ||
188 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); | 185 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler); |
189 | ret |= copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t)); | 186 | ret |= put_compat_sigset(&oact->sa_mask, &old_ka.sa.sa_mask, |
187 | sizeof(oact->sa_mask)); | ||
190 | ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); | 188 | ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
191 | ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); | 189 | ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer); |
192 | if (ret) | 190 | if (ret) |
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c index 70d434bc1cbf..c4ef73c6f455 100644 --- a/drivers/char/ipmi/bt-bmc.c +++ b/drivers/char/ipmi/bt-bmc.c | |||
@@ -204,9 +204,6 @@ static ssize_t bt_bmc_read(struct file *file, char __user *buf, | |||
204 | ssize_t ret = 0; | 204 | ssize_t ret = 0; |
205 | ssize_t nread; | 205 | ssize_t nread; |
206 | 206 | ||
207 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
208 | return -EFAULT; | ||
209 | |||
210 | WARN_ON(*ppos); | 207 | WARN_ON(*ppos); |
211 | 208 | ||
212 | if (wait_event_interruptible(bt_bmc->queue, | 209 | if (wait_event_interruptible(bt_bmc->queue, |
@@ -277,9 +274,6 @@ static ssize_t bt_bmc_write(struct file *file, const char __user *buf, | |||
277 | if (count < 5) | 274 | if (count < 5) |
278 | return -EINVAL; | 275 | return -EINVAL; |
279 | 276 | ||
280 | if (!access_ok(VERIFY_READ, buf, count)) | ||
281 | return -EFAULT; | ||
282 | |||
283 | WARN_ON(*ppos); | 277 | WARN_ON(*ppos); |
284 | 278 | ||
285 | /* | 279 | /* |
diff --git a/drivers/gpu/drm/r128/r128_drv.h b/drivers/gpu/drm/r128/r128_drv.h index 09143b840482..2de40d276116 100644 --- a/drivers/gpu/drm/r128/r128_drv.h +++ b/drivers/gpu/drm/r128/r128_drv.h | |||
@@ -147,6 +147,10 @@ extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file | |||
147 | extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); | 147 | extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); |
148 | extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); | 148 | extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); |
149 | 149 | ||
150 | extern int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
151 | extern int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
152 | extern int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv); | ||
153 | |||
150 | extern void r128_freelist_reset(struct drm_device *dev); | 154 | extern void r128_freelist_reset(struct drm_device *dev); |
151 | 155 | ||
152 | extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n); | 156 | extern int r128_wait_ring(drm_r128_private_t *dev_priv, int n); |
diff --git a/drivers/gpu/drm/r128/r128_ioc32.c b/drivers/gpu/drm/r128/r128_ioc32.c index 663f38c63ba6..6589f9e0310e 100644 --- a/drivers/gpu/drm/r128/r128_ioc32.c +++ b/drivers/gpu/drm/r128/r128_ioc32.c | |||
@@ -63,39 +63,36 @@ static int compat_r128_init(struct file *file, unsigned int cmd, | |||
63 | unsigned long arg) | 63 | unsigned long arg) |
64 | { | 64 | { |
65 | drm_r128_init32_t init32; | 65 | drm_r128_init32_t init32; |
66 | drm_r128_init_t __user *init; | 66 | drm_r128_init_t init; |
67 | 67 | ||
68 | if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) | 68 | if (copy_from_user(&init32, (void __user *)arg, sizeof(init32))) |
69 | return -EFAULT; | 69 | return -EFAULT; |
70 | 70 | ||
71 | init = compat_alloc_user_space(sizeof(*init)); | 71 | init.func = init32.func; |
72 | if (!access_ok(VERIFY_WRITE, init, sizeof(*init)) | 72 | init.sarea_priv_offset = init32.sarea_priv_offset; |
73 | || __put_user(init32.func, &init->func) | 73 | init.is_pci = init32.is_pci; |
74 | || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset) | 74 | init.cce_mode = init32.cce_mode; |
75 | || __put_user(init32.is_pci, &init->is_pci) | 75 | init.cce_secure = init32.cce_secure; |
76 | || __put_user(init32.cce_mode, &init->cce_mode) | 76 | init.ring_size = init32.ring_size; |
77 | || __put_user(init32.cce_secure, &init->cce_secure) | 77 | init.usec_timeout = init32.usec_timeout; |
78 | || __put_user(init32.ring_size, &init->ring_size) | 78 | init.fb_bpp = init32.fb_bpp; |
79 | || __put_user(init32.usec_timeout, &init->usec_timeout) | 79 | init.front_offset = init32.front_offset; |
80 | || __put_user(init32.fb_bpp, &init->fb_bpp) | 80 | init.front_pitch = init32.front_pitch; |
81 | || __put_user(init32.front_offset, &init->front_offset) | 81 | init.back_offset = init32.back_offset; |
82 | || __put_user(init32.front_pitch, &init->front_pitch) | 82 | init.back_pitch = init32.back_pitch; |
83 | || __put_user(init32.back_offset, &init->back_offset) | 83 | init.depth_bpp = init32.depth_bpp; |
84 | || __put_user(init32.back_pitch, &init->back_pitch) | 84 | init.depth_offset = init32.depth_offset; |
85 | || __put_user(init32.depth_bpp, &init->depth_bpp) | 85 | init.depth_pitch = init32.depth_pitch; |
86 | || __put_user(init32.depth_offset, &init->depth_offset) | 86 | init.span_offset = init32.span_offset; |
87 | || __put_user(init32.depth_pitch, &init->depth_pitch) | 87 | init.fb_offset = init32.fb_offset; |
88 | || __put_user(init32.span_offset, &init->span_offset) | 88 | init.mmio_offset = init32.mmio_offset; |
89 | || __put_user(init32.fb_offset, &init->fb_offset) | 89 | init.ring_offset = init32.ring_offset; |
90 | || __put_user(init32.mmio_offset, &init->mmio_offset) | 90 | init.ring_rptr_offset = init32.ring_rptr_offset; |
91 | || __put_user(init32.ring_offset, &init->ring_offset) | 91 | init.buffers_offset = init32.buffers_offset; |
92 | || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset) | 92 | init.agp_textures_offset = init32.agp_textures_offset; |
93 | || __put_user(init32.buffers_offset, &init->buffers_offset) | 93 | |
94 | || __put_user(init32.agp_textures_offset, | 94 | return drm_ioctl_kernel(file, r128_cce_init, &init, |
95 | &init->agp_textures_offset)) | 95 | DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY); |
96 | return -EFAULT; | ||
97 | |||
98 | return drm_ioctl(file, DRM_IOCTL_R128_INIT, (unsigned long)init); | ||
99 | } | 96 | } |
100 | 97 | ||
101 | typedef struct drm_r128_depth32 { | 98 | typedef struct drm_r128_depth32 { |
@@ -111,25 +108,19 @@ static int compat_r128_depth(struct file *file, unsigned int cmd, | |||
111 | unsigned long arg) | 108 | unsigned long arg) |
112 | { | 109 | { |
113 | drm_r128_depth32_t depth32; | 110 | drm_r128_depth32_t depth32; |
114 | drm_r128_depth_t __user *depth; | 111 | drm_r128_depth_t depth; |
115 | 112 | ||
116 | if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32))) | 113 | if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32))) |
117 | return -EFAULT; | 114 | return -EFAULT; |
118 | 115 | ||
119 | depth = compat_alloc_user_space(sizeof(*depth)); | 116 | depth.func = depth32.func; |
120 | if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth)) | 117 | depth.n = depth32.n; |
121 | || __put_user(depth32.func, &depth->func) | 118 | depth.x = compat_ptr(depth32.x); |
122 | || __put_user(depth32.n, &depth->n) | 119 | depth.y = compat_ptr(depth32.y); |
123 | || __put_user((int __user *)(unsigned long)depth32.x, &depth->x) | 120 | depth.buffer = compat_ptr(depth32.buffer); |
124 | || __put_user((int __user *)(unsigned long)depth32.y, &depth->y) | 121 | depth.mask = compat_ptr(depth32.mask); |
125 | || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, | ||
126 | &depth->buffer) | ||
127 | || __put_user((unsigned char __user *)(unsigned long)depth32.mask, | ||
128 | &depth->mask)) | ||
129 | return -EFAULT; | ||
130 | |||
131 | return drm_ioctl(file, DRM_IOCTL_R128_DEPTH, (unsigned long)depth); | ||
132 | 122 | ||
123 | return drm_ioctl_kernel(file, r128_cce_depth, &depth, DRM_AUTH); | ||
133 | } | 124 | } |
134 | 125 | ||
135 | typedef struct drm_r128_stipple32 { | 126 | typedef struct drm_r128_stipple32 { |
@@ -140,18 +131,14 @@ static int compat_r128_stipple(struct file *file, unsigned int cmd, | |||
140 | unsigned long arg) | 131 | unsigned long arg) |
141 | { | 132 | { |
142 | drm_r128_stipple32_t stipple32; | 133 | drm_r128_stipple32_t stipple32; |
143 | drm_r128_stipple_t __user *stipple; | 134 | drm_r128_stipple_t stipple; |
144 | 135 | ||
145 | if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32))) | 136 | if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32))) |
146 | return -EFAULT; | 137 | return -EFAULT; |
147 | 138 | ||
148 | stipple = compat_alloc_user_space(sizeof(*stipple)); | 139 | stipple.mask = compat_ptr(stipple32.mask); |
149 | if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple)) | ||
150 | || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, | ||
151 | &stipple->mask)) | ||
152 | return -EFAULT; | ||
153 | 140 | ||
154 | return drm_ioctl(file, DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple); | 141 | return drm_ioctl_kernel(file, r128_cce_stipple, &stipple, DRM_AUTH); |
155 | } | 142 | } |
156 | 143 | ||
157 | typedef struct drm_r128_getparam32 { | 144 | typedef struct drm_r128_getparam32 { |
@@ -163,19 +150,15 @@ static int compat_r128_getparam(struct file *file, unsigned int cmd, | |||
163 | unsigned long arg) | 150 | unsigned long arg) |
164 | { | 151 | { |
165 | drm_r128_getparam32_t getparam32; | 152 | drm_r128_getparam32_t getparam32; |
166 | drm_r128_getparam_t __user *getparam; | 153 | drm_r128_getparam_t getparam; |
167 | 154 | ||
168 | if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) | 155 | if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32))) |
169 | return -EFAULT; | 156 | return -EFAULT; |
170 | 157 | ||
171 | getparam = compat_alloc_user_space(sizeof(*getparam)); | 158 | getparam.param = getparam32.param; |
172 | if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam)) | 159 | getparam.value = compat_ptr(getparam32.value); |
173 | || __put_user(getparam32.param, &getparam->param) | ||
174 | || __put_user((void __user *)(unsigned long)getparam32.value, | ||
175 | &getparam->value)) | ||
176 | return -EFAULT; | ||
177 | 160 | ||
178 | return drm_ioctl(file, DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam); | 161 | return drm_ioctl_kernel(file, r128_getparam, &getparam, DRM_AUTH); |
179 | } | 162 | } |
180 | 163 | ||
181 | drm_ioctl_compat_t *r128_compat_ioctls[] = { | 164 | drm_ioctl_compat_t *r128_compat_ioctls[] = { |
diff --git a/drivers/gpu/drm/r128/r128_state.c b/drivers/gpu/drm/r128/r128_state.c index 8fd2d9f58f77..8fdc56c1c953 100644 --- a/drivers/gpu/drm/r128/r128_state.c +++ b/drivers/gpu/drm/r128/r128_state.c | |||
@@ -1460,7 +1460,7 @@ static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *fi | |||
1460 | return ret; | 1460 | return ret; |
1461 | } | 1461 | } |
1462 | 1462 | ||
1463 | static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) | 1463 | int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1464 | { | 1464 | { |
1465 | drm_r128_private_t *dev_priv = dev->dev_private; | 1465 | drm_r128_private_t *dev_priv = dev->dev_private; |
1466 | drm_r128_depth_t *depth = data; | 1466 | drm_r128_depth_t *depth = data; |
@@ -1492,7 +1492,7 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f | |||
1492 | return ret; | 1492 | return ret; |
1493 | } | 1493 | } |
1494 | 1494 | ||
1495 | static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) | 1495 | int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1496 | { | 1496 | { |
1497 | drm_r128_private_t *dev_priv = dev->dev_private; | 1497 | drm_r128_private_t *dev_priv = dev->dev_private; |
1498 | drm_r128_stipple_t *stipple = data; | 1498 | drm_r128_stipple_t *stipple = data; |
@@ -1582,7 +1582,7 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file | |||
1582 | return 0; | 1582 | return 0; |
1583 | } | 1583 | } |
1584 | 1584 | ||
1585 | static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) | 1585 | int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) |
1586 | { | 1586 | { |
1587 | drm_r128_private_t *dev_priv = dev->dev_private; | 1587 | drm_r128_private_t *dev_priv = dev->dev_private; |
1588 | drm_r128_getparam_t *param = data; | 1588 | drm_r128_getparam_t *param = data; |
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c index 6f638bbc922d..2cab27a68479 100644 --- a/drivers/i2c/i2c-dev.c +++ b/drivers/i2c/i2c-dev.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/notifier.h> | 35 | #include <linux/notifier.h> |
36 | #include <linux/slab.h> | 36 | #include <linux/slab.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <linux/compat.h> | ||
38 | 39 | ||
39 | /* | 40 | /* |
40 | * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a | 41 | * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a |
@@ -238,46 +239,29 @@ static int i2cdev_check_addr(struct i2c_adapter *adapter, unsigned int addr) | |||
238 | } | 239 | } |
239 | 240 | ||
240 | static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, | 241 | static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, |
241 | unsigned long arg) | 242 | unsigned nmsgs, struct i2c_msg *msgs) |
242 | { | 243 | { |
243 | struct i2c_rdwr_ioctl_data rdwr_arg; | ||
244 | struct i2c_msg *rdwr_pa; | ||
245 | u8 __user **data_ptrs; | 244 | u8 __user **data_ptrs; |
246 | int i, res; | 245 | int i, res; |
247 | 246 | ||
248 | if (copy_from_user(&rdwr_arg, | 247 | data_ptrs = kmalloc(nmsgs * sizeof(u8 __user *), GFP_KERNEL); |
249 | (struct i2c_rdwr_ioctl_data __user *)arg, | ||
250 | sizeof(rdwr_arg))) | ||
251 | return -EFAULT; | ||
252 | |||
253 | /* Put an arbitrary limit on the number of messages that can | ||
254 | * be sent at once */ | ||
255 | if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
256 | return -EINVAL; | ||
257 | |||
258 | rdwr_pa = memdup_user(rdwr_arg.msgs, | ||
259 | rdwr_arg.nmsgs * sizeof(struct i2c_msg)); | ||
260 | if (IS_ERR(rdwr_pa)) | ||
261 | return PTR_ERR(rdwr_pa); | ||
262 | |||
263 | data_ptrs = kmalloc(rdwr_arg.nmsgs * sizeof(u8 __user *), GFP_KERNEL); | ||
264 | if (data_ptrs == NULL) { | 248 | if (data_ptrs == NULL) { |
265 | kfree(rdwr_pa); | 249 | kfree(msgs); |
266 | return -ENOMEM; | 250 | return -ENOMEM; |
267 | } | 251 | } |
268 | 252 | ||
269 | res = 0; | 253 | res = 0; |
270 | for (i = 0; i < rdwr_arg.nmsgs; i++) { | 254 | for (i = 0; i < nmsgs; i++) { |
271 | /* Limit the size of the message to a sane amount */ | 255 | /* Limit the size of the message to a sane amount */ |
272 | if (rdwr_pa[i].len > 8192) { | 256 | if (msgs[i].len > 8192) { |
273 | res = -EINVAL; | 257 | res = -EINVAL; |
274 | break; | 258 | break; |
275 | } | 259 | } |
276 | 260 | ||
277 | data_ptrs[i] = (u8 __user *)rdwr_pa[i].buf; | 261 | data_ptrs[i] = (u8 __user *)msgs[i].buf; |
278 | rdwr_pa[i].buf = memdup_user(data_ptrs[i], rdwr_pa[i].len); | 262 | msgs[i].buf = memdup_user(data_ptrs[i], msgs[i].len); |
279 | if (IS_ERR(rdwr_pa[i].buf)) { | 263 | if (IS_ERR(msgs[i].buf)) { |
280 | res = PTR_ERR(rdwr_pa[i].buf); | 264 | res = PTR_ERR(msgs[i].buf); |
281 | break; | 265 | break; |
282 | } | 266 | } |
283 | 267 | ||
@@ -292,121 +276,117 @@ static noinline int i2cdev_ioctl_rdwr(struct i2c_client *client, | |||
292 | * greater (for example to account for a checksum byte at | 276 | * greater (for example to account for a checksum byte at |
293 | * the end of the message.) | 277 | * the end of the message.) |
294 | */ | 278 | */ |
295 | if (rdwr_pa[i].flags & I2C_M_RECV_LEN) { | 279 | if (msgs[i].flags & I2C_M_RECV_LEN) { |
296 | if (!(rdwr_pa[i].flags & I2C_M_RD) || | 280 | if (!(msgs[i].flags & I2C_M_RD) || |
297 | rdwr_pa[i].buf[0] < 1 || | 281 | msgs[i].buf[0] < 1 || |
298 | rdwr_pa[i].len < rdwr_pa[i].buf[0] + | 282 | msgs[i].len < msgs[i].buf[0] + |
299 | I2C_SMBUS_BLOCK_MAX) { | 283 | I2C_SMBUS_BLOCK_MAX) { |
300 | res = -EINVAL; | 284 | res = -EINVAL; |
301 | break; | 285 | break; |
302 | } | 286 | } |
303 | 287 | ||
304 | rdwr_pa[i].len = rdwr_pa[i].buf[0]; | 288 | msgs[i].len = msgs[i].buf[0]; |
305 | } | 289 | } |
306 | } | 290 | } |
307 | if (res < 0) { | 291 | if (res < 0) { |
308 | int j; | 292 | int j; |
309 | for (j = 0; j < i; ++j) | 293 | for (j = 0; j < i; ++j) |
310 | kfree(rdwr_pa[j].buf); | 294 | kfree(msgs[j].buf); |
311 | kfree(data_ptrs); | 295 | kfree(data_ptrs); |
312 | kfree(rdwr_pa); | 296 | kfree(msgs); |
313 | return res; | 297 | return res; |
314 | } | 298 | } |
315 | 299 | ||
316 | res = i2c_transfer(client->adapter, rdwr_pa, rdwr_arg.nmsgs); | 300 | res = i2c_transfer(client->adapter, msgs, nmsgs); |
317 | while (i-- > 0) { | 301 | while (i-- > 0) { |
318 | if (res >= 0 && (rdwr_pa[i].flags & I2C_M_RD)) { | 302 | if (res >= 0 && (msgs[i].flags & I2C_M_RD)) { |
319 | if (copy_to_user(data_ptrs[i], rdwr_pa[i].buf, | 303 | if (copy_to_user(data_ptrs[i], msgs[i].buf, |
320 | rdwr_pa[i].len)) | 304 | msgs[i].len)) |
321 | res = -EFAULT; | 305 | res = -EFAULT; |
322 | } | 306 | } |
323 | kfree(rdwr_pa[i].buf); | 307 | kfree(msgs[i].buf); |
324 | } | 308 | } |
325 | kfree(data_ptrs); | 309 | kfree(data_ptrs); |
326 | kfree(rdwr_pa); | 310 | kfree(msgs); |
327 | return res; | 311 | return res; |
328 | } | 312 | } |
329 | 313 | ||
330 | static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, | 314 | static noinline int i2cdev_ioctl_smbus(struct i2c_client *client, |
331 | unsigned long arg) | 315 | u8 read_write, u8 command, u32 size, |
316 | union i2c_smbus_data __user *data) | ||
332 | { | 317 | { |
333 | struct i2c_smbus_ioctl_data data_arg; | ||
334 | union i2c_smbus_data temp = {}; | 318 | union i2c_smbus_data temp = {}; |
335 | int datasize, res; | 319 | int datasize, res; |
336 | 320 | ||
337 | if (copy_from_user(&data_arg, | 321 | if ((size != I2C_SMBUS_BYTE) && |
338 | (struct i2c_smbus_ioctl_data __user *) arg, | 322 | (size != I2C_SMBUS_QUICK) && |
339 | sizeof(struct i2c_smbus_ioctl_data))) | 323 | (size != I2C_SMBUS_BYTE_DATA) && |
340 | return -EFAULT; | 324 | (size != I2C_SMBUS_WORD_DATA) && |
341 | if ((data_arg.size != I2C_SMBUS_BYTE) && | 325 | (size != I2C_SMBUS_PROC_CALL) && |
342 | (data_arg.size != I2C_SMBUS_QUICK) && | 326 | (size != I2C_SMBUS_BLOCK_DATA) && |
343 | (data_arg.size != I2C_SMBUS_BYTE_DATA) && | 327 | (size != I2C_SMBUS_I2C_BLOCK_BROKEN) && |
344 | (data_arg.size != I2C_SMBUS_WORD_DATA) && | 328 | (size != I2C_SMBUS_I2C_BLOCK_DATA) && |
345 | (data_arg.size != I2C_SMBUS_PROC_CALL) && | 329 | (size != I2C_SMBUS_BLOCK_PROC_CALL)) { |
346 | (data_arg.size != I2C_SMBUS_BLOCK_DATA) && | ||
347 | (data_arg.size != I2C_SMBUS_I2C_BLOCK_BROKEN) && | ||
348 | (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA) && | ||
349 | (data_arg.size != I2C_SMBUS_BLOCK_PROC_CALL)) { | ||
350 | dev_dbg(&client->adapter->dev, | 330 | dev_dbg(&client->adapter->dev, |
351 | "size out of range (%x) in ioctl I2C_SMBUS.\n", | 331 | "size out of range (%x) in ioctl I2C_SMBUS.\n", |
352 | data_arg.size); | 332 | size); |
353 | return -EINVAL; | 333 | return -EINVAL; |
354 | } | 334 | } |
355 | /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, | 335 | /* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, |
356 | so the check is valid if size==I2C_SMBUS_QUICK too. */ | 336 | so the check is valid if size==I2C_SMBUS_QUICK too. */ |
357 | if ((data_arg.read_write != I2C_SMBUS_READ) && | 337 | if ((read_write != I2C_SMBUS_READ) && |
358 | (data_arg.read_write != I2C_SMBUS_WRITE)) { | 338 | (read_write != I2C_SMBUS_WRITE)) { |
359 | dev_dbg(&client->adapter->dev, | 339 | dev_dbg(&client->adapter->dev, |
360 | "read_write out of range (%x) in ioctl I2C_SMBUS.\n", | 340 | "read_write out of range (%x) in ioctl I2C_SMBUS.\n", |
361 | data_arg.read_write); | 341 | read_write); |
362 | return -EINVAL; | 342 | return -EINVAL; |
363 | } | 343 | } |
364 | 344 | ||
365 | /* Note that command values are always valid! */ | 345 | /* Note that command values are always valid! */ |
366 | 346 | ||
367 | if ((data_arg.size == I2C_SMBUS_QUICK) || | 347 | if ((size == I2C_SMBUS_QUICK) || |
368 | ((data_arg.size == I2C_SMBUS_BYTE) && | 348 | ((size == I2C_SMBUS_BYTE) && |
369 | (data_arg.read_write == I2C_SMBUS_WRITE))) | 349 | (read_write == I2C_SMBUS_WRITE))) |
370 | /* These are special: we do not use data */ | 350 | /* These are special: we do not use data */ |
371 | return i2c_smbus_xfer(client->adapter, client->addr, | 351 | return i2c_smbus_xfer(client->adapter, client->addr, |
372 | client->flags, data_arg.read_write, | 352 | client->flags, read_write, |
373 | data_arg.command, data_arg.size, NULL); | 353 | command, size, NULL); |
374 | 354 | ||
375 | if (data_arg.data == NULL) { | 355 | if (data == NULL) { |
376 | dev_dbg(&client->adapter->dev, | 356 | dev_dbg(&client->adapter->dev, |
377 | "data is NULL pointer in ioctl I2C_SMBUS.\n"); | 357 | "data is NULL pointer in ioctl I2C_SMBUS.\n"); |
378 | return -EINVAL; | 358 | return -EINVAL; |
379 | } | 359 | } |
380 | 360 | ||
381 | if ((data_arg.size == I2C_SMBUS_BYTE_DATA) || | 361 | if ((size == I2C_SMBUS_BYTE_DATA) || |
382 | (data_arg.size == I2C_SMBUS_BYTE)) | 362 | (size == I2C_SMBUS_BYTE)) |
383 | datasize = sizeof(data_arg.data->byte); | 363 | datasize = sizeof(data->byte); |
384 | else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || | 364 | else if ((size == I2C_SMBUS_WORD_DATA) || |
385 | (data_arg.size == I2C_SMBUS_PROC_CALL)) | 365 | (size == I2C_SMBUS_PROC_CALL)) |
386 | datasize = sizeof(data_arg.data->word); | 366 | datasize = sizeof(data->word); |
387 | else /* size == smbus block, i2c block, or block proc. call */ | 367 | else /* size == smbus block, i2c block, or block proc. call */ |
388 | datasize = sizeof(data_arg.data->block); | 368 | datasize = sizeof(data->block); |
389 | 369 | ||
390 | if ((data_arg.size == I2C_SMBUS_PROC_CALL) || | 370 | if ((size == I2C_SMBUS_PROC_CALL) || |
391 | (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || | 371 | (size == I2C_SMBUS_BLOCK_PROC_CALL) || |
392 | (data_arg.size == I2C_SMBUS_I2C_BLOCK_DATA) || | 372 | (size == I2C_SMBUS_I2C_BLOCK_DATA) || |
393 | (data_arg.read_write == I2C_SMBUS_WRITE)) { | 373 | (read_write == I2C_SMBUS_WRITE)) { |
394 | if (copy_from_user(&temp, data_arg.data, datasize)) | 374 | if (copy_from_user(&temp, data, datasize)) |
395 | return -EFAULT; | 375 | return -EFAULT; |
396 | } | 376 | } |
397 | if (data_arg.size == I2C_SMBUS_I2C_BLOCK_BROKEN) { | 377 | if (size == I2C_SMBUS_I2C_BLOCK_BROKEN) { |
398 | /* Convert old I2C block commands to the new | 378 | /* Convert old I2C block commands to the new |
399 | convention. This preserves binary compatibility. */ | 379 | convention. This preserves binary compatibility. */ |
400 | data_arg.size = I2C_SMBUS_I2C_BLOCK_DATA; | 380 | size = I2C_SMBUS_I2C_BLOCK_DATA; |
401 | if (data_arg.read_write == I2C_SMBUS_READ) | 381 | if (read_write == I2C_SMBUS_READ) |
402 | temp.block[0] = I2C_SMBUS_BLOCK_MAX; | 382 | temp.block[0] = I2C_SMBUS_BLOCK_MAX; |
403 | } | 383 | } |
404 | res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, | 384 | res = i2c_smbus_xfer(client->adapter, client->addr, client->flags, |
405 | data_arg.read_write, data_arg.command, data_arg.size, &temp); | 385 | read_write, command, size, &temp); |
406 | if (!res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || | 386 | if (!res && ((size == I2C_SMBUS_PROC_CALL) || |
407 | (data_arg.size == I2C_SMBUS_BLOCK_PROC_CALL) || | 387 | (size == I2C_SMBUS_BLOCK_PROC_CALL) || |
408 | (data_arg.read_write == I2C_SMBUS_READ))) { | 388 | (read_write == I2C_SMBUS_READ))) { |
409 | if (copy_to_user(data_arg.data, &temp, datasize)) | 389 | if (copy_to_user(data, &temp, datasize)) |
410 | return -EFAULT; | 390 | return -EFAULT; |
411 | } | 391 | } |
412 | return res; | 392 | return res; |
@@ -454,12 +434,39 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
454 | funcs = i2c_get_functionality(client->adapter); | 434 | funcs = i2c_get_functionality(client->adapter); |
455 | return put_user(funcs, (unsigned long __user *)arg); | 435 | return put_user(funcs, (unsigned long __user *)arg); |
456 | 436 | ||
457 | case I2C_RDWR: | 437 | case I2C_RDWR: { |
458 | return i2cdev_ioctl_rdwr(client, arg); | 438 | struct i2c_rdwr_ioctl_data rdwr_arg; |
439 | struct i2c_msg *rdwr_pa; | ||
440 | |||
441 | if (copy_from_user(&rdwr_arg, | ||
442 | (struct i2c_rdwr_ioctl_data __user *)arg, | ||
443 | sizeof(rdwr_arg))) | ||
444 | return -EFAULT; | ||
445 | |||
446 | /* Put an arbitrary limit on the number of messages that can | ||
447 | * be sent at once */ | ||
448 | if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
449 | return -EINVAL; | ||
459 | 450 | ||
460 | case I2C_SMBUS: | 451 | rdwr_pa = memdup_user(rdwr_arg.msgs, |
461 | return i2cdev_ioctl_smbus(client, arg); | 452 | rdwr_arg.nmsgs * sizeof(struct i2c_msg)); |
453 | if (IS_ERR(rdwr_pa)) | ||
454 | return PTR_ERR(rdwr_pa); | ||
455 | |||
456 | return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); | ||
457 | } | ||
462 | 458 | ||
459 | case I2C_SMBUS: { | ||
460 | struct i2c_smbus_ioctl_data data_arg; | ||
461 | if (copy_from_user(&data_arg, | ||
462 | (struct i2c_smbus_ioctl_data __user *) arg, | ||
463 | sizeof(struct i2c_smbus_ioctl_data))) | ||
464 | return -EFAULT; | ||
465 | return i2cdev_ioctl_smbus(client, data_arg.read_write, | ||
466 | data_arg.command, | ||
467 | data_arg.size, | ||
468 | data_arg.data); | ||
469 | } | ||
463 | case I2C_RETRIES: | 470 | case I2C_RETRIES: |
464 | client->adapter->retries = arg; | 471 | client->adapter->retries = arg; |
465 | break; | 472 | break; |
@@ -480,6 +487,90 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
480 | return 0; | 487 | return 0; |
481 | } | 488 | } |
482 | 489 | ||
490 | #ifdef CONFIG_COMPAT | ||
491 | |||
492 | struct i2c_smbus_ioctl_data32 { | ||
493 | u8 read_write; | ||
494 | u8 command; | ||
495 | u32 size; | ||
496 | compat_caddr_t data; /* union i2c_smbus_data *data */ | ||
497 | }; | ||
498 | |||
499 | struct i2c_msg32 { | ||
500 | u16 addr; | ||
501 | u16 flags; | ||
502 | u16 len; | ||
503 | compat_caddr_t buf; | ||
504 | }; | ||
505 | |||
506 | struct i2c_rdwr_ioctl_data32 { | ||
507 | compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ | ||
508 | u32 nmsgs; | ||
509 | }; | ||
510 | |||
511 | static long compat_i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
512 | { | ||
513 | struct i2c_client *client = file->private_data; | ||
514 | unsigned long funcs; | ||
515 | switch (cmd) { | ||
516 | case I2C_FUNCS: | ||
517 | funcs = i2c_get_functionality(client->adapter); | ||
518 | return put_user(funcs, (compat_ulong_t __user *)arg); | ||
519 | case I2C_RDWR: { | ||
520 | struct i2c_rdwr_ioctl_data32 rdwr_arg; | ||
521 | struct i2c_msg32 *p; | ||
522 | struct i2c_msg *rdwr_pa; | ||
523 | int i; | ||
524 | |||
525 | if (copy_from_user(&rdwr_arg, | ||
526 | (struct i2c_rdwr_ioctl_data32 __user *)arg, | ||
527 | sizeof(rdwr_arg))) | ||
528 | return -EFAULT; | ||
529 | |||
530 | if (rdwr_arg.nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
531 | return -EINVAL; | ||
532 | |||
533 | rdwr_pa = kmalloc_array(rdwr_arg.nmsgs, sizeof(struct i2c_msg), | ||
534 | GFP_KERNEL); | ||
535 | if (!rdwr_pa) | ||
536 | return -ENOMEM; | ||
537 | |||
538 | p = compat_ptr(rdwr_arg.msgs); | ||
539 | for (i = 0; i < rdwr_arg.nmsgs; i++) { | ||
540 | struct i2c_msg32 umsg; | ||
541 | if (copy_from_user(&umsg, p + i, sizeof(umsg))) { | ||
542 | kfree(rdwr_pa); | ||
543 | return -EFAULT; | ||
544 | } | ||
545 | rdwr_pa[i] = (struct i2c_msg) { | ||
546 | .addr = umsg.addr, | ||
547 | .flags = umsg.flags, | ||
548 | .len = umsg.len, | ||
549 | .buf = compat_ptr(umsg.buf) | ||
550 | }; | ||
551 | } | ||
552 | |||
553 | return i2cdev_ioctl_rdwr(client, rdwr_arg.nmsgs, rdwr_pa); | ||
554 | } | ||
555 | case I2C_SMBUS: { | ||
556 | struct i2c_smbus_ioctl_data32 data32; | ||
557 | if (copy_from_user(&data32, | ||
558 | (void __user *) arg, | ||
559 | sizeof(data32))) | ||
560 | return -EFAULT; | ||
561 | return i2cdev_ioctl_smbus(client, data32.read_write, | ||
562 | data32.command, | ||
563 | data32.size, | ||
564 | compat_ptr(data32.data)); | ||
565 | } | ||
566 | default: | ||
567 | return i2cdev_ioctl(file, cmd, arg); | ||
568 | } | ||
569 | } | ||
570 | #else | ||
571 | #define compat_i2cdev_ioctl NULL | ||
572 | #endif | ||
573 | |||
483 | static int i2cdev_open(struct inode *inode, struct file *file) | 574 | static int i2cdev_open(struct inode *inode, struct file *file) |
484 | { | 575 | { |
485 | unsigned int minor = iminor(inode); | 576 | unsigned int minor = iminor(inode); |
@@ -527,6 +618,7 @@ static const struct file_operations i2cdev_fops = { | |||
527 | .read = i2cdev_read, | 618 | .read = i2cdev_read, |
528 | .write = i2cdev_write, | 619 | .write = i2cdev_write, |
529 | .unlocked_ioctl = i2cdev_ioctl, | 620 | .unlocked_ioctl = i2cdev_ioctl, |
621 | .compat_ioctl = compat_i2cdev_ioctl, | ||
530 | .open = i2cdev_open, | 622 | .open = i2cdev_open, |
531 | .release = i2cdev_release, | 623 | .release = i2cdev_release, |
532 | }; | 624 | }; |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 3568294d4854..de8c902059b8 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -375,12 +375,7 @@ static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd, | |||
375 | return -EINVAL; | 375 | return -EINVAL; |
376 | 376 | ||
377 | if (!mtd->_write_oob) | 377 | if (!mtd->_write_oob) |
378 | ret = -EOPNOTSUPP; | 378 | return -EOPNOTSUPP; |
379 | else | ||
380 | ret = access_ok(VERIFY_READ, ptr, length) ? 0 : -EFAULT; | ||
381 | |||
382 | if (ret) | ||
383 | return ret; | ||
384 | 379 | ||
385 | ops.ooblen = length; | 380 | ops.ooblen = length; |
386 | ops.ooboffs = start & (mtd->writesize - 1); | 381 | ops.ooboffs = start & (mtd->writesize - 1); |
@@ -419,9 +414,6 @@ static int mtdchar_readoob(struct file *file, struct mtd_info *mtd, | |||
419 | if (length > 4096) | 414 | if (length > 4096) |
420 | return -EINVAL; | 415 | return -EINVAL; |
421 | 416 | ||
422 | if (!access_ok(VERIFY_WRITE, ptr, length)) | ||
423 | return -EFAULT; | ||
424 | |||
425 | ops.ooblen = length; | 417 | ops.ooblen = length; |
426 | ops.ooboffs = start & (mtd->writesize - 1); | 418 | ops.ooboffs = start & (mtd->writesize - 1); |
427 | ops.datbuf = NULL; | 419 | ops.datbuf = NULL; |
@@ -618,9 +610,6 @@ static int mtdchar_write_ioctl(struct mtd_info *mtd, | |||
618 | 610 | ||
619 | usr_data = (const void __user *)(uintptr_t)req.usr_data; | 611 | usr_data = (const void __user *)(uintptr_t)req.usr_data; |
620 | usr_oob = (const void __user *)(uintptr_t)req.usr_oob; | 612 | usr_oob = (const void __user *)(uintptr_t)req.usr_oob; |
621 | if (!access_ok(VERIFY_READ, usr_data, req.len) || | ||
622 | !access_ok(VERIFY_READ, usr_oob, req.ooblen)) | ||
623 | return -EFAULT; | ||
624 | 613 | ||
625 | if (!mtd->_write_oob) | 614 | if (!mtd->_write_oob) |
626 | return -EOPNOTSUPP; | 615 | return -EOPNOTSUPP; |
@@ -662,21 +651,10 @@ static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) | |||
662 | struct mtd_info *mtd = mfi->mtd; | 651 | struct mtd_info *mtd = mfi->mtd; |
663 | void __user *argp = (void __user *)arg; | 652 | void __user *argp = (void __user *)arg; |
664 | int ret = 0; | 653 | int ret = 0; |
665 | u_long size; | ||
666 | struct mtd_info_user info; | 654 | struct mtd_info_user info; |
667 | 655 | ||
668 | pr_debug("MTD_ioctl\n"); | 656 | pr_debug("MTD_ioctl\n"); |
669 | 657 | ||
670 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; | ||
671 | if (cmd & IOC_IN) { | ||
672 | if (!access_ok(VERIFY_READ, argp, size)) | ||
673 | return -EFAULT; | ||
674 | } | ||
675 | if (cmd & IOC_OUT) { | ||
676 | if (!access_ok(VERIFY_WRITE, argp, size)) | ||
677 | return -EFAULT; | ||
678 | } | ||
679 | |||
680 | switch (cmd) { | 658 | switch (cmd) { |
681 | case MEMGETREGIONCOUNT: | 659 | case MEMGETREGIONCOUNT: |
682 | if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) | 660 | if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) |
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c index 617802855233..38b3a9c84fd1 100644 --- a/drivers/scsi/cxlflash/main.c +++ b/drivers/scsi/cxlflash/main.c | |||
@@ -3393,12 +3393,6 @@ static int cxlflash_afu_debug(struct cxlflash_cfg *cfg, | |||
3393 | goto out; | 3393 | goto out; |
3394 | } | 3394 | } |
3395 | 3395 | ||
3396 | if (unlikely(!access_ok(is_write ? VERIFY_READ : VERIFY_WRITE, | ||
3397 | ubuf, ulen))) { | ||
3398 | rc = -EFAULT; | ||
3399 | goto out; | ||
3400 | } | ||
3401 | |||
3402 | buf = kmalloc(ulen + cache_line_size() - 1, GFP_KERNEL); | 3396 | buf = kmalloc(ulen + cache_line_size() - 1, GFP_KERNEL); |
3403 | if (unlikely(!buf)) { | 3397 | if (unlikely(!buf)) { |
3404 | rc = -ENOMEM; | 3398 | rc = -ENOMEM; |
diff --git a/drivers/staging/pi433/pi433_if.c b/drivers/staging/pi433/pi433_if.c index d946838450d4..2a205c6173dc 100644 --- a/drivers/staging/pi433/pi433_if.c +++ b/drivers/staging/pi433/pi433_if.c | |||
@@ -762,32 +762,15 @@ abort: | |||
762 | static long | 762 | static long |
763 | pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 763 | pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
764 | { | 764 | { |
765 | int err = 0; | ||
766 | int retval = 0; | 765 | int retval = 0; |
767 | struct pi433_instance *instance; | 766 | struct pi433_instance *instance; |
768 | struct pi433_device *device; | 767 | struct pi433_device *device; |
769 | u32 tmp; | 768 | void __user *argp = (void __user *)arg; |
770 | 769 | ||
771 | /* Check type and command number */ | 770 | /* Check type and command number */ |
772 | if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC) | 771 | if (_IOC_TYPE(cmd) != PI433_IOC_MAGIC) |
773 | return -ENOTTY; | 772 | return -ENOTTY; |
774 | 773 | ||
775 | /* Check access direction once here; don't repeat below. | ||
776 | * IOC_DIR is from the user perspective, while access_ok is | ||
777 | * from the kernel perspective; so they look reversed. | ||
778 | */ | ||
779 | if (_IOC_DIR(cmd) & _IOC_READ) | ||
780 | err = !access_ok(VERIFY_WRITE, | ||
781 | (void __user *)arg, | ||
782 | _IOC_SIZE(cmd)); | ||
783 | |||
784 | if (err == 0 && _IOC_DIR(cmd) & _IOC_WRITE) | ||
785 | err = !access_ok(VERIFY_READ, | ||
786 | (void __user *)arg, | ||
787 | _IOC_SIZE(cmd)); | ||
788 | if (err) | ||
789 | return -EFAULT; | ||
790 | |||
791 | /* TODO? guard against device removal before, or while, | 774 | /* TODO? guard against device removal before, or while, |
792 | * we issue this ioctl. --> device_get() | 775 | * we issue this ioctl. --> device_get() |
793 | */ | 776 | */ |
@@ -799,78 +782,33 @@ pi433_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | |||
799 | 782 | ||
800 | switch (cmd) { | 783 | switch (cmd) { |
801 | case PI433_IOC_RD_TX_CFG: | 784 | case PI433_IOC_RD_TX_CFG: |
802 | tmp = _IOC_SIZE(cmd); | 785 | if (copy_to_user(argp, &instance->tx_cfg, |
803 | if ((tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0)) { | 786 | sizeof(struct pi433_tx_cfg))) |
804 | retval = -EINVAL; | 787 | return -EFAULT; |
805 | break; | ||
806 | } | ||
807 | |||
808 | if (__copy_to_user((void __user *)arg, | ||
809 | &instance->tx_cfg, | ||
810 | tmp)) | ||
811 | { | ||
812 | retval = -EFAULT; | ||
813 | break; | ||
814 | } | ||
815 | |||
816 | break; | 788 | break; |
817 | case PI433_IOC_WR_TX_CFG: | 789 | case PI433_IOC_WR_TX_CFG: |
818 | tmp = _IOC_SIZE(cmd); | 790 | if (copy_from_user(&instance->tx_cfg, argp, |
819 | if ((tmp == 0) || ((tmp % sizeof(struct pi433_tx_cfg)) != 0)) { | 791 | sizeof(struct pi433_tx_cfg))) |
820 | retval = -EINVAL; | 792 | return -EFAULT; |
821 | break; | ||
822 | } | ||
823 | |||
824 | if (__copy_from_user(&instance->tx_cfg, | ||
825 | (void __user *)arg, | ||
826 | tmp)) | ||
827 | { | ||
828 | retval = -EFAULT; | ||
829 | break; | ||
830 | } | ||
831 | |||
832 | break; | 793 | break; |
833 | |||
834 | case PI433_IOC_RD_RX_CFG: | 794 | case PI433_IOC_RD_RX_CFG: |
835 | tmp = _IOC_SIZE(cmd); | 795 | if (copy_to_user(argp, &device->rx_cfg, |
836 | if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) { | 796 | sizeof(struct pi433_rx_cfg))) |
837 | retval = -EINVAL; | 797 | return -EFAULT; |
838 | break; | ||
839 | } | ||
840 | |||
841 | if (__copy_to_user((void __user *)arg, | ||
842 | &device->rx_cfg, | ||
843 | tmp)) | ||
844 | { | ||
845 | retval = -EFAULT; | ||
846 | break; | ||
847 | } | ||
848 | |||
849 | break; | 798 | break; |
850 | case PI433_IOC_WR_RX_CFG: | 799 | case PI433_IOC_WR_RX_CFG: |
851 | tmp = _IOC_SIZE(cmd); | ||
852 | mutex_lock(&device->rx_lock); | 800 | mutex_lock(&device->rx_lock); |
853 | 801 | ||
854 | /* during pendig read request, change of config not allowed */ | 802 | /* during pendig read request, change of config not allowed */ |
855 | if (device->rx_active) { | 803 | if (device->rx_active) { |
856 | retval = -EAGAIN; | ||
857 | mutex_unlock(&device->rx_lock); | ||
858 | break; | ||
859 | } | ||
860 | |||
861 | if ( (tmp == 0) || ((tmp % sizeof(struct pi433_rx_cfg)) != 0) ) { | ||
862 | retval = -EINVAL; | ||
863 | mutex_unlock(&device->rx_lock); | 804 | mutex_unlock(&device->rx_lock); |
864 | break; | 805 | return -EAGAIN; |
865 | } | 806 | } |
866 | 807 | ||
867 | if (__copy_from_user(&device->rx_cfg, | 808 | if (copy_from_user(&device->rx_cfg, argp, |
868 | (void __user *)arg, | 809 | sizeof(struct pi433_rx_cfg))) { |
869 | tmp)) | ||
870 | { | ||
871 | retval = -EFAULT; | ||
872 | mutex_unlock(&device->rx_lock); | 810 | mutex_unlock(&device->rx_lock); |
873 | break; | 811 | return -EFAULT; |
874 | } | 812 | } |
875 | 813 | ||
876 | mutex_unlock(&device->rx_lock); | 814 | mutex_unlock(&device->rx_lock); |
diff --git a/drivers/tty/vt/selection.c b/drivers/tty/vt/selection.c index 7a4c8022c023..af4da9507180 100644 --- a/drivers/tty/vt/selection.c +++ b/drivers/tty/vt/selection.c | |||
@@ -156,42 +156,34 @@ static int store_utf8(u16 c, char *p) | |||
156 | int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) | 156 | int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *tty) |
157 | { | 157 | { |
158 | struct vc_data *vc = vc_cons[fg_console].d; | 158 | struct vc_data *vc = vc_cons[fg_console].d; |
159 | int sel_mode, new_sel_start, new_sel_end, spc; | 159 | int new_sel_start, new_sel_end, spc; |
160 | struct tiocl_selection v; | ||
160 | char *bp, *obp; | 161 | char *bp, *obp; |
161 | int i, ps, pe, multiplier; | 162 | int i, ps, pe, multiplier; |
162 | u16 c; | 163 | u16 c; |
163 | int mode; | 164 | int mode; |
164 | 165 | ||
165 | poke_blanked_console(); | 166 | poke_blanked_console(); |
167 | if (copy_from_user(&v, sel, sizeof(*sel))) | ||
168 | return -EFAULT; | ||
166 | 169 | ||
167 | { unsigned short xs, ys, xe, ye; | 170 | v.xs = limit(v.xs - 1, vc->vc_cols - 1); |
171 | v.ys = limit(v.ys - 1, vc->vc_rows - 1); | ||
172 | v.xe = limit(v.xe - 1, vc->vc_cols - 1); | ||
173 | v.ye = limit(v.ye - 1, vc->vc_rows - 1); | ||
174 | ps = v.ys * vc->vc_size_row + (v.xs << 1); | ||
175 | pe = v.ye * vc->vc_size_row + (v.xe << 1); | ||
168 | 176 | ||
169 | if (!access_ok(VERIFY_READ, sel, sizeof(*sel))) | 177 | if (v.sel_mode == TIOCL_SELCLEAR) { |
170 | return -EFAULT; | 178 | /* useful for screendump without selection highlights */ |
171 | __get_user(xs, &sel->xs); | 179 | clear_selection(); |
172 | __get_user(ys, &sel->ys); | 180 | return 0; |
173 | __get_user(xe, &sel->xe); | 181 | } |
174 | __get_user(ye, &sel->ye); | 182 | |
175 | __get_user(sel_mode, &sel->sel_mode); | 183 | if (mouse_reporting() && (v.sel_mode & TIOCL_SELMOUSEREPORT)) { |
176 | xs--; ys--; xe--; ye--; | 184 | mouse_report(tty, v.sel_mode & TIOCL_SELBUTTONMASK, v.xs, v.ys); |
177 | xs = limit(xs, vc->vc_cols - 1); | 185 | return 0; |
178 | ys = limit(ys, vc->vc_rows - 1); | 186 | } |
179 | xe = limit(xe, vc->vc_cols - 1); | ||
180 | ye = limit(ye, vc->vc_rows - 1); | ||
181 | ps = ys * vc->vc_size_row + (xs << 1); | ||
182 | pe = ye * vc->vc_size_row + (xe << 1); | ||
183 | |||
184 | if (sel_mode == TIOCL_SELCLEAR) { | ||
185 | /* useful for screendump without selection highlights */ | ||
186 | clear_selection(); | ||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | if (mouse_reporting() && (sel_mode & TIOCL_SELMOUSEREPORT)) { | ||
191 | mouse_report(tty, sel_mode & TIOCL_SELBUTTONMASK, xs, ys); | ||
192 | return 0; | ||
193 | } | ||
194 | } | ||
195 | 187 | ||
196 | if (ps > pe) /* make sel_start <= sel_end */ | 188 | if (ps > pe) /* make sel_start <= sel_end */ |
197 | { | 189 | { |
@@ -210,7 +202,7 @@ int set_selection(const struct tiocl_selection __user *sel, struct tty_struct *t | |||
210 | else | 202 | else |
211 | use_unicode = 0; | 203 | use_unicode = 0; |
212 | 204 | ||
213 | switch (sel_mode) | 205 | switch (v.sel_mode) |
214 | { | 206 | { |
215 | case TIOCL_SELCHAR: /* character-by-character selection */ | 207 | case TIOCL_SELCHAR: /* character-by-character selection */ |
216 | new_sel_start = ps; | 208 | new_sel_start = ps; |
diff --git a/drivers/tty/vt/vt_ioctl.c b/drivers/tty/vt/vt_ioctl.c index 2d2b420598b2..d61be307256a 100644 --- a/drivers/tty/vt/vt_ioctl.c +++ b/drivers/tty/vt/vt_ioctl.c | |||
@@ -843,58 +843,44 @@ int vt_ioctl(struct tty_struct *tty, | |||
843 | 843 | ||
844 | case VT_RESIZEX: | 844 | case VT_RESIZEX: |
845 | { | 845 | { |
846 | struct vt_consize __user *vtconsize = up; | 846 | struct vt_consize v; |
847 | ushort ll,cc,vlin,clin,vcol,ccol; | ||
848 | if (!perm) | 847 | if (!perm) |
849 | return -EPERM; | 848 | return -EPERM; |
850 | if (!access_ok(VERIFY_READ, vtconsize, | 849 | if (copy_from_user(&v, up, sizeof(struct vt_consize))) |
851 | sizeof(struct vt_consize))) { | 850 | return -EFAULT; |
852 | ret = -EFAULT; | ||
853 | break; | ||
854 | } | ||
855 | /* FIXME: Should check the copies properly */ | 851 | /* FIXME: Should check the copies properly */ |
856 | __get_user(ll, &vtconsize->v_rows); | 852 | if (!v.v_vlin) |
857 | __get_user(cc, &vtconsize->v_cols); | 853 | v.v_vlin = vc->vc_scan_lines; |
858 | __get_user(vlin, &vtconsize->v_vlin); | 854 | if (v.v_clin) { |
859 | __get_user(clin, &vtconsize->v_clin); | 855 | int rows = v.v_vlin/v.v_clin; |
860 | __get_user(vcol, &vtconsize->v_vcol); | 856 | if (v.v_rows != rows) { |
861 | __get_user(ccol, &vtconsize->v_ccol); | 857 | if (v.v_rows) /* Parameters don't add up */ |
862 | vlin = vlin ? vlin : vc->vc_scan_lines; | 858 | return -EINVAL; |
863 | if (clin) { | 859 | v.v_rows = rows; |
864 | if (ll) { | 860 | } |
865 | if (ll != vlin/clin) { | ||
866 | /* Parameters don't add up */ | ||
867 | ret = -EINVAL; | ||
868 | break; | ||
869 | } | ||
870 | } else | ||
871 | ll = vlin/clin; | ||
872 | } | 861 | } |
873 | if (vcol && ccol) { | 862 | if (v.v_vcol && v.v_ccol) { |
874 | if (cc) { | 863 | int cols = v.v_vcol/v.v_ccol; |
875 | if (cc != vcol/ccol) { | 864 | if (v.v_cols != cols) { |
876 | ret = -EINVAL; | 865 | if (v.v_cols) |
877 | break; | 866 | return -EINVAL; |
878 | } | 867 | v.v_cols = cols; |
879 | } else | 868 | } |
880 | cc = vcol/ccol; | ||
881 | } | 869 | } |
882 | 870 | ||
883 | if (clin > 32) { | 871 | if (v.v_clin > 32) |
884 | ret = -EINVAL; | 872 | return -EINVAL; |
885 | break; | 873 | |
886 | } | ||
887 | |||
888 | for (i = 0; i < MAX_NR_CONSOLES; i++) { | 874 | for (i = 0; i < MAX_NR_CONSOLES; i++) { |
889 | if (!vc_cons[i].d) | 875 | if (!vc_cons[i].d) |
890 | continue; | 876 | continue; |
891 | console_lock(); | 877 | console_lock(); |
892 | if (vlin) | 878 | if (v.v_vlin) |
893 | vc_cons[i].d->vc_scan_lines = vlin; | 879 | vc_cons[i].d->vc_scan_lines = v.v_vlin; |
894 | if (clin) | 880 | if (v.v_clin) |
895 | vc_cons[i].d->vc_font.height = clin; | 881 | vc_cons[i].d->vc_font.height = v.v_clin; |
896 | vc_cons[i].d->vc_resize_user = 1; | 882 | vc_cons[i].d->vc_resize_user = 1; |
897 | vc_resize(vc_cons[i].d, cc, ll); | 883 | vc_resize(vc_cons[i].d, v.v_cols, v.v_rows); |
898 | console_unlock(); | 884 | console_unlock(); |
899 | } | 885 | } |
900 | break; | 886 | break; |
@@ -1297,20 +1297,10 @@ static bool aio_read_events(struct kioctx *ctx, long min_nr, long nr, | |||
1297 | 1297 | ||
1298 | static long read_events(struct kioctx *ctx, long min_nr, long nr, | 1298 | static long read_events(struct kioctx *ctx, long min_nr, long nr, |
1299 | struct io_event __user *event, | 1299 | struct io_event __user *event, |
1300 | struct timespec __user *timeout) | 1300 | ktime_t until) |
1301 | { | 1301 | { |
1302 | ktime_t until = KTIME_MAX; | ||
1303 | long ret = 0; | 1302 | long ret = 0; |
1304 | 1303 | ||
1305 | if (timeout) { | ||
1306 | struct timespec ts; | ||
1307 | |||
1308 | if (unlikely(copy_from_user(&ts, timeout, sizeof(ts)))) | ||
1309 | return -EFAULT; | ||
1310 | |||
1311 | until = timespec_to_ktime(ts); | ||
1312 | } | ||
1313 | |||
1314 | /* | 1304 | /* |
1315 | * Note that aio_read_events() is being called as the conditional - i.e. | 1305 | * Note that aio_read_events() is being called as the conditional - i.e. |
1316 | * we're calling it after prepare_to_wait() has set task state to | 1306 | * we're calling it after prepare_to_wait() has set task state to |
@@ -1826,6 +1816,25 @@ SYSCALL_DEFINE3(io_cancel, aio_context_t, ctx_id, struct iocb __user *, iocb, | |||
1826 | return ret; | 1816 | return ret; |
1827 | } | 1817 | } |
1828 | 1818 | ||
1819 | static long do_io_getevents(aio_context_t ctx_id, | ||
1820 | long min_nr, | ||
1821 | long nr, | ||
1822 | struct io_event __user *events, | ||
1823 | struct timespec64 *ts) | ||
1824 | { | ||
1825 | ktime_t until = ts ? timespec64_to_ktime(*ts) : KTIME_MAX; | ||
1826 | struct kioctx *ioctx = lookup_ioctx(ctx_id); | ||
1827 | long ret = -EINVAL; | ||
1828 | |||
1829 | if (likely(ioctx)) { | ||
1830 | if (likely(min_nr <= nr && min_nr >= 0)) | ||
1831 | ret = read_events(ioctx, min_nr, nr, events, until); | ||
1832 | percpu_ref_put(&ioctx->users); | ||
1833 | } | ||
1834 | |||
1835 | return ret; | ||
1836 | } | ||
1837 | |||
1829 | /* io_getevents: | 1838 | /* io_getevents: |
1830 | * Attempts to read at least min_nr events and up to nr events from | 1839 | * Attempts to read at least min_nr events and up to nr events from |
1831 | * the completion queue for the aio_context specified by ctx_id. If | 1840 | * the completion queue for the aio_context specified by ctx_id. If |
@@ -1844,15 +1853,14 @@ SYSCALL_DEFINE5(io_getevents, aio_context_t, ctx_id, | |||
1844 | struct io_event __user *, events, | 1853 | struct io_event __user *, events, |
1845 | struct timespec __user *, timeout) | 1854 | struct timespec __user *, timeout) |
1846 | { | 1855 | { |
1847 | struct kioctx *ioctx = lookup_ioctx(ctx_id); | 1856 | struct timespec64 ts; |
1848 | long ret = -EINVAL; | ||
1849 | 1857 | ||
1850 | if (likely(ioctx)) { | 1858 | if (timeout) { |
1851 | if (likely(min_nr <= nr && min_nr >= 0)) | 1859 | if (unlikely(get_timespec64(&ts, timeout))) |
1852 | ret = read_events(ioctx, min_nr, nr, events, timeout); | 1860 | return -EFAULT; |
1853 | percpu_ref_put(&ioctx->users); | ||
1854 | } | 1861 | } |
1855 | return ret; | 1862 | |
1863 | return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &ts : NULL); | ||
1856 | } | 1864 | } |
1857 | 1865 | ||
1858 | #ifdef CONFIG_COMPAT | 1866 | #ifdef CONFIG_COMPAT |
@@ -1862,17 +1870,14 @@ COMPAT_SYSCALL_DEFINE5(io_getevents, compat_aio_context_t, ctx_id, | |||
1862 | struct io_event __user *, events, | 1870 | struct io_event __user *, events, |
1863 | struct compat_timespec __user *, timeout) | 1871 | struct compat_timespec __user *, timeout) |
1864 | { | 1872 | { |
1865 | struct timespec t; | 1873 | struct timespec64 t; |
1866 | struct timespec __user *ut = NULL; | ||
1867 | 1874 | ||
1868 | if (timeout) { | 1875 | if (timeout) { |
1869 | if (compat_get_timespec(&t, timeout)) | 1876 | if (compat_get_timespec64(&t, timeout)) |
1870 | return -EFAULT; | 1877 | return -EFAULT; |
1871 | 1878 | ||
1872 | ut = compat_alloc_user_space(sizeof(*ut)); | ||
1873 | if (copy_to_user(ut, &t, sizeof(t))) | ||
1874 | return -EFAULT; | ||
1875 | } | 1879 | } |
1876 | return sys_io_getevents(ctx_id, min_nr, nr, events, ut); | 1880 | |
1881 | return do_io_getevents(ctx_id, min_nr, nr, events, timeout ? &t : NULL); | ||
1877 | } | 1882 | } |
1878 | #endif | 1883 | #endif |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index bd5d91e119ca..f95aa0b2e9c0 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -54,8 +54,6 @@ | |||
54 | #include <linux/if_tun.h> | 54 | #include <linux/if_tun.h> |
55 | #include <linux/ctype.h> | 55 | #include <linux/ctype.h> |
56 | #include <linux/syscalls.h> | 56 | #include <linux/syscalls.h> |
57 | #include <linux/i2c.h> | ||
58 | #include <linux/i2c-dev.h> | ||
59 | #include <linux/atalk.h> | 57 | #include <linux/atalk.h> |
60 | #include <linux/gfp.h> | 58 | #include <linux/gfp.h> |
61 | #include <linux/cec.h> | 59 | #include <linux/cec.h> |
@@ -137,22 +135,6 @@ static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
137 | return vfs_ioctl(file, cmd, arg); | 135 | return vfs_ioctl(file, cmd, arg); |
138 | } | 136 | } |
139 | 137 | ||
140 | static int w_long(struct file *file, | ||
141 | unsigned int cmd, compat_ulong_t __user *argp) | ||
142 | { | ||
143 | int err; | ||
144 | unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); | ||
145 | |||
146 | if (valp == NULL) | ||
147 | return -EFAULT; | ||
148 | err = do_ioctl(file, cmd, (unsigned long)valp); | ||
149 | if (err) | ||
150 | return err; | ||
151 | if (convert_in_user(valp, argp)) | ||
152 | return -EFAULT; | ||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | struct compat_video_event { | 138 | struct compat_video_event { |
157 | int32_t type; | 139 | int32_t type; |
158 | compat_time_t timestamp; | 140 | compat_time_t timestamp; |
@@ -671,96 +653,6 @@ static int serial_struct_ioctl(struct file *file, | |||
671 | return err; | 653 | return err; |
672 | } | 654 | } |
673 | 655 | ||
674 | /* | ||
675 | * I2C layer ioctls | ||
676 | */ | ||
677 | |||
678 | struct i2c_msg32 { | ||
679 | u16 addr; | ||
680 | u16 flags; | ||
681 | u16 len; | ||
682 | compat_caddr_t buf; | ||
683 | }; | ||
684 | |||
685 | struct i2c_rdwr_ioctl_data32 { | ||
686 | compat_caddr_t msgs; /* struct i2c_msg __user *msgs */ | ||
687 | u32 nmsgs; | ||
688 | }; | ||
689 | |||
690 | struct i2c_smbus_ioctl_data32 { | ||
691 | u8 read_write; | ||
692 | u8 command; | ||
693 | u32 size; | ||
694 | compat_caddr_t data; /* union i2c_smbus_data *data */ | ||
695 | }; | ||
696 | |||
697 | struct i2c_rdwr_aligned { | ||
698 | struct i2c_rdwr_ioctl_data cmd; | ||
699 | struct i2c_msg msgs[0]; | ||
700 | }; | ||
701 | |||
702 | static int do_i2c_rdwr_ioctl(struct file *file, | ||
703 | unsigned int cmd, struct i2c_rdwr_ioctl_data32 __user *udata) | ||
704 | { | ||
705 | struct i2c_rdwr_aligned __user *tdata; | ||
706 | struct i2c_msg __user *tmsgs; | ||
707 | struct i2c_msg32 __user *umsgs; | ||
708 | compat_caddr_t datap; | ||
709 | u32 nmsgs; | ||
710 | int i; | ||
711 | |||
712 | if (get_user(nmsgs, &udata->nmsgs)) | ||
713 | return -EFAULT; | ||
714 | if (nmsgs > I2C_RDWR_IOCTL_MAX_MSGS) | ||
715 | return -EINVAL; | ||
716 | |||
717 | if (get_user(datap, &udata->msgs)) | ||
718 | return -EFAULT; | ||
719 | umsgs = compat_ptr(datap); | ||
720 | |||
721 | tdata = compat_alloc_user_space(sizeof(*tdata) + | ||
722 | nmsgs * sizeof(struct i2c_msg)); | ||
723 | tmsgs = &tdata->msgs[0]; | ||
724 | |||
725 | if (put_user(nmsgs, &tdata->cmd.nmsgs) || | ||
726 | put_user(tmsgs, &tdata->cmd.msgs)) | ||
727 | return -EFAULT; | ||
728 | |||
729 | for (i = 0; i < nmsgs; i++) { | ||
730 | if (copy_in_user(&tmsgs[i].addr, &umsgs[i].addr, 3*sizeof(u16))) | ||
731 | return -EFAULT; | ||
732 | if (get_user(datap, &umsgs[i].buf) || | ||
733 | put_user(compat_ptr(datap), &tmsgs[i].buf)) | ||
734 | return -EFAULT; | ||
735 | } | ||
736 | return do_ioctl(file, cmd, (unsigned long)tdata); | ||
737 | } | ||
738 | |||
739 | static int do_i2c_smbus_ioctl(struct file *file, | ||
740 | unsigned int cmd, struct i2c_smbus_ioctl_data32 __user *udata) | ||
741 | { | ||
742 | struct i2c_smbus_ioctl_data __user *tdata; | ||
743 | union { | ||
744 | /* beginnings of those have identical layouts */ | ||
745 | struct i2c_smbus_ioctl_data32 data32; | ||
746 | struct i2c_smbus_ioctl_data data; | ||
747 | } v; | ||
748 | |||
749 | tdata = compat_alloc_user_space(sizeof(*tdata)); | ||
750 | if (tdata == NULL) | ||
751 | return -ENOMEM; | ||
752 | |||
753 | memset(&v, 0, sizeof(v)); | ||
754 | if (copy_from_user(&v.data32, udata, sizeof(v.data32))) | ||
755 | return -EFAULT; | ||
756 | v.data.data = compat_ptr(v.data32.data); | ||
757 | |||
758 | if (copy_to_user(tdata, &v.data, sizeof(v.data))) | ||
759 | return -EFAULT; | ||
760 | |||
761 | return do_ioctl(file, cmd, (unsigned long)tdata); | ||
762 | } | ||
763 | |||
764 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) | 656 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) |
765 | #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) | 657 | #define RTC_IRQP_SET32 _IOW('p', 0x0c, compat_ulong_t) |
766 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) | 658 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) |
@@ -1283,13 +1175,6 @@ COMPATIBLE_IOCTL(PCIIOC_CONTROLLER) | |||
1283 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) | 1175 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_IO) |
1284 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) | 1176 | COMPATIBLE_IOCTL(PCIIOC_MMAP_IS_MEM) |
1285 | COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) | 1177 | COMPATIBLE_IOCTL(PCIIOC_WRITE_COMBINE) |
1286 | /* i2c */ | ||
1287 | COMPATIBLE_IOCTL(I2C_SLAVE) | ||
1288 | COMPATIBLE_IOCTL(I2C_SLAVE_FORCE) | ||
1289 | COMPATIBLE_IOCTL(I2C_TENBIT) | ||
1290 | COMPATIBLE_IOCTL(I2C_PEC) | ||
1291 | COMPATIBLE_IOCTL(I2C_RETRIES) | ||
1292 | COMPATIBLE_IOCTL(I2C_TIMEOUT) | ||
1293 | /* hiddev */ | 1178 | /* hiddev */ |
1294 | COMPATIBLE_IOCTL(HIDIOCGVERSION) | 1179 | COMPATIBLE_IOCTL(HIDIOCGVERSION) |
1295 | COMPATIBLE_IOCTL(HIDIOCAPPLICATION) | 1180 | COMPATIBLE_IOCTL(HIDIOCAPPLICATION) |
@@ -1464,13 +1349,6 @@ static long do_ioctl_trans(unsigned int cmd, | |||
1464 | case TIOCGSERIAL: | 1349 | case TIOCGSERIAL: |
1465 | case TIOCSSERIAL: | 1350 | case TIOCSSERIAL: |
1466 | return serial_struct_ioctl(file, cmd, argp); | 1351 | return serial_struct_ioctl(file, cmd, argp); |
1467 | /* i2c */ | ||
1468 | case I2C_FUNCS: | ||
1469 | return w_long(file, cmd, argp); | ||
1470 | case I2C_RDWR: | ||
1471 | return do_i2c_rdwr_ioctl(file, cmd, argp); | ||
1472 | case I2C_SMBUS: | ||
1473 | return do_i2c_smbus_ioctl(file, cmd, argp); | ||
1474 | /* Not implemented in the native kernel */ | 1352 | /* Not implemented in the native kernel */ |
1475 | case RTC_IRQP_READ32: | 1353 | case RTC_IRQP_READ32: |
1476 | case RTC_IRQP_SET32: | 1354 | case RTC_IRQP_SET32: |
diff --git a/fs/coredump.c b/fs/coredump.c index 52c63d6c9143..1e2c87acac9b 100644 --- a/fs/coredump.c +++ b/fs/coredump.c | |||
@@ -680,16 +680,11 @@ void do_coredump(const siginfo_t *siginfo) | |||
680 | * privs and don't want to unlink another user's coredump. | 680 | * privs and don't want to unlink another user's coredump. |
681 | */ | 681 | */ |
682 | if (!need_suid_safe) { | 682 | if (!need_suid_safe) { |
683 | mm_segment_t old_fs; | ||
684 | |||
685 | old_fs = get_fs(); | ||
686 | set_fs(KERNEL_DS); | ||
687 | /* | 683 | /* |
688 | * If it doesn't exist, that's fine. If there's some | 684 | * If it doesn't exist, that's fine. If there's some |
689 | * other problem, we'll catch it at the filp_open(). | 685 | * other problem, we'll catch it at the filp_open(). |
690 | */ | 686 | */ |
691 | (void) sys_unlink((const char __user *)cn.corename); | 687 | do_unlinkat(AT_FDCWD, getname_kernel(cn.corename)); |
692 | set_fs(old_fs); | ||
693 | } | 688 | } |
694 | 689 | ||
695 | /* | 690 | /* |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 2fabd19cdeea..396a3c075fd4 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -2259,7 +2259,6 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, | |||
2259 | compat_size_t, sigsetsize) | 2259 | compat_size_t, sigsetsize) |
2260 | { | 2260 | { |
2261 | long err; | 2261 | long err; |
2262 | compat_sigset_t csigmask; | ||
2263 | sigset_t ksigmask, sigsaved; | 2262 | sigset_t ksigmask, sigsaved; |
2264 | 2263 | ||
2265 | /* | 2264 | /* |
@@ -2269,9 +2268,8 @@ COMPAT_SYSCALL_DEFINE6(epoll_pwait, int, epfd, | |||
2269 | if (sigmask) { | 2268 | if (sigmask) { |
2270 | if (sigsetsize != sizeof(compat_sigset_t)) | 2269 | if (sigsetsize != sizeof(compat_sigset_t)) |
2271 | return -EINVAL; | 2270 | return -EINVAL; |
2272 | if (copy_from_user(&csigmask, sigmask, sizeof(csigmask))) | 2271 | if (get_compat_sigset(&ksigmask, sigmask)) |
2273 | return -EFAULT; | 2272 | return -EFAULT; |
2274 | sigset_from_compat(&ksigmask, &csigmask); | ||
2275 | sigsaved = current->blocked; | 2273 | sigsaved = current->blocked; |
2276 | set_current_blocked(&ksigmask); | 2274 | set_current_blocked(&ksigmask); |
2277 | } | 2275 | } |
diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c index b7558f292420..1eec25014f62 100644 --- a/fs/ext4/ioctl.c +++ b/fs/ext4/ioctl.c | |||
@@ -592,6 +592,44 @@ static int ext4_ioc_getfsmap(struct super_block *sb, | |||
592 | return 0; | 592 | return 0; |
593 | } | 593 | } |
594 | 594 | ||
595 | static long ext4_ioctl_group_add(struct file *file, | ||
596 | struct ext4_new_group_data *input) | ||
597 | { | ||
598 | struct super_block *sb = file_inode(file)->i_sb; | ||
599 | int err, err2=0; | ||
600 | |||
601 | err = ext4_resize_begin(sb); | ||
602 | if (err) | ||
603 | return err; | ||
604 | |||
605 | if (ext4_has_feature_bigalloc(sb)) { | ||
606 | ext4_msg(sb, KERN_ERR, | ||
607 | "Online resizing not supported with bigalloc"); | ||
608 | err = -EOPNOTSUPP; | ||
609 | goto group_add_out; | ||
610 | } | ||
611 | |||
612 | err = mnt_want_write_file(file); | ||
613 | if (err) | ||
614 | goto group_add_out; | ||
615 | |||
616 | err = ext4_group_add(sb, input); | ||
617 | if (EXT4_SB(sb)->s_journal) { | ||
618 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | ||
619 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); | ||
620 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | ||
621 | } | ||
622 | if (err == 0) | ||
623 | err = err2; | ||
624 | mnt_drop_write_file(file); | ||
625 | if (!err && ext4_has_group_desc_csum(sb) && | ||
626 | test_opt(sb, INIT_INODE_TABLE)) | ||
627 | err = ext4_register_li_request(sb, input->group); | ||
628 | group_add_out: | ||
629 | ext4_resize_end(sb); | ||
630 | return err; | ||
631 | } | ||
632 | |||
595 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) | 633 | long ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
596 | { | 634 | { |
597 | struct inode *inode = file_inode(filp); | 635 | struct inode *inode = file_inode(filp); |
@@ -776,44 +814,12 @@ mext_out: | |||
776 | 814 | ||
777 | case EXT4_IOC_GROUP_ADD: { | 815 | case EXT4_IOC_GROUP_ADD: { |
778 | struct ext4_new_group_data input; | 816 | struct ext4_new_group_data input; |
779 | int err, err2=0; | ||
780 | |||
781 | err = ext4_resize_begin(sb); | ||
782 | if (err) | ||
783 | return err; | ||
784 | 817 | ||
785 | if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, | 818 | if (copy_from_user(&input, (struct ext4_new_group_input __user *)arg, |
786 | sizeof(input))) { | 819 | sizeof(input))) |
787 | err = -EFAULT; | 820 | return -EFAULT; |
788 | goto group_add_out; | ||
789 | } | ||
790 | |||
791 | if (ext4_has_feature_bigalloc(sb)) { | ||
792 | ext4_msg(sb, KERN_ERR, | ||
793 | "Online resizing not supported with bigalloc"); | ||
794 | err = -EOPNOTSUPP; | ||
795 | goto group_add_out; | ||
796 | } | ||
797 | |||
798 | err = mnt_want_write_file(filp); | ||
799 | if (err) | ||
800 | goto group_add_out; | ||
801 | 821 | ||
802 | err = ext4_group_add(sb, &input); | 822 | return ext4_ioctl_group_add(filp, &input); |
803 | if (EXT4_SB(sb)->s_journal) { | ||
804 | jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal); | ||
805 | err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal); | ||
806 | jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal); | ||
807 | } | ||
808 | if (err == 0) | ||
809 | err = err2; | ||
810 | mnt_drop_write_file(filp); | ||
811 | if (!err && ext4_has_group_desc_csum(sb) && | ||
812 | test_opt(sb, INIT_INODE_TABLE)) | ||
813 | err = ext4_register_li_request(sb, input.group); | ||
814 | group_add_out: | ||
815 | ext4_resize_end(sb); | ||
816 | return err; | ||
817 | } | 823 | } |
818 | 824 | ||
819 | case EXT4_IOC_MIGRATE: | 825 | case EXT4_IOC_MIGRATE: |
@@ -1078,8 +1084,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1078 | break; | 1084 | break; |
1079 | case EXT4_IOC32_GROUP_ADD: { | 1085 | case EXT4_IOC32_GROUP_ADD: { |
1080 | struct compat_ext4_new_group_input __user *uinput; | 1086 | struct compat_ext4_new_group_input __user *uinput; |
1081 | struct ext4_new_group_input input; | 1087 | struct ext4_new_group_data input; |
1082 | mm_segment_t old_fs; | ||
1083 | int err; | 1088 | int err; |
1084 | 1089 | ||
1085 | uinput = compat_ptr(arg); | 1090 | uinput = compat_ptr(arg); |
@@ -1092,12 +1097,7 @@ long ext4_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
1092 | &uinput->reserved_blocks); | 1097 | &uinput->reserved_blocks); |
1093 | if (err) | 1098 | if (err) |
1094 | return -EFAULT; | 1099 | return -EFAULT; |
1095 | old_fs = get_fs(); | 1100 | return ext4_ioctl_group_add(file, &input); |
1096 | set_fs(KERNEL_DS); | ||
1097 | err = ext4_ioctl(file, EXT4_IOC_GROUP_ADD, | ||
1098 | (unsigned long) &input); | ||
1099 | set_fs(old_fs); | ||
1100 | return err; | ||
1101 | } | 1101 | } |
1102 | case EXT4_IOC_MOVE_EXT: | 1102 | case EXT4_IOC_MOVE_EXT: |
1103 | case EXT4_IOC_RESIZE_FS: | 1103 | case EXT4_IOC_RESIZE_FS: |
diff --git a/fs/internal.h b/fs/internal.h index 48cee21b4f14..df262f41a0ef 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -55,6 +55,7 @@ extern void __init chrdev_init(void); | |||
55 | extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *); | 55 | extern int user_path_mountpoint_at(int, const char __user *, unsigned int, struct path *); |
56 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, | 56 | extern int vfs_path_lookup(struct dentry *, struct vfsmount *, |
57 | const char *, unsigned int, struct path *); | 57 | const char *, unsigned int, struct path *); |
58 | long do_unlinkat(int dfd, struct filename *name); | ||
58 | 59 | ||
59 | /* | 60 | /* |
60 | * namespace.c | 61 | * namespace.c |
diff --git a/fs/namei.c b/fs/namei.c index 5424b10cfdc4..287781363763 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -4010,10 +4010,9 @@ EXPORT_SYMBOL(vfs_unlink); | |||
4010 | * writeout happening, and we don't want to prevent access to the directory | 4010 | * writeout happening, and we don't want to prevent access to the directory |
4011 | * while waiting on the I/O. | 4011 | * while waiting on the I/O. |
4012 | */ | 4012 | */ |
4013 | static long do_unlinkat(int dfd, const char __user *pathname) | 4013 | long do_unlinkat(int dfd, struct filename *name) |
4014 | { | 4014 | { |
4015 | int error; | 4015 | int error; |
4016 | struct filename *name; | ||
4017 | struct dentry *dentry; | 4016 | struct dentry *dentry; |
4018 | struct path path; | 4017 | struct path path; |
4019 | struct qstr last; | 4018 | struct qstr last; |
@@ -4022,8 +4021,7 @@ static long do_unlinkat(int dfd, const char __user *pathname) | |||
4022 | struct inode *delegated_inode = NULL; | 4021 | struct inode *delegated_inode = NULL; |
4023 | unsigned int lookup_flags = 0; | 4022 | unsigned int lookup_flags = 0; |
4024 | retry: | 4023 | retry: |
4025 | name = filename_parentat(dfd, getname(pathname), lookup_flags, | 4024 | name = filename_parentat(dfd, name, lookup_flags, &path, &last, &type); |
4026 | &path, &last, &type); | ||
4027 | if (IS_ERR(name)) | 4025 | if (IS_ERR(name)) |
4028 | return PTR_ERR(name); | 4026 | return PTR_ERR(name); |
4029 | 4027 | ||
@@ -4065,12 +4063,12 @@ exit2: | |||
4065 | mnt_drop_write(path.mnt); | 4063 | mnt_drop_write(path.mnt); |
4066 | exit1: | 4064 | exit1: |
4067 | path_put(&path); | 4065 | path_put(&path); |
4068 | putname(name); | ||
4069 | if (retry_estale(error, lookup_flags)) { | 4066 | if (retry_estale(error, lookup_flags)) { |
4070 | lookup_flags |= LOOKUP_REVAL; | 4067 | lookup_flags |= LOOKUP_REVAL; |
4071 | inode = NULL; | 4068 | inode = NULL; |
4072 | goto retry; | 4069 | goto retry; |
4073 | } | 4070 | } |
4071 | putname(name); | ||
4074 | return error; | 4072 | return error; |
4075 | 4073 | ||
4076 | slashes: | 4074 | slashes: |
@@ -4091,12 +4089,12 @@ SYSCALL_DEFINE3(unlinkat, int, dfd, const char __user *, pathname, int, flag) | |||
4091 | if (flag & AT_REMOVEDIR) | 4089 | if (flag & AT_REMOVEDIR) |
4092 | return do_rmdir(dfd, pathname); | 4090 | return do_rmdir(dfd, pathname); |
4093 | 4091 | ||
4094 | return do_unlinkat(dfd, pathname); | 4092 | return do_unlinkat(dfd, getname(pathname)); |
4095 | } | 4093 | } |
4096 | 4094 | ||
4097 | SYSCALL_DEFINE1(unlink, const char __user *, pathname) | 4095 | SYSCALL_DEFINE1(unlink, const char __user *, pathname) |
4098 | { | 4096 | { |
4099 | return do_unlinkat(AT_FDCWD, pathname); | 4097 | return do_unlinkat(AT_FDCWD, getname(pathname)); |
4100 | } | 4098 | } |
4101 | 4099 | ||
4102 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) | 4100 | int vfs_symlink(struct inode *dir, struct dentry *dentry, const char *oldname) |
diff --git a/fs/select.c b/fs/select.c index 063067e606ca..6de493bb42a4 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -292,8 +292,7 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, | |||
292 | void __user *p, | 292 | void __user *p, |
293 | int timeval, int ret) | 293 | int timeval, int ret) |
294 | { | 294 | { |
295 | struct timespec64 rts64; | 295 | struct timespec64 rts; |
296 | struct timespec rts; | ||
297 | struct timeval rtv; | 296 | struct timeval rtv; |
298 | 297 | ||
299 | if (!p) | 298 | if (!p) |
@@ -306,23 +305,22 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, | |||
306 | if (!end_time->tv_sec && !end_time->tv_nsec) | 305 | if (!end_time->tv_sec && !end_time->tv_nsec) |
307 | return ret; | 306 | return ret; |
308 | 307 | ||
309 | ktime_get_ts64(&rts64); | 308 | ktime_get_ts64(&rts); |
310 | rts64 = timespec64_sub(*end_time, rts64); | 309 | rts = timespec64_sub(*end_time, rts); |
311 | if (rts64.tv_sec < 0) | 310 | if (rts.tv_sec < 0) |
312 | rts64.tv_sec = rts64.tv_nsec = 0; | 311 | rts.tv_sec = rts.tv_nsec = 0; |
313 | 312 | ||
314 | rts = timespec64_to_timespec(rts64); | ||
315 | 313 | ||
316 | if (timeval) { | 314 | if (timeval) { |
317 | if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) | 315 | if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) |
318 | memset(&rtv, 0, sizeof(rtv)); | 316 | memset(&rtv, 0, sizeof(rtv)); |
319 | rtv.tv_sec = rts64.tv_sec; | 317 | rtv.tv_sec = rts.tv_sec; |
320 | rtv.tv_usec = rts64.tv_nsec / NSEC_PER_USEC; | 318 | rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC; |
321 | 319 | ||
322 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | 320 | if (!copy_to_user(p, &rtv, sizeof(rtv))) |
323 | return ret; | 321 | return ret; |
324 | 322 | ||
325 | } else if (!copy_to_user(p, &rts, sizeof(rts))) | 323 | } else if (!put_timespec64(&rts, p)) |
326 | return ret; | 324 | return ret; |
327 | 325 | ||
328 | /* | 326 | /* |
@@ -705,17 +703,15 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, | |||
705 | const sigset_t __user *sigmask, size_t sigsetsize) | 703 | const sigset_t __user *sigmask, size_t sigsetsize) |
706 | { | 704 | { |
707 | sigset_t ksigmask, sigsaved; | 705 | sigset_t ksigmask, sigsaved; |
708 | struct timespec ts; | 706 | struct timespec64 ts, end_time, *to = NULL; |
709 | struct timespec64 ts64, end_time, *to = NULL; | ||
710 | int ret; | 707 | int ret; |
711 | 708 | ||
712 | if (tsp) { | 709 | if (tsp) { |
713 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 710 | if (get_timespec64(&ts, tsp)) |
714 | return -EFAULT; | 711 | return -EFAULT; |
715 | ts64 = timespec_to_timespec64(ts); | ||
716 | 712 | ||
717 | to = &end_time; | 713 | to = &end_time; |
718 | if (poll_select_set_timeout(to, ts64.tv_sec, ts64.tv_nsec)) | 714 | if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) |
719 | return -EINVAL; | 715 | return -EINVAL; |
720 | } | 716 | } |
721 | 717 | ||
@@ -1052,12 +1048,11 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
1052 | size_t, sigsetsize) | 1048 | size_t, sigsetsize) |
1053 | { | 1049 | { |
1054 | sigset_t ksigmask, sigsaved; | 1050 | sigset_t ksigmask, sigsaved; |
1055 | struct timespec ts; | 1051 | struct timespec64 ts, end_time, *to = NULL; |
1056 | struct timespec64 end_time, *to = NULL; | ||
1057 | int ret; | 1052 | int ret; |
1058 | 1053 | ||
1059 | if (tsp) { | 1054 | if (tsp) { |
1060 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1055 | if (get_timespec64(&ts, tsp)) |
1061 | return -EFAULT; | 1056 | return -EFAULT; |
1062 | 1057 | ||
1063 | to = &end_time; | 1058 | to = &end_time; |
@@ -1103,10 +1098,10 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
1103 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) | 1098 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) |
1104 | 1099 | ||
1105 | static | 1100 | static |
1106 | int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | 1101 | int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *p, |
1107 | int timeval, int ret) | 1102 | int timeval, int ret) |
1108 | { | 1103 | { |
1109 | struct timespec ts; | 1104 | struct timespec64 ts; |
1110 | 1105 | ||
1111 | if (!p) | 1106 | if (!p) |
1112 | return ret; | 1107 | return ret; |
@@ -1118,8 +1113,8 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | |||
1118 | if (!end_time->tv_sec && !end_time->tv_nsec) | 1113 | if (!end_time->tv_sec && !end_time->tv_nsec) |
1119 | return ret; | 1114 | return ret; |
1120 | 1115 | ||
1121 | ktime_get_ts(&ts); | 1116 | ktime_get_ts64(&ts); |
1122 | ts = timespec_sub(*end_time, ts); | 1117 | ts = timespec64_sub(*end_time, ts); |
1123 | if (ts.tv_sec < 0) | 1118 | if (ts.tv_sec < 0) |
1124 | ts.tv_sec = ts.tv_nsec = 0; | 1119 | ts.tv_sec = ts.tv_nsec = 0; |
1125 | 1120 | ||
@@ -1132,12 +1127,7 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | |||
1132 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | 1127 | if (!copy_to_user(p, &rtv, sizeof(rtv))) |
1133 | return ret; | 1128 | return ret; |
1134 | } else { | 1129 | } else { |
1135 | struct compat_timespec rts; | 1130 | if (!compat_put_timespec64(&ts, p)) |
1136 | |||
1137 | rts.tv_sec = ts.tv_sec; | ||
1138 | rts.tv_nsec = ts.tv_nsec; | ||
1139 | |||
1140 | if (!copy_to_user(p, &rts, sizeof(rts))) | ||
1141 | return ret; | 1131 | return ret; |
1142 | } | 1132 | } |
1143 | /* | 1133 | /* |
@@ -1195,7 +1185,7 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1195 | */ | 1185 | */ |
1196 | static int compat_core_sys_select(int n, compat_ulong_t __user *inp, | 1186 | static int compat_core_sys_select(int n, compat_ulong_t __user *inp, |
1197 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1187 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
1198 | struct timespec *end_time) | 1188 | struct timespec64 *end_time) |
1199 | { | 1189 | { |
1200 | fd_set_bits fds; | 1190 | fd_set_bits fds; |
1201 | void *bits; | 1191 | void *bits; |
@@ -1268,7 +1258,7 @@ COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp, | |||
1268 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, | 1258 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, |
1269 | struct compat_timeval __user *, tvp) | 1259 | struct compat_timeval __user *, tvp) |
1270 | { | 1260 | { |
1271 | struct timespec end_time, *to = NULL; | 1261 | struct timespec64 end_time, *to = NULL; |
1272 | struct compat_timeval tv; | 1262 | struct compat_timeval tv; |
1273 | int ret; | 1263 | int ret; |
1274 | 1264 | ||
@@ -1312,14 +1302,12 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, | |||
1312 | struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, | 1302 | struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, |
1313 | compat_size_t sigsetsize) | 1303 | compat_size_t sigsetsize) |
1314 | { | 1304 | { |
1315 | compat_sigset_t ss32; | ||
1316 | sigset_t ksigmask, sigsaved; | 1305 | sigset_t ksigmask, sigsaved; |
1317 | struct compat_timespec ts; | 1306 | struct timespec64 ts, end_time, *to = NULL; |
1318 | struct timespec end_time, *to = NULL; | ||
1319 | int ret; | 1307 | int ret; |
1320 | 1308 | ||
1321 | if (tsp) { | 1309 | if (tsp) { |
1322 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1310 | if (compat_get_timespec64(&ts, tsp)) |
1323 | return -EFAULT; | 1311 | return -EFAULT; |
1324 | 1312 | ||
1325 | to = &end_time; | 1313 | to = &end_time; |
@@ -1330,9 +1318,8 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, | |||
1330 | if (sigmask) { | 1318 | if (sigmask) { |
1331 | if (sigsetsize != sizeof(compat_sigset_t)) | 1319 | if (sigsetsize != sizeof(compat_sigset_t)) |
1332 | return -EINVAL; | 1320 | return -EINVAL; |
1333 | if (copy_from_user(&ss32, sigmask, sizeof(ss32))) | 1321 | if (get_compat_sigset(&ksigmask, sigmask)) |
1334 | return -EFAULT; | 1322 | return -EFAULT; |
1335 | sigset_from_compat(&ksigmask, &ss32); | ||
1336 | 1323 | ||
1337 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 1324 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
1338 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | 1325 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); |
@@ -1381,14 +1368,12 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, | |||
1381 | unsigned int, nfds, struct compat_timespec __user *, tsp, | 1368 | unsigned int, nfds, struct compat_timespec __user *, tsp, |
1382 | const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) | 1369 | const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) |
1383 | { | 1370 | { |
1384 | compat_sigset_t ss32; | ||
1385 | sigset_t ksigmask, sigsaved; | 1371 | sigset_t ksigmask, sigsaved; |
1386 | struct compat_timespec ts; | 1372 | struct timespec64 ts, end_time, *to = NULL; |
1387 | struct timespec end_time, *to = NULL; | ||
1388 | int ret; | 1373 | int ret; |
1389 | 1374 | ||
1390 | if (tsp) { | 1375 | if (tsp) { |
1391 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1376 | if (compat_get_timespec64(&ts, tsp)) |
1392 | return -EFAULT; | 1377 | return -EFAULT; |
1393 | 1378 | ||
1394 | to = &end_time; | 1379 | to = &end_time; |
@@ -1399,9 +1384,8 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, | |||
1399 | if (sigmask) { | 1384 | if (sigmask) { |
1400 | if (sigsetsize != sizeof(compat_sigset_t)) | 1385 | if (sigsetsize != sizeof(compat_sigset_t)) |
1401 | return -EINVAL; | 1386 | return -EINVAL; |
1402 | if (copy_from_user(&ss32, sigmask, sizeof(ss32))) | 1387 | if (get_compat_sigset(&ksigmask, sigmask)) |
1403 | return -EFAULT; | 1388 | return -EFAULT; |
1404 | sigset_from_compat(&ksigmask, &ss32); | ||
1405 | 1389 | ||
1406 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 1390 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
1407 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | 1391 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); |
diff --git a/fs/signalfd.c b/fs/signalfd.c index 1c667af86da5..5f1ff8756595 100644 --- a/fs/signalfd.c +++ b/fs/signalfd.c | |||
@@ -313,15 +313,13 @@ COMPAT_SYSCALL_DEFINE4(signalfd4, int, ufd, | |||
313 | compat_size_t, sigsetsize, | 313 | compat_size_t, sigsetsize, |
314 | int, flags) | 314 | int, flags) |
315 | { | 315 | { |
316 | compat_sigset_t ss32; | ||
317 | sigset_t tmp; | 316 | sigset_t tmp; |
318 | sigset_t __user *ksigmask; | 317 | sigset_t __user *ksigmask; |
319 | 318 | ||
320 | if (sigsetsize != sizeof(compat_sigset_t)) | 319 | if (sigsetsize != sizeof(compat_sigset_t)) |
321 | return -EINVAL; | 320 | return -EINVAL; |
322 | if (copy_from_user(&ss32, sigmask, sizeof(ss32))) | 321 | if (get_compat_sigset(&tmp, sigmask)) |
323 | return -EFAULT; | 322 | return -EFAULT; |
324 | sigset_from_compat(&tmp, &ss32); | ||
325 | ksigmask = compat_alloc_user_space(sizeof(sigset_t)); | 323 | ksigmask = compat_alloc_user_space(sizeof(sigset_t)); |
326 | if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) | 324 | if (copy_to_user(ksigmask, &tmp, sizeof(sigset_t))) |
327 | return -EFAULT; | 325 | return -EFAULT; |
diff --git a/include/linux/compat.h b/include/linux/compat.h index 3e838a828459..0fc36406f32c 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h | |||
@@ -444,11 +444,6 @@ static inline int compat_timespec_compare(struct compat_timespec *lhs, | |||
444 | return lhs->tv_nsec - rhs->tv_nsec; | 444 | return lhs->tv_nsec - rhs->tv_nsec; |
445 | } | 445 | } |
446 | 446 | ||
447 | extern int get_compat_itimerspec(struct itimerspec *dst, | ||
448 | const struct compat_itimerspec __user *src); | ||
449 | extern int put_compat_itimerspec(struct compat_itimerspec __user *dst, | ||
450 | const struct itimerspec *src); | ||
451 | |||
452 | asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, | 447 | asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv, |
453 | struct timezone __user *tz); | 448 | struct timezone __user *tz); |
454 | asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, | 449 | asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, |
@@ -456,8 +451,9 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, | |||
456 | 451 | ||
457 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); | 452 | asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); |
458 | 453 | ||
459 | extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat); | 454 | extern int get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat); |
460 | extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set); | 455 | extern int put_compat_sigset(compat_sigset_t __user *compat, |
456 | const sigset_t *set, unsigned int size); | ||
461 | 457 | ||
462 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, | 458 | asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, |
463 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, | 459 | compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, |
diff --git a/kernel/compat.c b/kernel/compat.c index 772e038d04d9..d1cee656a7ed 100644 --- a/kernel/compat.c +++ b/kernel/compat.c | |||
@@ -367,24 +367,6 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len, | |||
367 | return ret; | 367 | return ret; |
368 | } | 368 | } |
369 | 369 | ||
370 | int get_compat_itimerspec(struct itimerspec *dst, | ||
371 | const struct compat_itimerspec __user *src) | ||
372 | { | ||
373 | if (__compat_get_timespec(&dst->it_interval, &src->it_interval) || | ||
374 | __compat_get_timespec(&dst->it_value, &src->it_value)) | ||
375 | return -EFAULT; | ||
376 | return 0; | ||
377 | } | ||
378 | |||
379 | int put_compat_itimerspec(struct compat_itimerspec __user *dst, | ||
380 | const struct itimerspec *src) | ||
381 | { | ||
382 | if (__compat_put_timespec(&src->it_interval, &dst->it_interval) || | ||
383 | __compat_put_timespec(&src->it_value, &dst->it_value)) | ||
384 | return -EFAULT; | ||
385 | return 0; | ||
386 | } | ||
387 | |||
388 | int get_compat_itimerspec64(struct itimerspec64 *its, | 370 | int get_compat_itimerspec64(struct itimerspec64 *its, |
389 | const struct compat_itimerspec __user *uits) | 371 | const struct compat_itimerspec __user *uits) |
390 | { | 372 | { |
@@ -485,27 +467,44 @@ Efault: | |||
485 | return -EFAULT; | 467 | return -EFAULT; |
486 | } | 468 | } |
487 | 469 | ||
488 | void | 470 | int |
489 | sigset_from_compat(sigset_t *set, const compat_sigset_t *compat) | 471 | get_compat_sigset(sigset_t *set, const compat_sigset_t __user *compat) |
490 | { | 472 | { |
473 | #ifdef __BIG_ENDIAN | ||
474 | compat_sigset_t v; | ||
475 | if (copy_from_user(&v, compat, sizeof(compat_sigset_t))) | ||
476 | return -EFAULT; | ||
491 | switch (_NSIG_WORDS) { | 477 | switch (_NSIG_WORDS) { |
492 | case 4: set->sig[3] = compat->sig[6] | (((long)compat->sig[7]) << 32 ); | 478 | case 4: set->sig[3] = v.sig[6] | (((long)v.sig[7]) << 32 ); |
493 | case 3: set->sig[2] = compat->sig[4] | (((long)compat->sig[5]) << 32 ); | 479 | case 3: set->sig[2] = v.sig[4] | (((long)v.sig[5]) << 32 ); |
494 | case 2: set->sig[1] = compat->sig[2] | (((long)compat->sig[3]) << 32 ); | 480 | case 2: set->sig[1] = v.sig[2] | (((long)v.sig[3]) << 32 ); |
495 | case 1: set->sig[0] = compat->sig[0] | (((long)compat->sig[1]) << 32 ); | 481 | case 1: set->sig[0] = v.sig[0] | (((long)v.sig[1]) << 32 ); |
496 | } | 482 | } |
483 | #else | ||
484 | if (copy_from_user(set, compat, sizeof(compat_sigset_t))) | ||
485 | return -EFAULT; | ||
486 | #endif | ||
487 | return 0; | ||
497 | } | 488 | } |
498 | EXPORT_SYMBOL_GPL(sigset_from_compat); | 489 | EXPORT_SYMBOL_GPL(get_compat_sigset); |
499 | 490 | ||
500 | void | 491 | int |
501 | sigset_to_compat(compat_sigset_t *compat, const sigset_t *set) | 492 | put_compat_sigset(compat_sigset_t __user *compat, const sigset_t *set, |
493 | unsigned int size) | ||
502 | { | 494 | { |
495 | /* size <= sizeof(compat_sigset_t) <= sizeof(sigset_t) */ | ||
496 | #ifdef __BIG_ENDIAN | ||
497 | compat_sigset_t v; | ||
503 | switch (_NSIG_WORDS) { | 498 | switch (_NSIG_WORDS) { |
504 | case 4: compat->sig[7] = (set->sig[3] >> 32); compat->sig[6] = set->sig[3]; | 499 | case 4: v.sig[7] = (set->sig[3] >> 32); v.sig[6] = set->sig[3]; |
505 | case 3: compat->sig[5] = (set->sig[2] >> 32); compat->sig[4] = set->sig[2]; | 500 | case 3: v.sig[5] = (set->sig[2] >> 32); v.sig[4] = set->sig[2]; |
506 | case 2: compat->sig[3] = (set->sig[1] >> 32); compat->sig[2] = set->sig[1]; | 501 | case 2: v.sig[3] = (set->sig[1] >> 32); v.sig[2] = set->sig[1]; |
507 | case 1: compat->sig[1] = (set->sig[0] >> 32); compat->sig[0] = set->sig[0]; | 502 | case 1: v.sig[1] = (set->sig[0] >> 32); v.sig[0] = set->sig[0]; |
508 | } | 503 | } |
504 | return copy_to_user(compat, &v, size) ? -EFAULT : 0; | ||
505 | #else | ||
506 | return copy_to_user(compat, set, size) ? -EFAULT : 0; | ||
507 | #endif | ||
509 | } | 508 | } |
510 | 509 | ||
511 | #ifdef CONFIG_NUMA | 510 | #ifdef CONFIG_NUMA |
@@ -563,22 +562,6 @@ COMPAT_SYSCALL_DEFINE4(migrate_pages, compat_pid_t, pid, | |||
563 | } | 562 | } |
564 | #endif | 563 | #endif |
565 | 564 | ||
566 | COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, | ||
567 | compat_pid_t, pid, | ||
568 | struct compat_timespec __user *, interval) | ||
569 | { | ||
570 | struct timespec t; | ||
571 | int ret; | ||
572 | mm_segment_t old_fs = get_fs(); | ||
573 | |||
574 | set_fs(KERNEL_DS); | ||
575 | ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t); | ||
576 | set_fs(old_fs); | ||
577 | if (compat_put_timespec(&t, interval)) | ||
578 | return -EFAULT; | ||
579 | return ret; | ||
580 | } | ||
581 | |||
582 | /* | 565 | /* |
583 | * Allocate user-space memory for the duration of a single system call, | 566 | * Allocate user-space memory for the duration of a single system call, |
584 | * in order to marshall parameters inside a compat thunk. | 567 | * in order to marshall parameters inside a compat thunk. |
diff --git a/kernel/sched/core.c b/kernel/sched/core.c index a092f350f3a2..75554f366fd3 100644 --- a/kernel/sched/core.c +++ b/kernel/sched/core.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/init_task.h> | 16 | #include <linux/init_task.h> |
17 | #include <linux/context_tracking.h> | 17 | #include <linux/context_tracking.h> |
18 | #include <linux/rcupdate_wait.h> | 18 | #include <linux/rcupdate_wait.h> |
19 | #include <linux/compat.h> | ||
19 | 20 | ||
20 | #include <linux/blkdev.h> | 21 | #include <linux/blkdev.h> |
21 | #include <linux/kprobes.h> | 22 | #include <linux/kprobes.h> |
@@ -5107,13 +5108,11 @@ SYSCALL_DEFINE1(sched_get_priority_min, int, policy) | |||
5107 | * Return: On success, 0 and the timeslice is in @interval. Otherwise, | 5108 | * Return: On success, 0 and the timeslice is in @interval. Otherwise, |
5108 | * an error code. | 5109 | * an error code. |
5109 | */ | 5110 | */ |
5110 | SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, | 5111 | static int sched_rr_get_interval(pid_t pid, struct timespec64 *t) |
5111 | struct timespec __user *, interval) | ||
5112 | { | 5112 | { |
5113 | struct task_struct *p; | 5113 | struct task_struct *p; |
5114 | unsigned int time_slice; | 5114 | unsigned int time_slice; |
5115 | struct rq_flags rf; | 5115 | struct rq_flags rf; |
5116 | struct timespec t; | ||
5117 | struct rq *rq; | 5116 | struct rq *rq; |
5118 | int retval; | 5117 | int retval; |
5119 | 5118 | ||
@@ -5137,15 +5136,40 @@ SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, | |||
5137 | task_rq_unlock(rq, p, &rf); | 5136 | task_rq_unlock(rq, p, &rf); |
5138 | 5137 | ||
5139 | rcu_read_unlock(); | 5138 | rcu_read_unlock(); |
5140 | jiffies_to_timespec(time_slice, &t); | 5139 | jiffies_to_timespec64(time_slice, t); |
5141 | retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0; | 5140 | return 0; |
5142 | return retval; | ||
5143 | 5141 | ||
5144 | out_unlock: | 5142 | out_unlock: |
5145 | rcu_read_unlock(); | 5143 | rcu_read_unlock(); |
5146 | return retval; | 5144 | return retval; |
5147 | } | 5145 | } |
5148 | 5146 | ||
5147 | SYSCALL_DEFINE2(sched_rr_get_interval, pid_t, pid, | ||
5148 | struct timespec __user *, interval) | ||
5149 | { | ||
5150 | struct timespec64 t; | ||
5151 | int retval = sched_rr_get_interval(pid, &t); | ||
5152 | |||
5153 | if (retval == 0) | ||
5154 | retval = put_timespec64(&t, interval); | ||
5155 | |||
5156 | return retval; | ||
5157 | } | ||
5158 | |||
5159 | #ifdef CONFIG_COMPAT | ||
5160 | COMPAT_SYSCALL_DEFINE2(sched_rr_get_interval, | ||
5161 | compat_pid_t, pid, | ||
5162 | struct compat_timespec __user *, interval) | ||
5163 | { | ||
5164 | struct timespec64 t; | ||
5165 | int retval = sched_rr_get_interval(pid, &t); | ||
5166 | |||
5167 | if (retval == 0) | ||
5168 | retval = compat_put_timespec64(&t, interval); | ||
5169 | return retval; | ||
5170 | } | ||
5171 | #endif | ||
5172 | |||
5149 | void sched_show_task(struct task_struct *p) | 5173 | void sched_show_task(struct task_struct *p) |
5150 | { | 5174 | { |
5151 | unsigned long free = 0; | 5175 | unsigned long free = 0; |
diff --git a/kernel/signal.c b/kernel/signal.c index aa1fb9f905db..babb36d3d039 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -2599,7 +2599,6 @@ SYSCALL_DEFINE4(rt_sigprocmask, int, how, sigset_t __user *, nset, | |||
2599 | COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, | 2599 | COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, |
2600 | compat_sigset_t __user *, oset, compat_size_t, sigsetsize) | 2600 | compat_sigset_t __user *, oset, compat_size_t, sigsetsize) |
2601 | { | 2601 | { |
2602 | #ifdef __BIG_ENDIAN | ||
2603 | sigset_t old_set = current->blocked; | 2602 | sigset_t old_set = current->blocked; |
2604 | 2603 | ||
2605 | /* XXX: Don't preclude handling different sized sigset_t's. */ | 2604 | /* XXX: Don't preclude handling different sized sigset_t's. */ |
@@ -2607,38 +2606,22 @@ COMPAT_SYSCALL_DEFINE4(rt_sigprocmask, int, how, compat_sigset_t __user *, nset, | |||
2607 | return -EINVAL; | 2606 | return -EINVAL; |
2608 | 2607 | ||
2609 | if (nset) { | 2608 | if (nset) { |
2610 | compat_sigset_t new32; | ||
2611 | sigset_t new_set; | 2609 | sigset_t new_set; |
2612 | int error; | 2610 | int error; |
2613 | if (copy_from_user(&new32, nset, sizeof(compat_sigset_t))) | 2611 | if (get_compat_sigset(&new_set, nset)) |
2614 | return -EFAULT; | 2612 | return -EFAULT; |
2615 | |||
2616 | sigset_from_compat(&new_set, &new32); | ||
2617 | sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 2613 | sigdelsetmask(&new_set, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
2618 | 2614 | ||
2619 | error = sigprocmask(how, &new_set, NULL); | 2615 | error = sigprocmask(how, &new_set, NULL); |
2620 | if (error) | 2616 | if (error) |
2621 | return error; | 2617 | return error; |
2622 | } | 2618 | } |
2623 | if (oset) { | 2619 | return oset ? put_compat_sigset(oset, &old_set, sizeof(*oset)) : 0; |
2624 | compat_sigset_t old32; | ||
2625 | sigset_to_compat(&old32, &old_set); | ||
2626 | if (copy_to_user(oset, &old32, sizeof(compat_sigset_t))) | ||
2627 | return -EFAULT; | ||
2628 | } | ||
2629 | return 0; | ||
2630 | #else | ||
2631 | return sys_rt_sigprocmask(how, (sigset_t __user *)nset, | ||
2632 | (sigset_t __user *)oset, sigsetsize); | ||
2633 | #endif | ||
2634 | } | 2620 | } |
2635 | #endif | 2621 | #endif |
2636 | 2622 | ||
2637 | static int do_sigpending(void *set, unsigned long sigsetsize) | 2623 | static int do_sigpending(sigset_t *set) |
2638 | { | 2624 | { |
2639 | if (sigsetsize > sizeof(sigset_t)) | ||
2640 | return -EINVAL; | ||
2641 | |||
2642 | spin_lock_irq(¤t->sighand->siglock); | 2625 | spin_lock_irq(¤t->sighand->siglock); |
2643 | sigorsets(set, ¤t->pending.signal, | 2626 | sigorsets(set, ¤t->pending.signal, |
2644 | ¤t->signal->shared_pending.signal); | 2627 | ¤t->signal->shared_pending.signal); |
@@ -2658,7 +2641,12 @@ static int do_sigpending(void *set, unsigned long sigsetsize) | |||
2658 | SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) | 2641 | SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) |
2659 | { | 2642 | { |
2660 | sigset_t set; | 2643 | sigset_t set; |
2661 | int err = do_sigpending(&set, sigsetsize); | 2644 | int err; |
2645 | |||
2646 | if (sigsetsize > sizeof(*uset)) | ||
2647 | return -EINVAL; | ||
2648 | |||
2649 | err = do_sigpending(&set); | ||
2662 | if (!err && copy_to_user(uset, &set, sigsetsize)) | 2650 | if (!err && copy_to_user(uset, &set, sigsetsize)) |
2663 | err = -EFAULT; | 2651 | err = -EFAULT; |
2664 | return err; | 2652 | return err; |
@@ -2668,20 +2656,16 @@ SYSCALL_DEFINE2(rt_sigpending, sigset_t __user *, uset, size_t, sigsetsize) | |||
2668 | COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, | 2656 | COMPAT_SYSCALL_DEFINE2(rt_sigpending, compat_sigset_t __user *, uset, |
2669 | compat_size_t, sigsetsize) | 2657 | compat_size_t, sigsetsize) |
2670 | { | 2658 | { |
2671 | #ifdef __BIG_ENDIAN | ||
2672 | sigset_t set; | 2659 | sigset_t set; |
2673 | int err = do_sigpending(&set, sigsetsize); | 2660 | int err; |
2674 | if (!err) { | 2661 | |
2675 | compat_sigset_t set32; | 2662 | if (sigsetsize > sizeof(*uset)) |
2676 | sigset_to_compat(&set32, &set); | 2663 | return -EINVAL; |
2677 | /* we can get here only if sigsetsize <= sizeof(set) */ | 2664 | |
2678 | if (copy_to_user(uset, &set32, sigsetsize)) | 2665 | err = do_sigpending(&set); |
2679 | err = -EFAULT; | 2666 | if (!err) |
2680 | } | 2667 | err = put_compat_sigset(uset, &set, sigsetsize); |
2681 | return err; | 2668 | return err; |
2682 | #else | ||
2683 | return sys_rt_sigpending((sigset_t __user *)uset, sigsetsize); | ||
2684 | #endif | ||
2685 | } | 2669 | } |
2686 | #endif | 2670 | #endif |
2687 | 2671 | ||
@@ -2915,7 +2899,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, | |||
2915 | struct compat_siginfo __user *, uinfo, | 2899 | struct compat_siginfo __user *, uinfo, |
2916 | struct compat_timespec __user *, uts, compat_size_t, sigsetsize) | 2900 | struct compat_timespec __user *, uts, compat_size_t, sigsetsize) |
2917 | { | 2901 | { |
2918 | compat_sigset_t s32; | ||
2919 | sigset_t s; | 2902 | sigset_t s; |
2920 | struct timespec t; | 2903 | struct timespec t; |
2921 | siginfo_t info; | 2904 | siginfo_t info; |
@@ -2924,9 +2907,8 @@ COMPAT_SYSCALL_DEFINE4(rt_sigtimedwait, compat_sigset_t __user *, uthese, | |||
2924 | if (sigsetsize != sizeof(sigset_t)) | 2907 | if (sigsetsize != sizeof(sigset_t)) |
2925 | return -EINVAL; | 2908 | return -EINVAL; |
2926 | 2909 | ||
2927 | if (copy_from_user(&s32, uthese, sizeof(compat_sigset_t))) | 2910 | if (get_compat_sigset(&s, uthese)) |
2928 | return -EFAULT; | 2911 | return -EFAULT; |
2929 | sigset_from_compat(&s, &s32); | ||
2930 | 2912 | ||
2931 | if (uts) { | 2913 | if (uts) { |
2932 | if (compat_get_timespec(&t, uts)) | 2914 | if (compat_get_timespec(&t, uts)) |
@@ -3344,15 +3326,11 @@ SYSCALL_DEFINE1(sigpending, old_sigset_t __user *, set) | |||
3344 | #ifdef CONFIG_COMPAT | 3326 | #ifdef CONFIG_COMPAT |
3345 | COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32) | 3327 | COMPAT_SYSCALL_DEFINE1(sigpending, compat_old_sigset_t __user *, set32) |
3346 | { | 3328 | { |
3347 | #ifdef __BIG_ENDIAN | ||
3348 | sigset_t set; | 3329 | sigset_t set; |
3349 | int err = do_sigpending(&set, sizeof(set.sig[0])); | 3330 | int err = do_sigpending(&set); |
3350 | if (!err) | 3331 | if (!err) |
3351 | err = put_user(set.sig[0], set32); | 3332 | err = put_user(set.sig[0], set32); |
3352 | return err; | 3333 | return err; |
3353 | #else | ||
3354 | return sys_rt_sigpending((sigset_t __user *)set32, sizeof(*set32)); | ||
3355 | #endif | ||
3356 | } | 3334 | } |
3357 | #endif | 3335 | #endif |
3358 | 3336 | ||
@@ -3450,7 +3428,6 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, | |||
3450 | compat_size_t, sigsetsize) | 3428 | compat_size_t, sigsetsize) |
3451 | { | 3429 | { |
3452 | struct k_sigaction new_ka, old_ka; | 3430 | struct k_sigaction new_ka, old_ka; |
3453 | compat_sigset_t mask; | ||
3454 | #ifdef __ARCH_HAS_SA_RESTORER | 3431 | #ifdef __ARCH_HAS_SA_RESTORER |
3455 | compat_uptr_t restorer; | 3432 | compat_uptr_t restorer; |
3456 | #endif | 3433 | #endif |
@@ -3468,19 +3445,18 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig, | |||
3468 | ret |= get_user(restorer, &act->sa_restorer); | 3445 | ret |= get_user(restorer, &act->sa_restorer); |
3469 | new_ka.sa.sa_restorer = compat_ptr(restorer); | 3446 | new_ka.sa.sa_restorer = compat_ptr(restorer); |
3470 | #endif | 3447 | #endif |
3471 | ret |= copy_from_user(&mask, &act->sa_mask, sizeof(mask)); | 3448 | ret |= get_compat_sigset(&new_ka.sa.sa_mask, &act->sa_mask); |
3472 | ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); | 3449 | ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags); |
3473 | if (ret) | 3450 | if (ret) |
3474 | return -EFAULT; | 3451 | return -EFAULT; |
3475 | sigset_from_compat(&new_ka.sa.sa_mask, &mask); | ||
3476 | } | 3452 | } |
3477 | 3453 | ||
3478 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); | 3454 | ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); |
3479 | if (!ret && oact) { | 3455 | if (!ret && oact) { |
3480 | sigset_to_compat(&mask, &old_ka.sa.sa_mask); | ||
3481 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), | 3456 | ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), |
3482 | &oact->sa_handler); | 3457 | &oact->sa_handler); |
3483 | ret |= copy_to_user(&oact->sa_mask, &mask, sizeof(mask)); | 3458 | ret |= put_compat_sigset(&oact->sa_mask, &old_ka.sa.sa_mask, |
3459 | sizeof(oact->sa_mask)); | ||
3484 | ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); | 3460 | ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags); |
3485 | #ifdef __ARCH_HAS_SA_RESTORER | 3461 | #ifdef __ARCH_HAS_SA_RESTORER |
3486 | ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), | 3462 | ret |= put_user(ptr_to_compat(old_ka.sa.sa_restorer), |
@@ -3660,22 +3636,15 @@ SYSCALL_DEFINE2(rt_sigsuspend, sigset_t __user *, unewset, size_t, sigsetsize) | |||
3660 | #ifdef CONFIG_COMPAT | 3636 | #ifdef CONFIG_COMPAT |
3661 | COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_size_t, sigsetsize) | 3637 | COMPAT_SYSCALL_DEFINE2(rt_sigsuspend, compat_sigset_t __user *, unewset, compat_size_t, sigsetsize) |
3662 | { | 3638 | { |
3663 | #ifdef __BIG_ENDIAN | ||
3664 | sigset_t newset; | 3639 | sigset_t newset; |
3665 | compat_sigset_t newset32; | ||
3666 | 3640 | ||
3667 | /* XXX: Don't preclude handling different sized sigset_t's. */ | 3641 | /* XXX: Don't preclude handling different sized sigset_t's. */ |
3668 | if (sigsetsize != sizeof(sigset_t)) | 3642 | if (sigsetsize != sizeof(sigset_t)) |
3669 | return -EINVAL; | 3643 | return -EINVAL; |
3670 | 3644 | ||
3671 | if (copy_from_user(&newset32, unewset, sizeof(compat_sigset_t))) | 3645 | if (get_compat_sigset(&newset, unewset)) |
3672 | return -EFAULT; | 3646 | return -EFAULT; |
3673 | sigset_from_compat(&newset, &newset32); | ||
3674 | return sigsuspend(&newset); | 3647 | return sigsuspend(&newset); |
3675 | #else | ||
3676 | /* on little-endian bitmaps don't care about granularity */ | ||
3677 | return sys_rt_sigsuspend((sigset_t __user *)unewset, sigsetsize); | ||
3678 | #endif | ||
3679 | } | 3648 | } |
3680 | #endif | 3649 | #endif |
3681 | 3650 | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 2dd1a9ca4599..f169ecc4f2e8 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
@@ -2724,7 +2724,6 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, | |||
2724 | case KVM_SET_SIGNAL_MASK: { | 2724 | case KVM_SET_SIGNAL_MASK: { |
2725 | struct kvm_signal_mask __user *sigmask_arg = argp; | 2725 | struct kvm_signal_mask __user *sigmask_arg = argp; |
2726 | struct kvm_signal_mask kvm_sigmask; | 2726 | struct kvm_signal_mask kvm_sigmask; |
2727 | compat_sigset_t csigset; | ||
2728 | sigset_t sigset; | 2727 | sigset_t sigset; |
2729 | 2728 | ||
2730 | if (argp) { | 2729 | if (argp) { |
@@ -2733,13 +2732,11 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, | |||
2733 | sizeof(kvm_sigmask))) | 2732 | sizeof(kvm_sigmask))) |
2734 | goto out; | 2733 | goto out; |
2735 | r = -EINVAL; | 2734 | r = -EINVAL; |
2736 | if (kvm_sigmask.len != sizeof(csigset)) | 2735 | if (kvm_sigmask.len != sizeof(compat_sigset_t)) |
2737 | goto out; | 2736 | goto out; |
2738 | r = -EFAULT; | 2737 | r = -EFAULT; |
2739 | if (copy_from_user(&csigset, sigmask_arg->sigset, | 2738 | if (get_compat_sigset(&sigset, (void *)sigmask_arg->sigset)) |
2740 | sizeof(csigset))) | ||
2741 | goto out; | 2739 | goto out; |
2742 | sigset_from_compat(&sigset, &csigset); | ||
2743 | r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); | 2740 | r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset); |
2744 | } else | 2741 | } else |
2745 | r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL); | 2742 | r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL); |