diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-05 16:13:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-07-05 16:13:32 -0400 |
commit | 3bad2f1c676581d01e7645eb03e9b27e28b0a92e (patch) | |
tree | 7e946eb2c7dab8c08e473ee1249be9a814728158 | |
parent | b4b8cbf679c4866a523a35d1454884a31bd5d8dc (diff) | |
parent | 8c6657cb50cb037ff58b3f6a547c6569568f3527 (diff) |
Merge branch 'work.misc-set_fs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull misc user access cleanups from Al Viro:
"The first pile is assorted getting rid of cargo-culted access_ok(),
cargo-culted set_fs() and field-by-field copyouts.
The same description applies to a lot of stuff in other branches -
this is just the stuff that didn't fit into a more specific topical
branch"
* 'work.misc-set_fs' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
Switch flock copyin/copyout primitives to copy_{from,to}_user()
fs/fcntl: return -ESRCH in f_setown when pid/pgid can't be found
fs/fcntl: f_setown, avoid undefined behaviour
fs/fcntl: f_setown, allow returning error
lpfc debugfs: get rid of pointless access_ok()
adb: get rid of pointless access_ok()
isdn: get rid of pointless access_ok()
compat statfs: switch to copy_to_user()
fs/locks: don't mess with the address limit in compat_fcntl64
nfsd_readlink(): switch to vfs_get_link()
drbd: ->sendpage() never needed set_fs()
fs/locks: pass kernel struct flock to fcntl_getlk/setlk
fs: locks: Fix some troubles at kernel-doc comments
-rw-r--r-- | drivers/block/drbd/drbd_main.c | 3 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_common.c | 18 | ||||
-rw-r--r-- | drivers/isdn/i4l/isdn_ppp.c | 6 | ||||
-rw-r--r-- | drivers/isdn/isdnloop/isdnloop.c | 2 | ||||
-rw-r--r-- | drivers/macintosh/adb.c | 4 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_debugfs.c | 20 | ||||
-rw-r--r-- | fs/fcntl.c | 231 | ||||
-rw-r--r-- | fs/locks.c | 97 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 39 | ||||
-rw-r--r-- | fs/statfs.c | 58 | ||||
-rw-r--r-- | include/linux/fs.h | 10 | ||||
-rw-r--r-- | net/socket.c | 3 |
12 files changed, 220 insertions, 271 deletions
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c index 5fb99e06ebe4..e2ed28d45ce1 100644 --- a/drivers/block/drbd/drbd_main.c +++ b/drivers/block/drbd/drbd_main.c | |||
@@ -1551,7 +1551,6 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa | |||
1551 | int offset, size_t size, unsigned msg_flags) | 1551 | int offset, size_t size, unsigned msg_flags) |
1552 | { | 1552 | { |
1553 | struct socket *socket = peer_device->connection->data.socket; | 1553 | struct socket *socket = peer_device->connection->data.socket; |
1554 | mm_segment_t oldfs = get_fs(); | ||
1555 | int len = size; | 1554 | int len = size; |
1556 | int err = -EIO; | 1555 | int err = -EIO; |
1557 | 1556 | ||
@@ -1566,7 +1565,6 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa | |||
1566 | 1565 | ||
1567 | msg_flags |= MSG_NOSIGNAL; | 1566 | msg_flags |= MSG_NOSIGNAL; |
1568 | drbd_update_congested(peer_device->connection); | 1567 | drbd_update_congested(peer_device->connection); |
1569 | set_fs(KERNEL_DS); | ||
1570 | do { | 1568 | do { |
1571 | int sent; | 1569 | int sent; |
1572 | 1570 | ||
@@ -1586,7 +1584,6 @@ static int _drbd_send_page(struct drbd_peer_device *peer_device, struct page *pa | |||
1586 | len -= sent; | 1584 | len -= sent; |
1587 | offset += sent; | 1585 | offset += sent; |
1588 | } while (len > 0 /* THINK && device->cstate >= C_CONNECTED*/); | 1586 | } while (len > 0 /* THINK && device->cstate >= C_CONNECTED*/); |
1589 | set_fs(oldfs); | ||
1590 | clear_bit(NET_CONGESTED, &peer_device->connection->flags); | 1587 | clear_bit(NET_CONGESTED, &peer_device->connection->flags); |
1591 | 1588 | ||
1592 | if (len == 0) { | 1589 | if (len == 0) { |
diff --git a/drivers/isdn/i4l/isdn_common.c b/drivers/isdn/i4l/isdn_common.c index 9b856e1890d1..89b09c51ab7c 100644 --- a/drivers/isdn/i4l/isdn_common.c +++ b/drivers/isdn/i4l/isdn_common.c | |||
@@ -1304,9 +1304,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) | |||
1304 | if (arg) { | 1304 | if (arg) { |
1305 | ulong __user *p = argp; | 1305 | ulong __user *p = argp; |
1306 | int i; | 1306 | int i; |
1307 | if (!access_ok(VERIFY_WRITE, p, | ||
1308 | sizeof(ulong) * ISDN_MAX_CHANNELS * 2)) | ||
1309 | return -EFAULT; | ||
1310 | for (i = 0; i < ISDN_MAX_CHANNELS; i++) { | 1307 | for (i = 0; i < ISDN_MAX_CHANNELS; i++) { |
1311 | put_user(dev->ibytes[i], p++); | 1308 | put_user(dev->ibytes[i], p++); |
1312 | put_user(dev->obytes[i], p++); | 1309 | put_user(dev->obytes[i], p++); |
@@ -1540,11 +1537,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) | |||
1540 | char __user *p = argp; | 1537 | char __user *p = argp; |
1541 | int i; | 1538 | int i; |
1542 | 1539 | ||
1543 | if (!access_ok(VERIFY_WRITE, argp, | ||
1544 | (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) | ||
1545 | * ISDN_MAX_CHANNELS)) | ||
1546 | return -EFAULT; | ||
1547 | |||
1548 | for (i = 0; i < ISDN_MAX_CHANNELS; i++) { | 1540 | for (i = 0; i < ISDN_MAX_CHANNELS; i++) { |
1549 | if (copy_to_user(p, dev->mdm.info[i].emu.profile, | 1541 | if (copy_to_user(p, dev->mdm.info[i].emu.profile, |
1550 | ISDN_MODEM_NUMREG)) | 1542 | ISDN_MODEM_NUMREG)) |
@@ -1567,11 +1559,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) | |||
1567 | char __user *p = argp; | 1559 | char __user *p = argp; |
1568 | int i; | 1560 | int i; |
1569 | 1561 | ||
1570 | if (!access_ok(VERIFY_READ, argp, | ||
1571 | (ISDN_MODEM_NUMREG + ISDN_MSNLEN + ISDN_LMSNLEN) | ||
1572 | * ISDN_MAX_CHANNELS)) | ||
1573 | return -EFAULT; | ||
1574 | |||
1575 | for (i = 0; i < ISDN_MAX_CHANNELS; i++) { | 1562 | for (i = 0; i < ISDN_MAX_CHANNELS; i++) { |
1576 | if (copy_from_user(dev->mdm.info[i].emu.profile, p, | 1563 | if (copy_from_user(dev->mdm.info[i].emu.profile, p, |
1577 | ISDN_MODEM_NUMREG)) | 1564 | ISDN_MODEM_NUMREG)) |
@@ -1617,8 +1604,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) | |||
1617 | int j = 0; | 1604 | int j = 0; |
1618 | 1605 | ||
1619 | while (1) { | 1606 | while (1) { |
1620 | if (!access_ok(VERIFY_READ, p, 1)) | ||
1621 | return -EFAULT; | ||
1622 | get_user(bname[j], p++); | 1607 | get_user(bname[j], p++); |
1623 | switch (bname[j]) { | 1608 | switch (bname[j]) { |
1624 | case '\0': | 1609 | case '\0': |
@@ -1685,9 +1670,6 @@ isdn_ioctl(struct file *file, uint cmd, ulong arg) | |||
1685 | drvidx = 0; | 1670 | drvidx = 0; |
1686 | if (drvidx == -1) | 1671 | if (drvidx == -1) |
1687 | return -ENODEV; | 1672 | return -ENODEV; |
1688 | if (!access_ok(VERIFY_WRITE, argp, | ||
1689 | sizeof(isdn_ioctl_struct))) | ||
1690 | return -EFAULT; | ||
1691 | c.driver = drvidx; | 1673 | c.driver = drvidx; |
1692 | c.command = ISDN_CMD_IOCTL; | 1674 | c.command = ISDN_CMD_IOCTL; |
1693 | c.arg = cmd; | 1675 | c.arg = cmd; |
diff --git a/drivers/isdn/i4l/isdn_ppp.c b/drivers/isdn/i4l/isdn_ppp.c index 88e5a025cea7..6c44609fd83a 100644 --- a/drivers/isdn/i4l/isdn_ppp.c +++ b/drivers/isdn/i4l/isdn_ppp.c | |||
@@ -795,9 +795,6 @@ isdn_ppp_read(int min, struct file *file, char __user *buf, int count) | |||
795 | if (!(is->state & IPPP_OPEN)) | 795 | if (!(is->state & IPPP_OPEN)) |
796 | return 0; | 796 | return 0; |
797 | 797 | ||
798 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
799 | return -EFAULT; | ||
800 | |||
801 | spin_lock_irqsave(&is->buflock, flags); | 798 | spin_lock_irqsave(&is->buflock, flags); |
802 | b = is->first->next; | 799 | b = is->first->next; |
803 | save_buf = b->buf; | 800 | save_buf = b->buf; |
@@ -2014,9 +2011,6 @@ isdn_ppp_dev_ioctl_stats(int slot, struct ifreq *ifr, struct net_device *dev) | |||
2014 | struct ppp_stats t; | 2011 | struct ppp_stats t; |
2015 | isdn_net_local *lp = netdev_priv(dev); | 2012 | isdn_net_local *lp = netdev_priv(dev); |
2016 | 2013 | ||
2017 | if (!access_ok(VERIFY_WRITE, res, sizeof(struct ppp_stats))) | ||
2018 | return -EFAULT; | ||
2019 | |||
2020 | /* build a temporary stat struct and copy it to user space */ | 2014 | /* build a temporary stat struct and copy it to user space */ |
2021 | 2015 | ||
2022 | memset(&t, 0, sizeof(struct ppp_stats)); | 2016 | memset(&t, 0, sizeof(struct ppp_stats)); |
diff --git a/drivers/isdn/isdnloop/isdnloop.c b/drivers/isdn/isdnloop/isdnloop.c index 7ac7badb8f55..6ffd13466b8c 100644 --- a/drivers/isdn/isdnloop/isdnloop.c +++ b/drivers/isdn/isdnloop/isdnloop.c | |||
@@ -1142,8 +1142,6 @@ isdnloop_command(isdn_ctrl *c, isdnloop_card *card) | |||
1142 | case ISDNLOOP_IOCTL_DEBUGVAR: | 1142 | case ISDNLOOP_IOCTL_DEBUGVAR: |
1143 | return (ulong) card; | 1143 | return (ulong) card; |
1144 | case ISDNLOOP_IOCTL_STARTUP: | 1144 | case ISDNLOOP_IOCTL_STARTUP: |
1145 | if (!access_ok(VERIFY_READ, (void *) a, sizeof(isdnloop_sdef))) | ||
1146 | return -EFAULT; | ||
1147 | return isdnloop_start(card, (isdnloop_sdef *) a); | 1145 | return isdnloop_start(card, (isdnloop_sdef *) a); |
1148 | break; | 1146 | break; |
1149 | case ISDNLOOP_IOCTL_ADDCARD: | 1147 | case ISDNLOOP_IOCTL_ADDCARD: |
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index fee939efc4fc..039dc8285fc5 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c | |||
@@ -723,8 +723,6 @@ static ssize_t adb_read(struct file *file, char __user *buf, | |||
723 | return -EINVAL; | 723 | return -EINVAL; |
724 | if (count > sizeof(req->reply)) | 724 | if (count > sizeof(req->reply)) |
725 | count = sizeof(req->reply); | 725 | count = sizeof(req->reply); |
726 | if (!access_ok(VERIFY_WRITE, buf, count)) | ||
727 | return -EFAULT; | ||
728 | 726 | ||
729 | req = NULL; | 727 | req = NULL; |
730 | spin_lock_irqsave(&state->lock, flags); | 728 | spin_lock_irqsave(&state->lock, flags); |
@@ -781,8 +779,6 @@ static ssize_t adb_write(struct file *file, const char __user *buf, | |||
781 | return -EINVAL; | 779 | return -EINVAL; |
782 | if (adb_controller == NULL) | 780 | if (adb_controller == NULL) |
783 | return -ENXIO; | 781 | return -ENXIO; |
784 | if (!access_ok(VERIFY_READ, buf, count)) | ||
785 | return -EFAULT; | ||
786 | 782 | ||
787 | req = kmalloc(sizeof(struct adb_request), | 783 | req = kmalloc(sizeof(struct adb_request), |
788 | GFP_KERNEL); | 784 | GFP_KERNEL); |
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 4bcb92c844ca..89afa7813e5a 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c | |||
@@ -1949,10 +1949,6 @@ lpfc_debugfs_nvmestat_write(struct file *file, const char __user *buf, | |||
1949 | if (nbytes > 64) | 1949 | if (nbytes > 64) |
1950 | nbytes = 64; | 1950 | nbytes = 64; |
1951 | 1951 | ||
1952 | /* Protect copy from user */ | ||
1953 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
1954 | return -EFAULT; | ||
1955 | |||
1956 | memset(mybuf, 0, sizeof(mybuf)); | 1952 | memset(mybuf, 0, sizeof(mybuf)); |
1957 | 1953 | ||
1958 | if (copy_from_user(mybuf, buf, nbytes)) | 1954 | if (copy_from_user(mybuf, buf, nbytes)) |
@@ -2037,10 +2033,6 @@ lpfc_debugfs_nvmektime_write(struct file *file, const char __user *buf, | |||
2037 | if (nbytes > 64) | 2033 | if (nbytes > 64) |
2038 | nbytes = 64; | 2034 | nbytes = 64; |
2039 | 2035 | ||
2040 | /* Protect copy from user */ | ||
2041 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
2042 | return -EFAULT; | ||
2043 | |||
2044 | memset(mybuf, 0, sizeof(mybuf)); | 2036 | memset(mybuf, 0, sizeof(mybuf)); |
2045 | 2037 | ||
2046 | if (copy_from_user(mybuf, buf, nbytes)) | 2038 | if (copy_from_user(mybuf, buf, nbytes)) |
@@ -2169,10 +2161,6 @@ lpfc_debugfs_nvmeio_trc_write(struct file *file, const char __user *buf, | |||
2169 | if (nbytes > 64) | 2161 | if (nbytes > 64) |
2170 | nbytes = 64; | 2162 | nbytes = 64; |
2171 | 2163 | ||
2172 | /* Protect copy from user */ | ||
2173 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
2174 | return -EFAULT; | ||
2175 | |||
2176 | memset(mybuf, 0, sizeof(mybuf)); | 2164 | memset(mybuf, 0, sizeof(mybuf)); |
2177 | 2165 | ||
2178 | if (copy_from_user(mybuf, buf, nbytes)) | 2166 | if (copy_from_user(mybuf, buf, nbytes)) |
@@ -2280,10 +2268,6 @@ lpfc_debugfs_cpucheck_write(struct file *file, const char __user *buf, | |||
2280 | if (nbytes > 64) | 2268 | if (nbytes > 64) |
2281 | nbytes = 64; | 2269 | nbytes = 64; |
2282 | 2270 | ||
2283 | /* Protect copy from user */ | ||
2284 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
2285 | return -EFAULT; | ||
2286 | |||
2287 | memset(mybuf, 0, sizeof(mybuf)); | 2271 | memset(mybuf, 0, sizeof(mybuf)); |
2288 | 2272 | ||
2289 | if (copy_from_user(mybuf, buf, nbytes)) | 2273 | if (copy_from_user(mybuf, buf, nbytes)) |
@@ -2354,10 +2338,6 @@ static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes, | |||
2354 | int i; | 2338 | int i; |
2355 | size_t bsize; | 2339 | size_t bsize; |
2356 | 2340 | ||
2357 | /* Protect copy from user */ | ||
2358 | if (!access_ok(VERIFY_READ, buf, nbytes)) | ||
2359 | return -EFAULT; | ||
2360 | |||
2361 | memset(mybuf, 0, sizeof(mybuf)); | 2341 | memset(mybuf, 0, sizeof(mybuf)); |
2362 | memset(idiag_cmd, 0, sizeof(*idiag_cmd)); | 2342 | memset(idiag_cmd, 0, sizeof(*idiag_cmd)); |
2363 | bsize = min(nbytes, (sizeof(mybuf)-1)); | 2343 | bsize = min(nbytes, (sizeof(mybuf)-1)); |
diff --git a/fs/fcntl.c b/fs/fcntl.c index ed051f825bad..b6bd89628025 100644 --- a/fs/fcntl.c +++ b/fs/fcntl.c | |||
@@ -109,20 +109,34 @@ void __f_setown(struct file *filp, struct pid *pid, enum pid_type type, | |||
109 | } | 109 | } |
110 | EXPORT_SYMBOL(__f_setown); | 110 | EXPORT_SYMBOL(__f_setown); |
111 | 111 | ||
112 | void f_setown(struct file *filp, unsigned long arg, int force) | 112 | int f_setown(struct file *filp, unsigned long arg, int force) |
113 | { | 113 | { |
114 | enum pid_type type; | 114 | enum pid_type type; |
115 | struct pid *pid; | 115 | struct pid *pid = NULL; |
116 | int who = arg; | 116 | int who = arg, ret = 0; |
117 | |||
117 | type = PIDTYPE_PID; | 118 | type = PIDTYPE_PID; |
118 | if (who < 0) { | 119 | if (who < 0) { |
120 | /* avoid overflow below */ | ||
121 | if (who == INT_MIN) | ||
122 | return -EINVAL; | ||
123 | |||
119 | type = PIDTYPE_PGID; | 124 | type = PIDTYPE_PGID; |
120 | who = -who; | 125 | who = -who; |
121 | } | 126 | } |
127 | |||
122 | rcu_read_lock(); | 128 | rcu_read_lock(); |
123 | pid = find_vpid(who); | 129 | if (who) { |
124 | __f_setown(filp, pid, type, force); | 130 | pid = find_vpid(who); |
131 | if (!pid) | ||
132 | ret = -ESRCH; | ||
133 | } | ||
134 | |||
135 | if (!ret) | ||
136 | __f_setown(filp, pid, type, force); | ||
125 | rcu_read_unlock(); | 137 | rcu_read_unlock(); |
138 | |||
139 | return ret; | ||
126 | } | 140 | } |
127 | EXPORT_SYMBOL(f_setown); | 141 | EXPORT_SYMBOL(f_setown); |
128 | 142 | ||
@@ -307,6 +321,8 @@ static long fcntl_rw_hint(struct file *file, unsigned int cmd, | |||
307 | static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | 321 | static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, |
308 | struct file *filp) | 322 | struct file *filp) |
309 | { | 323 | { |
324 | void __user *argp = (void __user *)arg; | ||
325 | struct flock flock; | ||
310 | long err = -EINVAL; | 326 | long err = -EINVAL; |
311 | 327 | ||
312 | switch (cmd) { | 328 | switch (cmd) { |
@@ -334,7 +350,11 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
334 | case F_OFD_GETLK: | 350 | case F_OFD_GETLK: |
335 | #endif | 351 | #endif |
336 | case F_GETLK: | 352 | case F_GETLK: |
337 | err = fcntl_getlk(filp, cmd, (struct flock __user *) arg); | 353 | if (copy_from_user(&flock, argp, sizeof(flock))) |
354 | return -EFAULT; | ||
355 | err = fcntl_getlk(filp, cmd, &flock); | ||
356 | if (!err && copy_to_user(argp, &flock, sizeof(flock))) | ||
357 | return -EFAULT; | ||
338 | break; | 358 | break; |
339 | #if BITS_PER_LONG != 32 | 359 | #if BITS_PER_LONG != 32 |
340 | /* 32-bit arches must use fcntl64() */ | 360 | /* 32-bit arches must use fcntl64() */ |
@@ -344,7 +364,9 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
344 | /* Fallthrough */ | 364 | /* Fallthrough */ |
345 | case F_SETLK: | 365 | case F_SETLK: |
346 | case F_SETLKW: | 366 | case F_SETLKW: |
347 | err = fcntl_setlk(fd, filp, cmd, (struct flock __user *) arg); | 367 | if (copy_from_user(&flock, argp, sizeof(flock))) |
368 | return -EFAULT; | ||
369 | err = fcntl_setlk(fd, filp, cmd, &flock); | ||
348 | break; | 370 | break; |
349 | case F_GETOWN: | 371 | case F_GETOWN: |
350 | /* | 372 | /* |
@@ -358,8 +380,7 @@ static long do_fcntl(int fd, unsigned int cmd, unsigned long arg, | |||
358 | force_successful_syscall_return(); | 380 | force_successful_syscall_return(); |
359 | break; | 381 | break; |
360 | case F_SETOWN: | 382 | case F_SETOWN: |
361 | f_setown(filp, arg, 1); | 383 | err = f_setown(filp, arg, 1); |
362 | err = 0; | ||
363 | break; | 384 | break; |
364 | case F_GETOWN_EX: | 385 | case F_GETOWN_EX: |
365 | err = f_getown_ex(filp, arg); | 386 | err = f_getown_ex(filp, arg); |
@@ -450,7 +471,9 @@ out: | |||
450 | SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | 471 | SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, |
451 | unsigned long, arg) | 472 | unsigned long, arg) |
452 | { | 473 | { |
474 | void __user *argp = (void __user *)arg; | ||
453 | struct fd f = fdget_raw(fd); | 475 | struct fd f = fdget_raw(fd); |
476 | struct flock64 flock; | ||
454 | long err = -EBADF; | 477 | long err = -EBADF; |
455 | 478 | ||
456 | if (!f.file) | 479 | if (!f.file) |
@@ -468,14 +491,21 @@ SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | |||
468 | switch (cmd) { | 491 | switch (cmd) { |
469 | case F_GETLK64: | 492 | case F_GETLK64: |
470 | case F_OFD_GETLK: | 493 | case F_OFD_GETLK: |
471 | err = fcntl_getlk64(f.file, cmd, (struct flock64 __user *) arg); | 494 | err = -EFAULT; |
495 | if (copy_from_user(&flock, argp, sizeof(flock))) | ||
496 | break; | ||
497 | err = fcntl_getlk64(f.file, cmd, &flock); | ||
498 | if (!err && copy_to_user(argp, &flock, sizeof(flock))) | ||
499 | err = -EFAULT; | ||
472 | break; | 500 | break; |
473 | case F_SETLK64: | 501 | case F_SETLK64: |
474 | case F_SETLKW64: | 502 | case F_SETLKW64: |
475 | case F_OFD_SETLK: | 503 | case F_OFD_SETLK: |
476 | case F_OFD_SETLKW: | 504 | case F_OFD_SETLKW: |
477 | err = fcntl_setlk64(fd, f.file, cmd, | 505 | err = -EFAULT; |
478 | (struct flock64 __user *) arg); | 506 | if (copy_from_user(&flock, argp, sizeof(flock))) |
507 | break; | ||
508 | err = fcntl_setlk64(fd, f.file, cmd, &flock); | ||
479 | break; | 509 | break; |
480 | default: | 510 | default: |
481 | err = do_fcntl(fd, cmd, arg, f.file); | 511 | err = do_fcntl(fd, cmd, arg, f.file); |
@@ -489,57 +519,56 @@ out: | |||
489 | #endif | 519 | #endif |
490 | 520 | ||
491 | #ifdef CONFIG_COMPAT | 521 | #ifdef CONFIG_COMPAT |
522 | /* careful - don't use anywhere else */ | ||
523 | #define copy_flock_fields(from, to) \ | ||
524 | (to).l_type = (from).l_type; \ | ||
525 | (to).l_whence = (from).l_whence; \ | ||
526 | (to).l_start = (from).l_start; \ | ||
527 | (to).l_len = (from).l_len; \ | ||
528 | (to).l_pid = (from).l_pid; | ||
529 | |||
492 | static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) | 530 | static int get_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) |
493 | { | 531 | { |
494 | if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || | 532 | struct compat_flock fl; |
495 | __get_user(kfl->l_type, &ufl->l_type) || | 533 | |
496 | __get_user(kfl->l_whence, &ufl->l_whence) || | 534 | if (copy_from_user(&fl, ufl, sizeof(struct compat_flock))) |
497 | __get_user(kfl->l_start, &ufl->l_start) || | ||
498 | __get_user(kfl->l_len, &ufl->l_len) || | ||
499 | __get_user(kfl->l_pid, &ufl->l_pid)) | ||
500 | return -EFAULT; | 535 | return -EFAULT; |
536 | copy_flock_fields(*kfl, fl); | ||
501 | return 0; | 537 | return 0; |
502 | } | 538 | } |
503 | 539 | ||
504 | static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) | 540 | static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) |
505 | { | 541 | { |
506 | if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) || | 542 | struct compat_flock64 fl; |
507 | __put_user(kfl->l_type, &ufl->l_type) || | 543 | |
508 | __put_user(kfl->l_whence, &ufl->l_whence) || | 544 | if (copy_from_user(&fl, ufl, sizeof(struct compat_flock64))) |
509 | __put_user(kfl->l_start, &ufl->l_start) || | ||
510 | __put_user(kfl->l_len, &ufl->l_len) || | ||
511 | __put_user(kfl->l_pid, &ufl->l_pid)) | ||
512 | return -EFAULT; | 545 | return -EFAULT; |
546 | copy_flock_fields(*kfl, fl); | ||
513 | return 0; | 547 | return 0; |
514 | } | 548 | } |
515 | 549 | ||
516 | #ifndef HAVE_ARCH_GET_COMPAT_FLOCK64 | 550 | static int put_compat_flock(struct flock *kfl, struct compat_flock __user *ufl) |
517 | static int get_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) | ||
518 | { | 551 | { |
519 | if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) || | 552 | struct compat_flock fl; |
520 | __get_user(kfl->l_type, &ufl->l_type) || | 553 | |
521 | __get_user(kfl->l_whence, &ufl->l_whence) || | 554 | memset(&fl, 0, sizeof(struct compat_flock)); |
522 | __get_user(kfl->l_start, &ufl->l_start) || | 555 | copy_flock_fields(fl, *kfl); |
523 | __get_user(kfl->l_len, &ufl->l_len) || | 556 | if (copy_to_user(ufl, &fl, sizeof(struct compat_flock))) |
524 | __get_user(kfl->l_pid, &ufl->l_pid)) | ||
525 | return -EFAULT; | 557 | return -EFAULT; |
526 | return 0; | 558 | return 0; |
527 | } | 559 | } |
528 | #endif | ||
529 | 560 | ||
530 | #ifndef HAVE_ARCH_PUT_COMPAT_FLOCK64 | ||
531 | static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) | 561 | static int put_compat_flock64(struct flock *kfl, struct compat_flock64 __user *ufl) |
532 | { | 562 | { |
533 | if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) || | 563 | struct compat_flock64 fl; |
534 | __put_user(kfl->l_type, &ufl->l_type) || | 564 | |
535 | __put_user(kfl->l_whence, &ufl->l_whence) || | 565 | memset(&fl, 0, sizeof(struct compat_flock64)); |
536 | __put_user(kfl->l_start, &ufl->l_start) || | 566 | copy_flock_fields(fl, *kfl); |
537 | __put_user(kfl->l_len, &ufl->l_len) || | 567 | if (copy_to_user(ufl, &fl, sizeof(struct compat_flock64))) |
538 | __put_user(kfl->l_pid, &ufl->l_pid)) | ||
539 | return -EFAULT; | 568 | return -EFAULT; |
540 | return 0; | 569 | return 0; |
541 | } | 570 | } |
542 | #endif | 571 | #undef copy_flock_fields |
543 | 572 | ||
544 | static unsigned int | 573 | static unsigned int |
545 | convert_fcntl_cmd(unsigned int cmd) | 574 | convert_fcntl_cmd(unsigned int cmd) |
@@ -556,76 +585,92 @@ convert_fcntl_cmd(unsigned int cmd) | |||
556 | return cmd; | 585 | return cmd; |
557 | } | 586 | } |
558 | 587 | ||
588 | /* | ||
589 | * GETLK was successful and we need to return the data, but it needs to fit in | ||
590 | * the compat structure. | ||
591 | * l_start shouldn't be too big, unless the original start + end is greater than | ||
592 | * COMPAT_OFF_T_MAX, in which case the app was asking for trouble, so we return | ||
593 | * -EOVERFLOW in that case. l_len could be too big, in which case we just | ||
594 | * truncate it, and only allow the app to see that part of the conflicting lock | ||
595 | * that might make sense to it anyway | ||
596 | */ | ||
597 | static int fixup_compat_flock(struct flock *flock) | ||
598 | { | ||
599 | if (flock->l_start > COMPAT_OFF_T_MAX) | ||
600 | return -EOVERFLOW; | ||
601 | if (flock->l_len > COMPAT_OFF_T_MAX) | ||
602 | flock->l_len = COMPAT_OFF_T_MAX; | ||
603 | return 0; | ||
604 | } | ||
605 | |||
559 | COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, | 606 | COMPAT_SYSCALL_DEFINE3(fcntl64, unsigned int, fd, unsigned int, cmd, |
560 | compat_ulong_t, arg) | 607 | compat_ulong_t, arg) |
561 | { | 608 | { |
562 | mm_segment_t old_fs; | 609 | struct fd f = fdget_raw(fd); |
563 | struct flock f; | 610 | struct flock flock; |
564 | long ret; | 611 | long err = -EBADF; |
565 | unsigned int conv_cmd; | 612 | |
613 | if (!f.file) | ||
614 | return err; | ||
615 | |||
616 | if (unlikely(f.file->f_mode & FMODE_PATH)) { | ||
617 | if (!check_fcntl_cmd(cmd)) | ||
618 | goto out_put; | ||
619 | } | ||
620 | |||
621 | err = security_file_fcntl(f.file, cmd, arg); | ||
622 | if (err) | ||
623 | goto out_put; | ||
566 | 624 | ||
567 | switch (cmd) { | 625 | switch (cmd) { |
568 | case F_GETLK: | 626 | case F_GETLK: |
627 | err = get_compat_flock(&flock, compat_ptr(arg)); | ||
628 | if (err) | ||
629 | break; | ||
630 | err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock); | ||
631 | if (err) | ||
632 | break; | ||
633 | err = fixup_compat_flock(&flock); | ||
634 | if (err) | ||
635 | return err; | ||
636 | err = put_compat_flock(&flock, compat_ptr(arg)); | ||
637 | break; | ||
638 | case F_GETLK64: | ||
639 | case F_OFD_GETLK: | ||
640 | err = get_compat_flock64(&flock, compat_ptr(arg)); | ||
641 | if (err) | ||
642 | break; | ||
643 | err = fcntl_getlk(f.file, convert_fcntl_cmd(cmd), &flock); | ||
644 | if (err) | ||
645 | break; | ||
646 | err = fixup_compat_flock(&flock); | ||
647 | if (err) | ||
648 | return err; | ||
649 | err = put_compat_flock64(&flock, compat_ptr(arg)); | ||
650 | break; | ||
569 | case F_SETLK: | 651 | case F_SETLK: |
570 | case F_SETLKW: | 652 | case F_SETLKW: |
571 | ret = get_compat_flock(&f, compat_ptr(arg)); | 653 | err = get_compat_flock(&flock, compat_ptr(arg)); |
572 | if (ret != 0) | 654 | if (err) |
573 | break; | 655 | break; |
574 | old_fs = get_fs(); | 656 | err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock); |
575 | set_fs(KERNEL_DS); | ||
576 | ret = sys_fcntl(fd, cmd, (unsigned long)&f); | ||
577 | set_fs(old_fs); | ||
578 | if (cmd == F_GETLK && ret == 0) { | ||
579 | /* GETLK was successful and we need to return the data... | ||
580 | * but it needs to fit in the compat structure. | ||
581 | * l_start shouldn't be too big, unless the original | ||
582 | * start + end is greater than COMPAT_OFF_T_MAX, in which | ||
583 | * case the app was asking for trouble, so we return | ||
584 | * -EOVERFLOW in that case. | ||
585 | * l_len could be too big, in which case we just truncate it, | ||
586 | * and only allow the app to see that part of the conflicting | ||
587 | * lock that might make sense to it anyway | ||
588 | */ | ||
589 | |||
590 | if (f.l_start > COMPAT_OFF_T_MAX) | ||
591 | ret = -EOVERFLOW; | ||
592 | if (f.l_len > COMPAT_OFF_T_MAX) | ||
593 | f.l_len = COMPAT_OFF_T_MAX; | ||
594 | if (ret == 0) | ||
595 | ret = put_compat_flock(&f, compat_ptr(arg)); | ||
596 | } | ||
597 | break; | 657 | break; |
598 | |||
599 | case F_GETLK64: | ||
600 | case F_SETLK64: | 658 | case F_SETLK64: |
601 | case F_SETLKW64: | 659 | case F_SETLKW64: |
602 | case F_OFD_GETLK: | ||
603 | case F_OFD_SETLK: | 660 | case F_OFD_SETLK: |
604 | case F_OFD_SETLKW: | 661 | case F_OFD_SETLKW: |
605 | ret = get_compat_flock64(&f, compat_ptr(arg)); | 662 | err = get_compat_flock64(&flock, compat_ptr(arg)); |
606 | if (ret != 0) | 663 | if (err) |
607 | break; | 664 | break; |
608 | old_fs = get_fs(); | 665 | err = fcntl_setlk(fd, f.file, convert_fcntl_cmd(cmd), &flock); |
609 | set_fs(KERNEL_DS); | ||
610 | conv_cmd = convert_fcntl_cmd(cmd); | ||
611 | ret = sys_fcntl(fd, conv_cmd, (unsigned long)&f); | ||
612 | set_fs(old_fs); | ||
613 | if ((conv_cmd == F_GETLK || conv_cmd == F_OFD_GETLK) && ret == 0) { | ||
614 | /* need to return lock information - see above for commentary */ | ||
615 | if (f.l_start > COMPAT_LOFF_T_MAX) | ||
616 | ret = -EOVERFLOW; | ||
617 | if (f.l_len > COMPAT_LOFF_T_MAX) | ||
618 | f.l_len = COMPAT_LOFF_T_MAX; | ||
619 | if (ret == 0) | ||
620 | ret = put_compat_flock64(&f, compat_ptr(arg)); | ||
621 | } | ||
622 | break; | 666 | break; |
623 | |||
624 | default: | 667 | default: |
625 | ret = sys_fcntl(fd, cmd, arg); | 668 | err = do_fcntl(fd, cmd, arg, f.file); |
626 | break; | 669 | break; |
627 | } | 670 | } |
628 | return ret; | 671 | out_put: |
672 | fdput(f); | ||
673 | return err; | ||
629 | } | 674 | } |
630 | 675 | ||
631 | COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, | 676 | COMPAT_SYSCALL_DEFINE3(fcntl, unsigned int, fd, unsigned int, cmd, |
diff --git a/fs/locks.c b/fs/locks.c index af2031a1fcff..afefeb4ad6de 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -1858,8 +1858,8 @@ EXPORT_SYMBOL(generic_setlease); | |||
1858 | * | 1858 | * |
1859 | * Call this to establish a lease on the file. The "lease" argument is not | 1859 | * Call this to establish a lease on the file. The "lease" argument is not |
1860 | * used for F_UNLCK requests and may be NULL. For commands that set or alter | 1860 | * used for F_UNLCK requests and may be NULL. For commands that set or alter |
1861 | * an existing lease, the (*lease)->fl_lmops->lm_break operation must be set; | 1861 | * an existing lease, the ``(*lease)->fl_lmops->lm_break`` operation must be |
1862 | * if not, this function will return -ENOLCK (and generate a scary-looking | 1862 | * set; if not, this function will return -ENOLCK (and generate a scary-looking |
1863 | * stack trace). | 1863 | * stack trace). |
1864 | * | 1864 | * |
1865 | * The "priv" pointer is passed directly to the lm_setup function as-is. It | 1865 | * The "priv" pointer is passed directly to the lm_setup function as-is. It |
@@ -1972,15 +1972,13 @@ EXPORT_SYMBOL(locks_lock_inode_wait); | |||
1972 | * @cmd: the type of lock to apply. | 1972 | * @cmd: the type of lock to apply. |
1973 | * | 1973 | * |
1974 | * Apply a %FL_FLOCK style lock to an open file descriptor. | 1974 | * Apply a %FL_FLOCK style lock to an open file descriptor. |
1975 | * The @cmd can be one of | 1975 | * The @cmd can be one of: |
1976 | * | 1976 | * |
1977 | * %LOCK_SH -- a shared lock. | 1977 | * - %LOCK_SH -- a shared lock. |
1978 | * | 1978 | * - %LOCK_EX -- an exclusive lock. |
1979 | * %LOCK_EX -- an exclusive lock. | 1979 | * - %LOCK_UN -- remove an existing lock. |
1980 | * | 1980 | * - %LOCK_MAND -- a 'mandatory' flock. |
1981 | * %LOCK_UN -- remove an existing lock. | 1981 | * This exists to emulate Windows Share Modes. |
1982 | * | ||
1983 | * %LOCK_MAND -- a `mandatory' flock. This exists to emulate Windows Share Modes. | ||
1984 | * | 1982 | * |
1985 | * %LOCK_MAND can be combined with %LOCK_READ or %LOCK_WRITE to allow other | 1983 | * %LOCK_MAND can be combined with %LOCK_READ or %LOCK_WRITE to allow other |
1986 | * processes read and write access respectively. | 1984 | * processes read and write access respectively. |
@@ -2086,26 +2084,22 @@ static void posix_lock_to_flock64(struct flock64 *flock, struct file_lock *fl) | |||
2086 | /* Report the first existing lock that would conflict with l. | 2084 | /* Report the first existing lock that would conflict with l. |
2087 | * This implements the F_GETLK command of fcntl(). | 2085 | * This implements the F_GETLK command of fcntl(). |
2088 | */ | 2086 | */ |
2089 | int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) | 2087 | int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock *flock) |
2090 | { | 2088 | { |
2091 | struct file_lock file_lock; | 2089 | struct file_lock file_lock; |
2092 | struct flock flock; | ||
2093 | int error; | 2090 | int error; |
2094 | 2091 | ||
2095 | error = -EFAULT; | ||
2096 | if (copy_from_user(&flock, l, sizeof(flock))) | ||
2097 | goto out; | ||
2098 | error = -EINVAL; | 2092 | error = -EINVAL; |
2099 | if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) | 2093 | if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK) |
2100 | goto out; | 2094 | goto out; |
2101 | 2095 | ||
2102 | error = flock_to_posix_lock(filp, &file_lock, &flock); | 2096 | error = flock_to_posix_lock(filp, &file_lock, flock); |
2103 | if (error) | 2097 | if (error) |
2104 | goto out; | 2098 | goto out; |
2105 | 2099 | ||
2106 | if (cmd == F_OFD_GETLK) { | 2100 | if (cmd == F_OFD_GETLK) { |
2107 | error = -EINVAL; | 2101 | error = -EINVAL; |
2108 | if (flock.l_pid != 0) | 2102 | if (flock->l_pid != 0) |
2109 | goto out; | 2103 | goto out; |
2110 | 2104 | ||
2111 | cmd = F_GETLK; | 2105 | cmd = F_GETLK; |
@@ -2117,15 +2111,12 @@ int fcntl_getlk(struct file *filp, unsigned int cmd, struct flock __user *l) | |||
2117 | if (error) | 2111 | if (error) |
2118 | goto out; | 2112 | goto out; |
2119 | 2113 | ||
2120 | flock.l_type = file_lock.fl_type; | 2114 | flock->l_type = file_lock.fl_type; |
2121 | if (file_lock.fl_type != F_UNLCK) { | 2115 | if (file_lock.fl_type != F_UNLCK) { |
2122 | error = posix_lock_to_flock(&flock, &file_lock); | 2116 | error = posix_lock_to_flock(flock, &file_lock); |
2123 | if (error) | 2117 | if (error) |
2124 | goto rel_priv; | 2118 | goto rel_priv; |
2125 | } | 2119 | } |
2126 | error = -EFAULT; | ||
2127 | if (!copy_to_user(l, &flock, sizeof(flock))) | ||
2128 | error = 0; | ||
2129 | rel_priv: | 2120 | rel_priv: |
2130 | locks_release_private(&file_lock); | 2121 | locks_release_private(&file_lock); |
2131 | out: | 2122 | out: |
@@ -2218,26 +2209,16 @@ check_fmode_for_setlk(struct file_lock *fl) | |||
2218 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 2209 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
2219 | */ | 2210 | */ |
2220 | int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, | 2211 | int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, |
2221 | struct flock __user *l) | 2212 | struct flock *flock) |
2222 | { | 2213 | { |
2223 | struct file_lock *file_lock = locks_alloc_lock(); | 2214 | struct file_lock *file_lock = locks_alloc_lock(); |
2224 | struct flock flock; | 2215 | struct inode *inode = locks_inode(filp); |
2225 | struct inode *inode; | ||
2226 | struct file *f; | 2216 | struct file *f; |
2227 | int error; | 2217 | int error; |
2228 | 2218 | ||
2229 | if (file_lock == NULL) | 2219 | if (file_lock == NULL) |
2230 | return -ENOLCK; | 2220 | return -ENOLCK; |
2231 | 2221 | ||
2232 | inode = locks_inode(filp); | ||
2233 | |||
2234 | /* | ||
2235 | * This might block, so we do it before checking the inode. | ||
2236 | */ | ||
2237 | error = -EFAULT; | ||
2238 | if (copy_from_user(&flock, l, sizeof(flock))) | ||
2239 | goto out; | ||
2240 | |||
2241 | /* Don't allow mandatory locks on files that may be memory mapped | 2222 | /* Don't allow mandatory locks on files that may be memory mapped |
2242 | * and shared. | 2223 | * and shared. |
2243 | */ | 2224 | */ |
@@ -2246,7 +2227,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, | |||
2246 | goto out; | 2227 | goto out; |
2247 | } | 2228 | } |
2248 | 2229 | ||
2249 | error = flock_to_posix_lock(filp, file_lock, &flock); | 2230 | error = flock_to_posix_lock(filp, file_lock, flock); |
2250 | if (error) | 2231 | if (error) |
2251 | goto out; | 2232 | goto out; |
2252 | 2233 | ||
@@ -2261,7 +2242,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, | |||
2261 | switch (cmd) { | 2242 | switch (cmd) { |
2262 | case F_OFD_SETLK: | 2243 | case F_OFD_SETLK: |
2263 | error = -EINVAL; | 2244 | error = -EINVAL; |
2264 | if (flock.l_pid != 0) | 2245 | if (flock->l_pid != 0) |
2265 | goto out; | 2246 | goto out; |
2266 | 2247 | ||
2267 | cmd = F_SETLK; | 2248 | cmd = F_SETLK; |
@@ -2270,7 +2251,7 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd, | |||
2270 | break; | 2251 | break; |
2271 | case F_OFD_SETLKW: | 2252 | case F_OFD_SETLKW: |
2272 | error = -EINVAL; | 2253 | error = -EINVAL; |
2273 | if (flock.l_pid != 0) | 2254 | if (flock->l_pid != 0) |
2274 | goto out; | 2255 | goto out; |
2275 | 2256 | ||
2276 | cmd = F_SETLKW; | 2257 | cmd = F_SETLKW; |
@@ -2315,26 +2296,22 @@ out: | |||
2315 | /* Report the first existing lock that would conflict with l. | 2296 | /* Report the first existing lock that would conflict with l. |
2316 | * This implements the F_GETLK command of fcntl(). | 2297 | * This implements the F_GETLK command of fcntl(). |
2317 | */ | 2298 | */ |
2318 | int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) | 2299 | int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 *flock) |
2319 | { | 2300 | { |
2320 | struct file_lock file_lock; | 2301 | struct file_lock file_lock; |
2321 | struct flock64 flock; | ||
2322 | int error; | 2302 | int error; |
2323 | 2303 | ||
2324 | error = -EFAULT; | ||
2325 | if (copy_from_user(&flock, l, sizeof(flock))) | ||
2326 | goto out; | ||
2327 | error = -EINVAL; | 2304 | error = -EINVAL; |
2328 | if ((flock.l_type != F_RDLCK) && (flock.l_type != F_WRLCK)) | 2305 | if (flock->l_type != F_RDLCK && flock->l_type != F_WRLCK) |
2329 | goto out; | 2306 | goto out; |
2330 | 2307 | ||
2331 | error = flock64_to_posix_lock(filp, &file_lock, &flock); | 2308 | error = flock64_to_posix_lock(filp, &file_lock, flock); |
2332 | if (error) | 2309 | if (error) |
2333 | goto out; | 2310 | goto out; |
2334 | 2311 | ||
2335 | if (cmd == F_OFD_GETLK) { | 2312 | if (cmd == F_OFD_GETLK) { |
2336 | error = -EINVAL; | 2313 | error = -EINVAL; |
2337 | if (flock.l_pid != 0) | 2314 | if (flock->l_pid != 0) |
2338 | goto out; | 2315 | goto out; |
2339 | 2316 | ||
2340 | cmd = F_GETLK64; | 2317 | cmd = F_GETLK64; |
@@ -2346,13 +2323,9 @@ int fcntl_getlk64(struct file *filp, unsigned int cmd, struct flock64 __user *l) | |||
2346 | if (error) | 2323 | if (error) |
2347 | goto out; | 2324 | goto out; |
2348 | 2325 | ||
2349 | flock.l_type = file_lock.fl_type; | 2326 | flock->l_type = file_lock.fl_type; |
2350 | if (file_lock.fl_type != F_UNLCK) | 2327 | if (file_lock.fl_type != F_UNLCK) |
2351 | posix_lock_to_flock64(&flock, &file_lock); | 2328 | posix_lock_to_flock64(flock, &file_lock); |
2352 | |||
2353 | error = -EFAULT; | ||
2354 | if (!copy_to_user(l, &flock, sizeof(flock))) | ||
2355 | error = 0; | ||
2356 | 2329 | ||
2357 | locks_release_private(&file_lock); | 2330 | locks_release_private(&file_lock); |
2358 | out: | 2331 | out: |
@@ -2363,26 +2336,16 @@ out: | |||
2363 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). | 2336 | * This implements both the F_SETLK and F_SETLKW commands of fcntl(). |
2364 | */ | 2337 | */ |
2365 | int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, | 2338 | int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, |
2366 | struct flock64 __user *l) | 2339 | struct flock64 *flock) |
2367 | { | 2340 | { |
2368 | struct file_lock *file_lock = locks_alloc_lock(); | 2341 | struct file_lock *file_lock = locks_alloc_lock(); |
2369 | struct flock64 flock; | 2342 | struct inode *inode = locks_inode(filp); |
2370 | struct inode *inode; | ||
2371 | struct file *f; | 2343 | struct file *f; |
2372 | int error; | 2344 | int error; |
2373 | 2345 | ||
2374 | if (file_lock == NULL) | 2346 | if (file_lock == NULL) |
2375 | return -ENOLCK; | 2347 | return -ENOLCK; |
2376 | 2348 | ||
2377 | /* | ||
2378 | * This might block, so we do it before checking the inode. | ||
2379 | */ | ||
2380 | error = -EFAULT; | ||
2381 | if (copy_from_user(&flock, l, sizeof(flock))) | ||
2382 | goto out; | ||
2383 | |||
2384 | inode = locks_inode(filp); | ||
2385 | |||
2386 | /* Don't allow mandatory locks on files that may be memory mapped | 2349 | /* Don't allow mandatory locks on files that may be memory mapped |
2387 | * and shared. | 2350 | * and shared. |
2388 | */ | 2351 | */ |
@@ -2391,7 +2354,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, | |||
2391 | goto out; | 2354 | goto out; |
2392 | } | 2355 | } |
2393 | 2356 | ||
2394 | error = flock64_to_posix_lock(filp, file_lock, &flock); | 2357 | error = flock64_to_posix_lock(filp, file_lock, flock); |
2395 | if (error) | 2358 | if (error) |
2396 | goto out; | 2359 | goto out; |
2397 | 2360 | ||
@@ -2406,7 +2369,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, | |||
2406 | switch (cmd) { | 2369 | switch (cmd) { |
2407 | case F_OFD_SETLK: | 2370 | case F_OFD_SETLK: |
2408 | error = -EINVAL; | 2371 | error = -EINVAL; |
2409 | if (flock.l_pid != 0) | 2372 | if (flock->l_pid != 0) |
2410 | goto out; | 2373 | goto out; |
2411 | 2374 | ||
2412 | cmd = F_SETLK64; | 2375 | cmd = F_SETLK64; |
@@ -2415,7 +2378,7 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd, | |||
2415 | break; | 2378 | break; |
2416 | case F_OFD_SETLKW: | 2379 | case F_OFD_SETLKW: |
2417 | error = -EINVAL; | 2380 | error = -EINVAL; |
2418 | if (flock.l_pid != 0) | 2381 | if (flock->l_pid != 0) |
2419 | goto out; | 2382 | goto out; |
2420 | 2383 | ||
2421 | cmd = F_SETLKW64; | 2384 | cmd = F_SETLKW64; |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 2be32955d7f2..6eef95c585e3 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1464,41 +1464,34 @@ do_nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1464 | __be32 | 1464 | __be32 |
1465 | nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) | 1465 | nfsd_readlink(struct svc_rqst *rqstp, struct svc_fh *fhp, char *buf, int *lenp) |
1466 | { | 1466 | { |
1467 | mm_segment_t oldfs; | ||
1468 | __be32 err; | 1467 | __be32 err; |
1469 | int host_err; | 1468 | const char *link; |
1470 | struct path path; | 1469 | struct path path; |
1470 | DEFINE_DELAYED_CALL(done); | ||
1471 | int len; | ||
1471 | 1472 | ||
1472 | err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP); | 1473 | err = fh_verify(rqstp, fhp, S_IFLNK, NFSD_MAY_NOP); |
1473 | if (err) | 1474 | if (unlikely(err)) |
1474 | goto out; | 1475 | return err; |
1475 | 1476 | ||
1476 | path.mnt = fhp->fh_export->ex_path.mnt; | 1477 | path.mnt = fhp->fh_export->ex_path.mnt; |
1477 | path.dentry = fhp->fh_dentry; | 1478 | path.dentry = fhp->fh_dentry; |
1478 | 1479 | ||
1479 | err = nfserr_inval; | 1480 | if (unlikely(!d_is_symlink(path.dentry))) |
1480 | if (!d_is_symlink(path.dentry)) | 1481 | return nfserr_inval; |
1481 | goto out; | ||
1482 | 1482 | ||
1483 | touch_atime(&path); | 1483 | touch_atime(&path); |
1484 | /* N.B. Why does this call need a get_fs()?? | ||
1485 | * Remove the set_fs and watch the fireworks:-) --okir | ||
1486 | */ | ||
1487 | 1484 | ||
1488 | oldfs = get_fs(); set_fs(KERNEL_DS); | 1485 | link = vfs_get_link(path.dentry, &done); |
1489 | host_err = vfs_readlink(path.dentry, (char __user *)buf, *lenp); | 1486 | if (IS_ERR(link)) |
1490 | set_fs(oldfs); | 1487 | return nfserrno(PTR_ERR(link)); |
1491 | 1488 | ||
1492 | if (host_err < 0) | 1489 | len = strlen(link); |
1493 | goto out_nfserr; | 1490 | if (len < *lenp) |
1494 | *lenp = host_err; | 1491 | *lenp = len; |
1495 | err = 0; | 1492 | memcpy(buf, link, *lenp); |
1496 | out: | 1493 | do_delayed_call(&done); |
1497 | return err; | 1494 | return 0; |
1498 | |||
1499 | out_nfserr: | ||
1500 | err = nfserrno(host_err); | ||
1501 | goto out; | ||
1502 | } | 1495 | } |
1503 | 1496 | ||
1504 | /* | 1497 | /* |
diff --git a/fs/statfs.c b/fs/statfs.c index 4e4623c7a126..41a6a82da5e2 100644 --- a/fs/statfs.c +++ b/fs/statfs.c | |||
@@ -244,6 +244,7 @@ SYSCALL_DEFINE2(ustat, unsigned, dev, struct ustat __user *, ubuf) | |||
244 | #ifdef CONFIG_COMPAT | 244 | #ifdef CONFIG_COMPAT |
245 | static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) | 245 | static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs *kbuf) |
246 | { | 246 | { |
247 | struct compat_statfs buf; | ||
247 | if (sizeof ubuf->f_blocks == 4) { | 248 | if (sizeof ubuf->f_blocks == 4) { |
248 | if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | | 249 | if ((kbuf->f_blocks | kbuf->f_bfree | kbuf->f_bavail | |
249 | kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) | 250 | kbuf->f_bsize | kbuf->f_frsize) & 0xffffffff00000000ULL) |
@@ -257,20 +258,20 @@ static int put_compat_statfs(struct compat_statfs __user *ubuf, struct kstatfs * | |||
257 | && (kbuf->f_ffree & 0xffffffff00000000ULL)) | 258 | && (kbuf->f_ffree & 0xffffffff00000000ULL)) |
258 | return -EOVERFLOW; | 259 | return -EOVERFLOW; |
259 | } | 260 | } |
260 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || | 261 | memset(&buf, 0, sizeof(struct compat_statfs)); |
261 | __put_user(kbuf->f_type, &ubuf->f_type) || | 262 | buf.f_type = kbuf->f_type; |
262 | __put_user(kbuf->f_bsize, &ubuf->f_bsize) || | 263 | buf.f_bsize = kbuf->f_bsize; |
263 | __put_user(kbuf->f_blocks, &ubuf->f_blocks) || | 264 | buf.f_blocks = kbuf->f_blocks; |
264 | __put_user(kbuf->f_bfree, &ubuf->f_bfree) || | 265 | buf.f_bfree = kbuf->f_bfree; |
265 | __put_user(kbuf->f_bavail, &ubuf->f_bavail) || | 266 | buf.f_bavail = kbuf->f_bavail; |
266 | __put_user(kbuf->f_files, &ubuf->f_files) || | 267 | buf.f_files = kbuf->f_files; |
267 | __put_user(kbuf->f_ffree, &ubuf->f_ffree) || | 268 | buf.f_ffree = kbuf->f_ffree; |
268 | __put_user(kbuf->f_namelen, &ubuf->f_namelen) || | 269 | buf.f_namelen = kbuf->f_namelen; |
269 | __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || | 270 | buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; |
270 | __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || | 271 | buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; |
271 | __put_user(kbuf->f_frsize, &ubuf->f_frsize) || | 272 | buf.f_frsize = kbuf->f_frsize; |
272 | __put_user(kbuf->f_flags, &ubuf->f_flags) || | 273 | buf.f_flags = kbuf->f_flags; |
273 | __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare))) | 274 | if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs))) |
274 | return -EFAULT; | 275 | return -EFAULT; |
275 | return 0; | 276 | return 0; |
276 | } | 277 | } |
@@ -299,6 +300,7 @@ COMPAT_SYSCALL_DEFINE2(fstatfs, unsigned int, fd, struct compat_statfs __user *, | |||
299 | 300 | ||
300 | static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) | 301 | static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstatfs *kbuf) |
301 | { | 302 | { |
303 | struct compat_statfs64 buf; | ||
302 | if (sizeof(ubuf->f_bsize) == 4) { | 304 | if (sizeof(ubuf->f_bsize) == 4) { |
303 | if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen | | 305 | if ((kbuf->f_type | kbuf->f_bsize | kbuf->f_namelen | |
304 | kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL) | 306 | kbuf->f_frsize | kbuf->f_flags) & 0xffffffff00000000ULL) |
@@ -312,20 +314,20 @@ static int put_compat_statfs64(struct compat_statfs64 __user *ubuf, struct kstat | |||
312 | && (kbuf->f_ffree & 0xffffffff00000000ULL)) | 314 | && (kbuf->f_ffree & 0xffffffff00000000ULL)) |
313 | return -EOVERFLOW; | 315 | return -EOVERFLOW; |
314 | } | 316 | } |
315 | if (!access_ok(VERIFY_WRITE, ubuf, sizeof(*ubuf)) || | 317 | memset(&buf, 0, sizeof(struct compat_statfs64)); |
316 | __put_user(kbuf->f_type, &ubuf->f_type) || | 318 | buf.f_type = kbuf->f_type; |
317 | __put_user(kbuf->f_bsize, &ubuf->f_bsize) || | 319 | buf.f_bsize = kbuf->f_bsize; |
318 | __put_user(kbuf->f_blocks, &ubuf->f_blocks) || | 320 | buf.f_blocks = kbuf->f_blocks; |
319 | __put_user(kbuf->f_bfree, &ubuf->f_bfree) || | 321 | buf.f_bfree = kbuf->f_bfree; |
320 | __put_user(kbuf->f_bavail, &ubuf->f_bavail) || | 322 | buf.f_bavail = kbuf->f_bavail; |
321 | __put_user(kbuf->f_files, &ubuf->f_files) || | 323 | buf.f_files = kbuf->f_files; |
322 | __put_user(kbuf->f_ffree, &ubuf->f_ffree) || | 324 | buf.f_ffree = kbuf->f_ffree; |
323 | __put_user(kbuf->f_namelen, &ubuf->f_namelen) || | 325 | buf.f_namelen = kbuf->f_namelen; |
324 | __put_user(kbuf->f_fsid.val[0], &ubuf->f_fsid.val[0]) || | 326 | buf.f_fsid.val[0] = kbuf->f_fsid.val[0]; |
325 | __put_user(kbuf->f_fsid.val[1], &ubuf->f_fsid.val[1]) || | 327 | buf.f_fsid.val[1] = kbuf->f_fsid.val[1]; |
326 | __put_user(kbuf->f_frsize, &ubuf->f_frsize) || | 328 | buf.f_frsize = kbuf->f_frsize; |
327 | __put_user(kbuf->f_flags, &ubuf->f_flags) || | 329 | buf.f_flags = kbuf->f_flags; |
328 | __clear_user(ubuf->f_spare, sizeof(ubuf->f_spare))) | 330 | if (copy_to_user(ubuf, &buf, sizeof(struct compat_statfs64))) |
329 | return -EFAULT; | 331 | return -EFAULT; |
330 | return 0; | 332 | return 0; |
331 | } | 333 | } |
diff --git a/include/linux/fs.h b/include/linux/fs.h index 771fe1131467..9a540d399d1b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -1047,14 +1047,14 @@ static inline struct inode *locks_inode(const struct file *f) | |||
1047 | } | 1047 | } |
1048 | 1048 | ||
1049 | #ifdef CONFIG_FILE_LOCKING | 1049 | #ifdef CONFIG_FILE_LOCKING |
1050 | extern int fcntl_getlk(struct file *, unsigned int, struct flock __user *); | 1050 | extern int fcntl_getlk(struct file *, unsigned int, struct flock *); |
1051 | extern int fcntl_setlk(unsigned int, struct file *, unsigned int, | 1051 | extern int fcntl_setlk(unsigned int, struct file *, unsigned int, |
1052 | struct flock __user *); | 1052 | struct flock *); |
1053 | 1053 | ||
1054 | #if BITS_PER_LONG == 32 | 1054 | #if BITS_PER_LONG == 32 |
1055 | extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 __user *); | 1055 | extern int fcntl_getlk64(struct file *, unsigned int, struct flock64 *); |
1056 | extern int fcntl_setlk64(unsigned int, struct file *, unsigned int, | 1056 | extern int fcntl_setlk64(unsigned int, struct file *, unsigned int, |
1057 | struct flock64 __user *); | 1057 | struct flock64 *); |
1058 | #endif | 1058 | #endif |
1059 | 1059 | ||
1060 | extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); | 1060 | extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); |
@@ -1258,7 +1258,7 @@ extern void fasync_free(struct fasync_struct *); | |||
1258 | extern void kill_fasync(struct fasync_struct **, int, int); | 1258 | extern void kill_fasync(struct fasync_struct **, int, int); |
1259 | 1259 | ||
1260 | extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); | 1260 | extern void __f_setown(struct file *filp, struct pid *, enum pid_type, int force); |
1261 | extern void f_setown(struct file *filp, unsigned long arg, int force); | 1261 | extern int f_setown(struct file *filp, unsigned long arg, int force); |
1262 | extern void f_delown(struct file *filp); | 1262 | extern void f_delown(struct file *filp); |
1263 | extern pid_t f_getown(struct file *filp); | 1263 | extern pid_t f_getown(struct file *filp); |
1264 | extern int send_sigurg(struct fown_struct *fown); | 1264 | extern int send_sigurg(struct fown_struct *fown); |
diff --git a/net/socket.c b/net/socket.c index 8f9dab330d57..59e902b9df09 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -991,8 +991,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
991 | err = -EFAULT; | 991 | err = -EFAULT; |
992 | if (get_user(pid, (int __user *)argp)) | 992 | if (get_user(pid, (int __user *)argp)) |
993 | break; | 993 | break; |
994 | f_setown(sock->file, pid, 1); | 994 | err = f_setown(sock->file, pid, 1); |
995 | err = 0; | ||
996 | break; | 995 | break; |
997 | case FIOGETOWN: | 996 | case FIOGETOWN: |
998 | case SIOCGPGRP: | 997 | case SIOCGPGRP: |