diff options
Diffstat (limited to 'fs/fcntl.c')
| -rw-r--r-- | fs/fcntl.c | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/fs/fcntl.c b/fs/fcntl.c index cb1026181bd..6c82e5bac03 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
| @@ -131,7 +131,7 @@ SYSCALL_DEFINE2(dup2, unsigned int, oldfd, unsigned int, newfd) | |||
| 131 | SYSCALL_DEFINE1(dup, unsigned int, fildes) | 131 | SYSCALL_DEFINE1(dup, unsigned int, fildes) |
| 132 | { | 132 | { |
| 133 | int ret = -EBADF; | 133 | int ret = -EBADF; |
| 134 | struct file *file = fget(fildes); | 134 | struct file *file = fget_raw(fildes); |
| 135 | 135 | ||
| 136 | if (file) { | 136 | if (file) { |
| 137 | ret = get_unused_fd(); | 137 | ret = get_unused_fd(); |
| @@ -426,15 +426,35 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
| 426 | return err; | 426 | return err; |
| 427 | } | 427 | } |
| 428 | 428 | ||
| 429 | static int check_fcntl_cmd(unsigned cmd) | ||
| 430 | { | ||
| 431 | switch (cmd) { | ||
| 432 | case F_DUPFD: | ||
| 433 | case F_DUPFD_CLOEXEC: | ||
| 434 | case F_GETFD: | ||
| 435 | case F_SETFD: | ||
| 436 | case F_GETFL: | ||
| 437 | return 1; | ||
| 438 | } | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 429 | SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) | 442 | SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, unsigned long, arg) |
| 430 | { | 443 | { |
| 431 | struct file *filp; | 444 | struct file *filp; |
| 432 | long err = -EBADF; | 445 | long err = -EBADF; |
| 433 | 446 | ||
| 434 | filp = fget(fd); | 447 | filp = fget_raw(fd); |
| 435 | if (!filp) | 448 | if (!filp) |
| 436 | goto out; | 449 | goto out; |
| 437 | 450 | ||
| 451 | if (unlikely(filp->f_mode & FMODE_PATH)) { | ||
| 452 | if (!check_fcntl_cmd(cmd)) { | ||
| 453 | fput(filp); | ||
| 454 | goto out; | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 438 | err = security_file_fcntl(filp, cmd, arg); | 458 | err = security_file_fcntl(filp, cmd, arg); |
| 439 | if (err) { | 459 | if (err) { |
| 440 | fput(filp); | 460 | fput(filp); |
| @@ -456,10 +476,17 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
| 456 | long err; | 476 | long err; |
| 457 | 477 | ||
| 458 | err = -EBADF; | 478 | err = -EBADF; |
| 459 | filp = fget(fd); | 479 | filp = fget_raw(fd); |
| 460 | if (!filp) | 480 | if (!filp) |
| 461 | goto out; | 481 | goto out; |
| 462 | 482 | ||
| 483 | if (unlikely(filp->f_mode & FMODE_PATH)) { | ||
| 484 | if (!check_fcntl_cmd(cmd)) { | ||
| 485 | fput(filp); | ||
| 486 | goto out; | ||
| 487 | } | ||
| 488 | } | ||
| 489 | |||
| 463 | err = security_file_fcntl(filp, cmd, arg); | 490 | err = security_file_fcntl(filp, cmd, arg); |
| 464 | if (err) { | 491 | if (err) { |
| 465 | fput(filp); | 492 | fput(filp); |
| @@ -808,14 +835,14 @@ static int __init fcntl_init(void) | |||
| 808 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY | 835 | * Exceptions: O_NONBLOCK is a two bit define on parisc; O_NDELAY |
| 809 | * is defined as O_NONBLOCK on some platforms and not on others. | 836 | * is defined as O_NONBLOCK on some platforms and not on others. |
| 810 | */ | 837 | */ |
| 811 | BUILD_BUG_ON(18 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( | 838 | BUILD_BUG_ON(19 - 1 /* for O_RDONLY being 0 */ != HWEIGHT32( |
| 812 | O_RDONLY | O_WRONLY | O_RDWR | | 839 | O_RDONLY | O_WRONLY | O_RDWR | |
| 813 | O_CREAT | O_EXCL | O_NOCTTY | | 840 | O_CREAT | O_EXCL | O_NOCTTY | |
| 814 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ | 841 | O_TRUNC | O_APPEND | /* O_NONBLOCK | */ |
| 815 | __O_SYNC | O_DSYNC | FASYNC | | 842 | __O_SYNC | O_DSYNC | FASYNC | |
| 816 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | | 843 | O_DIRECT | O_LARGEFILE | O_DIRECTORY | |
| 817 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | | 844 | O_NOFOLLOW | O_NOATIME | O_CLOEXEC | |
| 818 | __FMODE_EXEC | 845 | __FMODE_EXEC | O_PATH |
| 819 | )); | 846 | )); |
| 820 | 847 | ||
| 821 | fasync_cache = kmem_cache_create("fasync_cache", | 848 | fasync_cache = kmem_cache_create("fasync_cache", |
