diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 15:54:03 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-01-11 15:54:03 -0500 |
commit | 19ccb28e296d5afa299db1003d37e5d37994d46e (patch) | |
tree | 124859635b8f0c6c429c0b19ca3a092ad42da703 | |
parent | afd2ff9b7e1b367172f18ba7f693dfb62bdcb2dc (diff) | |
parent | a7f61e89af73e9bf760826b20dba4e637221fcb9 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull vfs compat_ioctl fixes from Al Viro:
"This is basically Jann's patches from last week. I have _not_
included the stuff like switching i2c to ->compat_ioctl() into this
one - those need more testing.
Ideally I would like fs/compat_ioctl.c shrunk a lot, but that's a
separate story"
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
compat_ioctl: don't call do_ioctl under set_fs(KERNEL_DS)
compat_ioctl: don't pass fd around when not needed
compat_ioctl: don't look up the fd twice
-rw-r--r-- | fs/compat_ioctl.c | 253 | ||||
-rw-r--r-- | fs/internal.h | 7 | ||||
-rw-r--r-- | fs/ioctl.c | 4 | ||||
-rw-r--r-- | include/linux/fs.h | 2 |
4 files changed, 146 insertions, 120 deletions
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index dcf26537c935..9144b779d10e 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -58,6 +58,8 @@ | |||
58 | #include <linux/atalk.h> | 58 | #include <linux/atalk.h> |
59 | #include <linux/gfp.h> | 59 | #include <linux/gfp.h> |
60 | 60 | ||
61 | #include "internal.h" | ||
62 | |||
61 | #include <net/bluetooth/bluetooth.h> | 63 | #include <net/bluetooth/bluetooth.h> |
62 | #include <net/bluetooth/hci_sock.h> | 64 | #include <net/bluetooth/hci_sock.h> |
63 | #include <net/bluetooth/rfcomm.h> | 65 | #include <net/bluetooth/rfcomm.h> |
@@ -115,19 +117,38 @@ | |||
115 | #include <asm/fbio.h> | 117 | #include <asm/fbio.h> |
116 | #endif | 118 | #endif |
117 | 119 | ||
118 | static int w_long(unsigned int fd, unsigned int cmd, | 120 | #define convert_in_user(srcptr, dstptr) \ |
119 | compat_ulong_t __user *argp) | 121 | ({ \ |
122 | typeof(*srcptr) val; \ | ||
123 | \ | ||
124 | get_user(val, srcptr) || put_user(val, dstptr); \ | ||
125 | }) | ||
126 | |||
127 | static int do_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
128 | { | ||
129 | int err; | ||
130 | |||
131 | err = security_file_ioctl(file, cmd, arg); | ||
132 | if (err) | ||
133 | return err; | ||
134 | |||
135 | return vfs_ioctl(file, cmd, arg); | ||
136 | } | ||
137 | |||
138 | static int w_long(struct file *file, | ||
139 | unsigned int cmd, compat_ulong_t __user *argp) | ||
120 | { | 140 | { |
121 | mm_segment_t old_fs = get_fs(); | ||
122 | int err; | 141 | int err; |
123 | unsigned long val; | 142 | unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); |
124 | 143 | ||
125 | set_fs (KERNEL_DS); | 144 | if (valp == NULL) |
126 | err = sys_ioctl(fd, cmd, (unsigned long)&val); | ||
127 | set_fs (old_fs); | ||
128 | if (!err && put_user(val, argp)) | ||
129 | return -EFAULT; | 145 | return -EFAULT; |
130 | return err; | 146 | err = do_ioctl(file, cmd, (unsigned long)valp); |
147 | if (err) | ||
148 | return err; | ||
149 | if (convert_in_user(valp, argp)) | ||
150 | return -EFAULT; | ||
151 | return 0; | ||
131 | } | 152 | } |
132 | 153 | ||
133 | struct compat_video_event { | 154 | struct compat_video_event { |
@@ -139,23 +160,23 @@ struct compat_video_event { | |||
139 | } u; | 160 | } u; |
140 | }; | 161 | }; |
141 | 162 | ||
142 | static int do_video_get_event(unsigned int fd, unsigned int cmd, | 163 | static int do_video_get_event(struct file *file, |
143 | struct compat_video_event __user *up) | 164 | unsigned int cmd, struct compat_video_event __user *up) |
144 | { | 165 | { |
145 | struct video_event kevent; | 166 | struct video_event __user *kevent = |
146 | mm_segment_t old_fs = get_fs(); | 167 | compat_alloc_user_space(sizeof(*kevent)); |
147 | int err; | 168 | int err; |
148 | 169 | ||
149 | set_fs(KERNEL_DS); | 170 | if (kevent == NULL) |
150 | err = sys_ioctl(fd, cmd, (unsigned long) &kevent); | 171 | return -EFAULT; |
151 | set_fs(old_fs); | ||
152 | 172 | ||
173 | err = do_ioctl(file, cmd, (unsigned long)kevent); | ||
153 | if (!err) { | 174 | if (!err) { |
154 | err = put_user(kevent.type, &up->type); | 175 | err = convert_in_user(&kevent->type, &up->type); |
155 | err |= put_user(kevent.timestamp, &up->timestamp); | 176 | err |= convert_in_user(&kevent->timestamp, &up->timestamp); |
156 | err |= put_user(kevent.u.size.w, &up->u.size.w); | 177 | err |= convert_in_user(&kevent->u.size.w, &up->u.size.w); |
157 | err |= put_user(kevent.u.size.h, &up->u.size.h); | 178 | err |= convert_in_user(&kevent->u.size.h, &up->u.size.h); |
158 | err |= put_user(kevent.u.size.aspect_ratio, | 179 | err |= convert_in_user(&kevent->u.size.aspect_ratio, |
159 | &up->u.size.aspect_ratio); | 180 | &up->u.size.aspect_ratio); |
160 | if (err) | 181 | if (err) |
161 | err = -EFAULT; | 182 | err = -EFAULT; |
@@ -169,8 +190,8 @@ struct compat_video_still_picture { | |||
169 | int32_t size; | 190 | int32_t size; |
170 | }; | 191 | }; |
171 | 192 | ||
172 | static int do_video_stillpicture(unsigned int fd, unsigned int cmd, | 193 | static int do_video_stillpicture(struct file *file, |
173 | struct compat_video_still_picture __user *up) | 194 | unsigned int cmd, struct compat_video_still_picture __user *up) |
174 | { | 195 | { |
175 | struct video_still_picture __user *up_native; | 196 | struct video_still_picture __user *up_native; |
176 | compat_uptr_t fp; | 197 | compat_uptr_t fp; |
@@ -190,7 +211,7 @@ static int do_video_stillpicture(unsigned int fd, unsigned int cmd, | |||
190 | if (err) | 211 | if (err) |
191 | return -EFAULT; | 212 | return -EFAULT; |
192 | 213 | ||
193 | err = sys_ioctl(fd, cmd, (unsigned long) up_native); | 214 | err = do_ioctl(file, cmd, (unsigned long) up_native); |
194 | 215 | ||
195 | return err; | 216 | return err; |
196 | } | 217 | } |
@@ -200,8 +221,8 @@ struct compat_video_spu_palette { | |||
200 | compat_uptr_t palette; | 221 | compat_uptr_t palette; |
201 | }; | 222 | }; |
202 | 223 | ||
203 | static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, | 224 | static int do_video_set_spu_palette(struct file *file, |
204 | struct compat_video_spu_palette __user *up) | 225 | unsigned int cmd, struct compat_video_spu_palette __user *up) |
205 | { | 226 | { |
206 | struct video_spu_palette __user *up_native; | 227 | struct video_spu_palette __user *up_native; |
207 | compat_uptr_t palp; | 228 | compat_uptr_t palp; |
@@ -218,7 +239,7 @@ static int do_video_set_spu_palette(unsigned int fd, unsigned int cmd, | |||
218 | if (err) | 239 | if (err) |
219 | return -EFAULT; | 240 | return -EFAULT; |
220 | 241 | ||
221 | err = sys_ioctl(fd, cmd, (unsigned long) up_native); | 242 | err = do_ioctl(file, cmd, (unsigned long) up_native); |
222 | 243 | ||
223 | return err; | 244 | return err; |
224 | } | 245 | } |
@@ -276,7 +297,7 @@ static int sg_build_iovec(sg_io_hdr_t __user *sgio, void __user *dxferp, u16 iov | |||
276 | return 0; | 297 | return 0; |
277 | } | 298 | } |
278 | 299 | ||
279 | static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, | 300 | static int sg_ioctl_trans(struct file *file, unsigned int cmd, |
280 | sg_io_hdr32_t __user *sgio32) | 301 | sg_io_hdr32_t __user *sgio32) |
281 | { | 302 | { |
282 | sg_io_hdr_t __user *sgio; | 303 | sg_io_hdr_t __user *sgio; |
@@ -289,7 +310,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, | |||
289 | if (get_user(interface_id, &sgio32->interface_id)) | 310 | if (get_user(interface_id, &sgio32->interface_id)) |
290 | return -EFAULT; | 311 | return -EFAULT; |
291 | if (interface_id != 'S') | 312 | if (interface_id != 'S') |
292 | return sys_ioctl(fd, cmd, (unsigned long)sgio32); | 313 | return do_ioctl(file, cmd, (unsigned long)sgio32); |
293 | 314 | ||
294 | if (get_user(iovec_count, &sgio32->iovec_count)) | 315 | if (get_user(iovec_count, &sgio32->iovec_count)) |
295 | return -EFAULT; | 316 | return -EFAULT; |
@@ -349,7 +370,7 @@ static int sg_ioctl_trans(unsigned int fd, unsigned int cmd, | |||
349 | if (put_user(compat_ptr(data), &sgio->usr_ptr)) | 370 | if (put_user(compat_ptr(data), &sgio->usr_ptr)) |
350 | return -EFAULT; | 371 | return -EFAULT; |
351 | 372 | ||
352 | err = sys_ioctl(fd, cmd, (unsigned long) sgio); | 373 | err = do_ioctl(file, cmd, (unsigned long) sgio); |
353 | 374 | ||
354 | if (err >= 0) { | 375 | if (err >= 0) { |
355 | void __user *datap; | 376 | void __user *datap; |
@@ -380,13 +401,13 @@ struct compat_sg_req_info { /* used by SG_GET_REQUEST_TABLE ioctl() */ | |||
380 | int unused; | 401 | int unused; |
381 | }; | 402 | }; |
382 | 403 | ||
383 | static int sg_grt_trans(unsigned int fd, unsigned int cmd, struct | 404 | static int sg_grt_trans(struct file *file, |
384 | compat_sg_req_info __user *o) | 405 | unsigned int cmd, struct compat_sg_req_info __user *o) |
385 | { | 406 | { |
386 | int err, i; | 407 | int err, i; |
387 | sg_req_info_t __user *r; | 408 | sg_req_info_t __user *r; |
388 | r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE); | 409 | r = compat_alloc_user_space(sizeof(sg_req_info_t)*SG_MAX_QUEUE); |
389 | err = sys_ioctl(fd,cmd,(unsigned long)r); | 410 | err = do_ioctl(file, cmd, (unsigned long)r); |
390 | if (err < 0) | 411 | if (err < 0) |
391 | return err; | 412 | return err; |
392 | for (i = 0; i < SG_MAX_QUEUE; i++) { | 413 | for (i = 0; i < SG_MAX_QUEUE; i++) { |
@@ -412,8 +433,8 @@ struct sock_fprog32 { | |||
412 | #define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) | 433 | #define PPPIOCSPASS32 _IOW('t', 71, struct sock_fprog32) |
413 | #define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) | 434 | #define PPPIOCSACTIVE32 _IOW('t', 70, struct sock_fprog32) |
414 | 435 | ||
415 | static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, | 436 | static int ppp_sock_fprog_ioctl_trans(struct file *file, |
416 | struct sock_fprog32 __user *u_fprog32) | 437 | unsigned int cmd, struct sock_fprog32 __user *u_fprog32) |
417 | { | 438 | { |
418 | struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); | 439 | struct sock_fprog __user *u_fprog64 = compat_alloc_user_space(sizeof(struct sock_fprog)); |
419 | void __user *fptr64; | 440 | void __user *fptr64; |
@@ -435,7 +456,7 @@ static int ppp_sock_fprog_ioctl_trans(unsigned int fd, unsigned int cmd, | |||
435 | else | 456 | else |
436 | cmd = PPPIOCSACTIVE; | 457 | cmd = PPPIOCSACTIVE; |
437 | 458 | ||
438 | return sys_ioctl(fd, cmd, (unsigned long) u_fprog64); | 459 | return do_ioctl(file, cmd, (unsigned long) u_fprog64); |
439 | } | 460 | } |
440 | 461 | ||
441 | struct ppp_option_data32 { | 462 | struct ppp_option_data32 { |
@@ -451,7 +472,7 @@ struct ppp_idle32 { | |||
451 | }; | 472 | }; |
452 | #define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) | 473 | #define PPPIOCGIDLE32 _IOR('t', 63, struct ppp_idle32) |
453 | 474 | ||
454 | static int ppp_gidle(unsigned int fd, unsigned int cmd, | 475 | static int ppp_gidle(struct file *file, unsigned int cmd, |
455 | struct ppp_idle32 __user *idle32) | 476 | struct ppp_idle32 __user *idle32) |
456 | { | 477 | { |
457 | struct ppp_idle __user *idle; | 478 | struct ppp_idle __user *idle; |
@@ -460,7 +481,7 @@ static int ppp_gidle(unsigned int fd, unsigned int cmd, | |||
460 | 481 | ||
461 | idle = compat_alloc_user_space(sizeof(*idle)); | 482 | idle = compat_alloc_user_space(sizeof(*idle)); |
462 | 483 | ||
463 | err = sys_ioctl(fd, PPPIOCGIDLE, (unsigned long) idle); | 484 | err = do_ioctl(file, PPPIOCGIDLE, (unsigned long) idle); |
464 | 485 | ||
465 | if (!err) { | 486 | if (!err) { |
466 | if (get_user(xmit, &idle->xmit_idle) || | 487 | if (get_user(xmit, &idle->xmit_idle) || |
@@ -472,7 +493,7 @@ static int ppp_gidle(unsigned int fd, unsigned int cmd, | |||
472 | return err; | 493 | return err; |
473 | } | 494 | } |
474 | 495 | ||
475 | static int ppp_scompress(unsigned int fd, unsigned int cmd, | 496 | static int ppp_scompress(struct file *file, unsigned int cmd, |
476 | struct ppp_option_data32 __user *odata32) | 497 | struct ppp_option_data32 __user *odata32) |
477 | { | 498 | { |
478 | struct ppp_option_data __user *odata; | 499 | struct ppp_option_data __user *odata; |
@@ -492,7 +513,7 @@ static int ppp_scompress(unsigned int fd, unsigned int cmd, | |||
492 | sizeof(__u32) + sizeof(int))) | 513 | sizeof(__u32) + sizeof(int))) |
493 | return -EFAULT; | 514 | return -EFAULT; |
494 | 515 | ||
495 | return sys_ioctl(fd, PPPIOCSCOMPRESS, (unsigned long) odata); | 516 | return do_ioctl(file, PPPIOCSCOMPRESS, (unsigned long) odata); |
496 | } | 517 | } |
497 | 518 | ||
498 | #ifdef CONFIG_BLOCK | 519 | #ifdef CONFIG_BLOCK |
@@ -512,12 +533,13 @@ struct mtpos32 { | |||
512 | }; | 533 | }; |
513 | #define MTIOCPOS32 _IOR('m', 3, struct mtpos32) | 534 | #define MTIOCPOS32 _IOR('m', 3, struct mtpos32) |
514 | 535 | ||
515 | static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp) | 536 | static int mt_ioctl_trans(struct file *file, |
537 | unsigned int cmd, void __user *argp) | ||
516 | { | 538 | { |
517 | mm_segment_t old_fs = get_fs(); | 539 | /* NULL initialization to make gcc shut up */ |
518 | struct mtget get; | 540 | struct mtget __user *get = NULL; |
519 | struct mtget32 __user *umget32; | 541 | struct mtget32 __user *umget32; |
520 | struct mtpos pos; | 542 | struct mtpos __user *pos = NULL; |
521 | struct mtpos32 __user *upos32; | 543 | struct mtpos32 __user *upos32; |
522 | unsigned long kcmd; | 544 | unsigned long kcmd; |
523 | void *karg; | 545 | void *karg; |
@@ -526,32 +548,34 @@ static int mt_ioctl_trans(unsigned int fd, unsigned int cmd, void __user *argp) | |||
526 | switch(cmd) { | 548 | switch(cmd) { |
527 | case MTIOCPOS32: | 549 | case MTIOCPOS32: |
528 | kcmd = MTIOCPOS; | 550 | kcmd = MTIOCPOS; |
529 | karg = &pos; | 551 | pos = compat_alloc_user_space(sizeof(*pos)); |
552 | karg = pos; | ||
530 | break; | 553 | break; |
531 | default: /* MTIOCGET32 */ | 554 | default: /* MTIOCGET32 */ |
532 | kcmd = MTIOCGET; | 555 | kcmd = MTIOCGET; |
533 | karg = &get; | 556 | get = compat_alloc_user_space(sizeof(*get)); |
557 | karg = get; | ||
534 | break; | 558 | break; |
535 | } | 559 | } |
536 | set_fs (KERNEL_DS); | 560 | if (karg == NULL) |
537 | err = sys_ioctl (fd, kcmd, (unsigned long)karg); | 561 | return -EFAULT; |
538 | set_fs (old_fs); | 562 | err = do_ioctl(file, kcmd, (unsigned long)karg); |
539 | if (err) | 563 | if (err) |
540 | return err; | 564 | return err; |
541 | switch (cmd) { | 565 | switch (cmd) { |
542 | case MTIOCPOS32: | 566 | case MTIOCPOS32: |
543 | upos32 = argp; | 567 | upos32 = argp; |
544 | err = __put_user(pos.mt_blkno, &upos32->mt_blkno); | 568 | err = convert_in_user(&pos->mt_blkno, &upos32->mt_blkno); |
545 | break; | 569 | break; |
546 | case MTIOCGET32: | 570 | case MTIOCGET32: |
547 | umget32 = argp; | 571 | umget32 = argp; |
548 | err = __put_user(get.mt_type, &umget32->mt_type); | 572 | err = convert_in_user(&get->mt_type, &umget32->mt_type); |
549 | err |= __put_user(get.mt_resid, &umget32->mt_resid); | 573 | err |= convert_in_user(&get->mt_resid, &umget32->mt_resid); |
550 | err |= __put_user(get.mt_dsreg, &umget32->mt_dsreg); | 574 | err |= convert_in_user(&get->mt_dsreg, &umget32->mt_dsreg); |
551 | err |= __put_user(get.mt_gstat, &umget32->mt_gstat); | 575 | err |= convert_in_user(&get->mt_gstat, &umget32->mt_gstat); |
552 | err |= __put_user(get.mt_erreg, &umget32->mt_erreg); | 576 | err |= convert_in_user(&get->mt_erreg, &umget32->mt_erreg); |
553 | err |= __put_user(get.mt_fileno, &umget32->mt_fileno); | 577 | err |= convert_in_user(&get->mt_fileno, &umget32->mt_fileno); |
554 | err |= __put_user(get.mt_blkno, &umget32->mt_blkno); | 578 | err |= convert_in_user(&get->mt_blkno, &umget32->mt_blkno); |
555 | break; | 579 | break; |
556 | } | 580 | } |
557 | return err ? -EFAULT: 0; | 581 | return err ? -EFAULT: 0; |
@@ -605,42 +629,41 @@ struct serial_struct32 { | |||
605 | compat_int_t reserved[1]; | 629 | compat_int_t reserved[1]; |
606 | }; | 630 | }; |
607 | 631 | ||
608 | static int serial_struct_ioctl(unsigned fd, unsigned cmd, | 632 | static int serial_struct_ioctl(struct file *file, |
609 | struct serial_struct32 __user *ss32) | 633 | unsigned cmd, struct serial_struct32 __user *ss32) |
610 | { | 634 | { |
611 | typedef struct serial_struct32 SS32; | 635 | typedef struct serial_struct32 SS32; |
612 | int err; | 636 | int err; |
613 | struct serial_struct ss; | 637 | struct serial_struct __user *ss = compat_alloc_user_space(sizeof(*ss)); |
614 | mm_segment_t oldseg = get_fs(); | ||
615 | __u32 udata; | 638 | __u32 udata; |
616 | unsigned int base; | 639 | unsigned int base; |
640 | unsigned char *iomem_base; | ||
617 | 641 | ||
642 | if (ss == NULL) | ||
643 | return -EFAULT; | ||
618 | if (cmd == TIOCSSERIAL) { | 644 | if (cmd == TIOCSSERIAL) { |
619 | if (!access_ok(VERIFY_READ, ss32, sizeof(SS32))) | 645 | if (copy_in_user(ss, ss32, offsetof(SS32, iomem_base)) || |
620 | return -EFAULT; | 646 | get_user(udata, &ss32->iomem_base)) |
621 | if (__copy_from_user(&ss, ss32, offsetof(SS32, iomem_base))) | ||
622 | return -EFAULT; | 647 | return -EFAULT; |
623 | if (__get_user(udata, &ss32->iomem_base)) | 648 | iomem_base = compat_ptr(udata); |
649 | if (put_user(iomem_base, &ss->iomem_base) || | ||
650 | convert_in_user(&ss32->iomem_reg_shift, | ||
651 | &ss->iomem_reg_shift) || | ||
652 | convert_in_user(&ss32->port_high, &ss->port_high) || | ||
653 | put_user(0UL, &ss->iomap_base)) | ||
624 | return -EFAULT; | 654 | return -EFAULT; |
625 | ss.iomem_base = compat_ptr(udata); | ||
626 | if (__get_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || | ||
627 | __get_user(ss.port_high, &ss32->port_high)) | ||
628 | return -EFAULT; | ||
629 | ss.iomap_base = 0UL; | ||
630 | } | 655 | } |
631 | set_fs(KERNEL_DS); | 656 | err = do_ioctl(file, cmd, (unsigned long)ss); |
632 | err = sys_ioctl(fd,cmd,(unsigned long)(&ss)); | ||
633 | set_fs(oldseg); | ||
634 | if (cmd == TIOCGSERIAL && err >= 0) { | 657 | if (cmd == TIOCGSERIAL && err >= 0) { |
635 | if (!access_ok(VERIFY_WRITE, ss32, sizeof(SS32))) | 658 | if (copy_in_user(ss32, ss, offsetof(SS32, iomem_base)) || |
636 | return -EFAULT; | 659 | get_user(iomem_base, &ss->iomem_base)) |
637 | if (__copy_to_user(ss32,&ss,offsetof(SS32,iomem_base))) | ||
638 | return -EFAULT; | 660 | return -EFAULT; |
639 | base = (unsigned long)ss.iomem_base >> 32 ? | 661 | base = (unsigned long)iomem_base >> 32 ? |
640 | 0xffffffff : (unsigned)(unsigned long)ss.iomem_base; | 662 | 0xffffffff : (unsigned)(unsigned long)iomem_base; |
641 | if (__put_user(base, &ss32->iomem_base) || | 663 | if (put_user(base, &ss32->iomem_base) || |
642 | __put_user(ss.iomem_reg_shift, &ss32->iomem_reg_shift) || | 664 | convert_in_user(&ss->iomem_reg_shift, |
643 | __put_user(ss.port_high, &ss32->port_high)) | 665 | &ss32->iomem_reg_shift) || |
666 | convert_in_user(&ss->port_high, &ss32->port_high)) | ||
644 | return -EFAULT; | 667 | return -EFAULT; |
645 | } | 668 | } |
646 | return err; | 669 | return err; |
@@ -674,8 +697,8 @@ struct i2c_rdwr_aligned { | |||
674 | struct i2c_msg msgs[0]; | 697 | struct i2c_msg msgs[0]; |
675 | }; | 698 | }; |
676 | 699 | ||
677 | static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, | 700 | static int do_i2c_rdwr_ioctl(struct file *file, |
678 | struct i2c_rdwr_ioctl_data32 __user *udata) | 701 | unsigned int cmd, struct i2c_rdwr_ioctl_data32 __user *udata) |
679 | { | 702 | { |
680 | struct i2c_rdwr_aligned __user *tdata; | 703 | struct i2c_rdwr_aligned __user *tdata; |
681 | struct i2c_msg __user *tmsgs; | 704 | struct i2c_msg __user *tmsgs; |
@@ -708,11 +731,11 @@ static int do_i2c_rdwr_ioctl(unsigned int fd, unsigned int cmd, | |||
708 | put_user(compat_ptr(datap), &tmsgs[i].buf)) | 731 | put_user(compat_ptr(datap), &tmsgs[i].buf)) |
709 | return -EFAULT; | 732 | return -EFAULT; |
710 | } | 733 | } |
711 | return sys_ioctl(fd, cmd, (unsigned long)tdata); | 734 | return do_ioctl(file, cmd, (unsigned long)tdata); |
712 | } | 735 | } |
713 | 736 | ||
714 | static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, | 737 | static int do_i2c_smbus_ioctl(struct file *file, |
715 | struct i2c_smbus_ioctl_data32 __user *udata) | 738 | unsigned int cmd, struct i2c_smbus_ioctl_data32 __user *udata) |
716 | { | 739 | { |
717 | struct i2c_smbus_ioctl_data __user *tdata; | 740 | struct i2c_smbus_ioctl_data __user *tdata; |
718 | compat_caddr_t datap; | 741 | compat_caddr_t datap; |
@@ -734,7 +757,7 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, | |||
734 | __put_user(compat_ptr(datap), &tdata->data)) | 757 | __put_user(compat_ptr(datap), &tdata->data)) |
735 | return -EFAULT; | 758 | return -EFAULT; |
736 | 759 | ||
737 | return sys_ioctl(fd, cmd, (unsigned long)tdata); | 760 | return do_ioctl(file, cmd, (unsigned long)tdata); |
738 | } | 761 | } |
739 | 762 | ||
740 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) | 763 | #define RTC_IRQP_READ32 _IOR('p', 0x0b, compat_ulong_t) |
@@ -742,29 +765,27 @@ static int do_i2c_smbus_ioctl(unsigned int fd, unsigned int cmd, | |||
742 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) | 765 | #define RTC_EPOCH_READ32 _IOR('p', 0x0d, compat_ulong_t) |
743 | #define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) | 766 | #define RTC_EPOCH_SET32 _IOW('p', 0x0e, compat_ulong_t) |
744 | 767 | ||
745 | static int rtc_ioctl(unsigned fd, unsigned cmd, void __user *argp) | 768 | static int rtc_ioctl(struct file *file, |
769 | unsigned cmd, void __user *argp) | ||
746 | { | 770 | { |
747 | mm_segment_t oldfs = get_fs(); | 771 | unsigned long __user *valp = compat_alloc_user_space(sizeof(*valp)); |
748 | compat_ulong_t val32; | ||
749 | unsigned long kval; | ||
750 | int ret; | 772 | int ret; |
751 | 773 | ||
774 | if (valp == NULL) | ||
775 | return -EFAULT; | ||
752 | switch (cmd) { | 776 | switch (cmd) { |
753 | case RTC_IRQP_READ32: | 777 | case RTC_IRQP_READ32: |
754 | case RTC_EPOCH_READ32: | 778 | case RTC_EPOCH_READ32: |
755 | set_fs(KERNEL_DS); | 779 | ret = do_ioctl(file, (cmd == RTC_IRQP_READ32) ? |
756 | ret = sys_ioctl(fd, (cmd == RTC_IRQP_READ32) ? | ||
757 | RTC_IRQP_READ : RTC_EPOCH_READ, | 780 | RTC_IRQP_READ : RTC_EPOCH_READ, |
758 | (unsigned long)&kval); | 781 | (unsigned long)valp); |
759 | set_fs(oldfs); | ||
760 | if (ret) | 782 | if (ret) |
761 | return ret; | 783 | return ret; |
762 | val32 = kval; | 784 | return convert_in_user(valp, (unsigned int __user *)argp); |
763 | return put_user(val32, (unsigned int __user *)argp); | ||
764 | case RTC_IRQP_SET32: | 785 | case RTC_IRQP_SET32: |
765 | return sys_ioctl(fd, RTC_IRQP_SET, (unsigned long)argp); | 786 | return do_ioctl(file, RTC_IRQP_SET, (unsigned long)argp); |
766 | case RTC_EPOCH_SET32: | 787 | case RTC_EPOCH_SET32: |
767 | return sys_ioctl(fd, RTC_EPOCH_SET, (unsigned long)argp); | 788 | return do_ioctl(file, RTC_EPOCH_SET, (unsigned long)argp); |
768 | } | 789 | } |
769 | 790 | ||
770 | return -ENOIOCTLCMD; | 791 | return -ENOIOCTLCMD; |
@@ -1436,53 +1457,53 @@ IGNORE_IOCTL(FBIOGCURSOR32) | |||
1436 | * a compat_ioctl operation in the place that handleѕ the | 1457 | * a compat_ioctl operation in the place that handleѕ the |
1437 | * ioctl for the native case. | 1458 | * ioctl for the native case. |
1438 | */ | 1459 | */ |
1439 | static long do_ioctl_trans(int fd, unsigned int cmd, | 1460 | static long do_ioctl_trans(unsigned int cmd, |
1440 | unsigned long arg, struct file *file) | 1461 | unsigned long arg, struct file *file) |
1441 | { | 1462 | { |
1442 | void __user *argp = compat_ptr(arg); | 1463 | void __user *argp = compat_ptr(arg); |
1443 | 1464 | ||
1444 | switch (cmd) { | 1465 | switch (cmd) { |
1445 | case PPPIOCGIDLE32: | 1466 | case PPPIOCGIDLE32: |
1446 | return ppp_gidle(fd, cmd, argp); | 1467 | return ppp_gidle(file, cmd, argp); |
1447 | case PPPIOCSCOMPRESS32: | 1468 | case PPPIOCSCOMPRESS32: |
1448 | return ppp_scompress(fd, cmd, argp); | 1469 | return ppp_scompress(file, cmd, argp); |
1449 | case PPPIOCSPASS32: | 1470 | case PPPIOCSPASS32: |
1450 | case PPPIOCSACTIVE32: | 1471 | case PPPIOCSACTIVE32: |
1451 | return ppp_sock_fprog_ioctl_trans(fd, cmd, argp); | 1472 | return ppp_sock_fprog_ioctl_trans(file, cmd, argp); |
1452 | #ifdef CONFIG_BLOCK | 1473 | #ifdef CONFIG_BLOCK |
1453 | case SG_IO: | 1474 | case SG_IO: |
1454 | return sg_ioctl_trans(fd, cmd, argp); | 1475 | return sg_ioctl_trans(file, cmd, argp); |
1455 | case SG_GET_REQUEST_TABLE: | 1476 | case SG_GET_REQUEST_TABLE: |
1456 | return sg_grt_trans(fd, cmd, argp); | 1477 | return sg_grt_trans(file, cmd, argp); |
1457 | case MTIOCGET32: | 1478 | case MTIOCGET32: |
1458 | case MTIOCPOS32: | 1479 | case MTIOCPOS32: |
1459 | return mt_ioctl_trans(fd, cmd, argp); | 1480 | return mt_ioctl_trans(file, cmd, argp); |
1460 | #endif | 1481 | #endif |
1461 | /* Serial */ | 1482 | /* Serial */ |
1462 | case TIOCGSERIAL: | 1483 | case TIOCGSERIAL: |
1463 | case TIOCSSERIAL: | 1484 | case TIOCSSERIAL: |
1464 | return serial_struct_ioctl(fd, cmd, argp); | 1485 | return serial_struct_ioctl(file, cmd, argp); |
1465 | /* i2c */ | 1486 | /* i2c */ |
1466 | case I2C_FUNCS: | 1487 | case I2C_FUNCS: |
1467 | return w_long(fd, cmd, argp); | 1488 | return w_long(file, cmd, argp); |
1468 | case I2C_RDWR: | 1489 | case I2C_RDWR: |
1469 | return do_i2c_rdwr_ioctl(fd, cmd, argp); | 1490 | return do_i2c_rdwr_ioctl(file, cmd, argp); |
1470 | case I2C_SMBUS: | 1491 | case I2C_SMBUS: |
1471 | return do_i2c_smbus_ioctl(fd, cmd, argp); | 1492 | return do_i2c_smbus_ioctl(file, cmd, argp); |
1472 | /* Not implemented in the native kernel */ | 1493 | /* Not implemented in the native kernel */ |
1473 | case RTC_IRQP_READ32: | 1494 | case RTC_IRQP_READ32: |
1474 | case RTC_IRQP_SET32: | 1495 | case RTC_IRQP_SET32: |
1475 | case RTC_EPOCH_READ32: | 1496 | case RTC_EPOCH_READ32: |
1476 | case RTC_EPOCH_SET32: | 1497 | case RTC_EPOCH_SET32: |
1477 | return rtc_ioctl(fd, cmd, argp); | 1498 | return rtc_ioctl(file, cmd, argp); |
1478 | 1499 | ||
1479 | /* dvb */ | 1500 | /* dvb */ |
1480 | case VIDEO_GET_EVENT: | 1501 | case VIDEO_GET_EVENT: |
1481 | return do_video_get_event(fd, cmd, argp); | 1502 | return do_video_get_event(file, cmd, argp); |
1482 | case VIDEO_STILLPICTURE: | 1503 | case VIDEO_STILLPICTURE: |
1483 | return do_video_stillpicture(fd, cmd, argp); | 1504 | return do_video_stillpicture(file, cmd, argp); |
1484 | case VIDEO_SET_SPU_PALETTE: | 1505 | case VIDEO_SET_SPU_PALETTE: |
1485 | return do_video_set_spu_palette(fd, cmd, argp); | 1506 | return do_video_set_spu_palette(file, cmd, argp); |
1486 | } | 1507 | } |
1487 | 1508 | ||
1488 | /* | 1509 | /* |
@@ -1513,7 +1534,7 @@ static long do_ioctl_trans(int fd, unsigned int cmd, | |||
1513 | case NBD_SET_BLKSIZE: | 1534 | case NBD_SET_BLKSIZE: |
1514 | case NBD_SET_SIZE: | 1535 | case NBD_SET_SIZE: |
1515 | case NBD_SET_SIZE_BLOCKS: | 1536 | case NBD_SET_SIZE_BLOCKS: |
1516 | return do_vfs_ioctl(file, fd, cmd, arg); | 1537 | return vfs_ioctl(file, cmd, arg); |
1517 | } | 1538 | } |
1518 | 1539 | ||
1519 | return -ENOIOCTLCMD; | 1540 | return -ENOIOCTLCMD; |
@@ -1602,7 +1623,7 @@ COMPAT_SYSCALL_DEFINE3(ioctl, unsigned int, fd, unsigned int, cmd, | |||
1602 | if (compat_ioctl_check_table(XFORM(cmd))) | 1623 | if (compat_ioctl_check_table(XFORM(cmd))) |
1603 | goto found_handler; | 1624 | goto found_handler; |
1604 | 1625 | ||
1605 | error = do_ioctl_trans(fd, cmd, arg, f.file); | 1626 | error = do_ioctl_trans(cmd, arg, f.file); |
1606 | if (error == -ENOIOCTLCMD) | 1627 | if (error == -ENOIOCTLCMD) |
1607 | error = -ENOTTY; | 1628 | error = -ENOTTY; |
1608 | 1629 | ||
diff --git a/fs/internal.h b/fs/internal.h index 71859c4d0b41..e38c08ca437d 100644 --- a/fs/internal.h +++ b/fs/internal.h | |||
@@ -151,3 +151,10 @@ extern void mnt_pin_kill(struct mount *m); | |||
151 | * fs/nsfs.c | 151 | * fs/nsfs.c |
152 | */ | 152 | */ |
153 | extern struct dentry_operations ns_dentry_operations; | 153 | extern struct dentry_operations ns_dentry_operations; |
154 | |||
155 | /* | ||
156 | * fs/ioctl.c | ||
157 | */ | ||
158 | extern int do_vfs_ioctl(struct file *file, unsigned int fd, unsigned int cmd, | ||
159 | unsigned long arg); | ||
160 | extern long vfs_ioctl(struct file *file, unsigned int cmd, unsigned long arg); | ||
diff --git a/fs/ioctl.c b/fs/ioctl.c index 5d01d2638ca5..41c352e81193 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/writeback.h> | 15 | #include <linux/writeback.h> |
16 | #include <linux/buffer_head.h> | 16 | #include <linux/buffer_head.h> |
17 | #include <linux/falloc.h> | 17 | #include <linux/falloc.h> |
18 | #include "internal.h" | ||
18 | 19 | ||
19 | #include <asm/ioctls.h> | 20 | #include <asm/ioctls.h> |
20 | 21 | ||
@@ -32,8 +33,7 @@ | |||
32 | * | 33 | * |
33 | * Returns 0 on success, -errno on error. | 34 | * Returns 0 on success, -errno on error. |
34 | */ | 35 | */ |
35 | static long vfs_ioctl(struct file *filp, unsigned int cmd, | 36 | long vfs_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) |
36 | unsigned long arg) | ||
37 | { | 37 | { |
38 | int error = -ENOTTY; | 38 | int error = -ENOTTY; |
39 | 39 | ||
diff --git a/include/linux/fs.h b/include/linux/fs.h index 3aa514254161..51f9f8d93d4d 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2764,8 +2764,6 @@ extern int vfs_lstat(const char __user *, struct kstat *); | |||
2764 | extern int vfs_fstat(unsigned int, struct kstat *); | 2764 | extern int vfs_fstat(unsigned int, struct kstat *); |
2765 | extern int vfs_fstatat(int , const char __user *, struct kstat *, int); | 2765 | extern int vfs_fstatat(int , const char __user *, struct kstat *, int); |
2766 | 2766 | ||
2767 | extern int do_vfs_ioctl(struct file *filp, unsigned int fd, unsigned int cmd, | ||
2768 | unsigned long arg); | ||
2769 | extern int __generic_block_fiemap(struct inode *inode, | 2767 | extern int __generic_block_fiemap(struct inode *inode, |
2770 | struct fiemap_extent_info *fieinfo, | 2768 | struct fiemap_extent_info *fieinfo, |
2771 | loff_t start, loff_t len, | 2769 | loff_t start, loff_t len, |