diff options
author | Miklos Szeredi <mszeredi@suse.cz> | 2010-11-30 10:39:27 -0500 |
---|---|---|
committer | Miklos Szeredi <mszeredi@suse.cz> | 2010-11-30 10:39:27 -0500 |
commit | 7572777eef78ebdee1ecb7c258c0ef94d35bad16 (patch) | |
tree | 04bb06d75688912ac14855146dc013703529403d /fs/fuse/file.c | |
parent | d9d318d39dd5cb686660504a3565aac453709ccc (diff) |
fuse: verify ioctl retries
Verify that the total length of the iovec returned in FUSE_IOCTL_RETRY
doesn't overflow iov_length().
Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
CC: Tejun Heo <tj@kernel.org>
CC: <stable@kernel.org> [2.6.31+]
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r-- | fs/fuse/file.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 0e2e25b114a6..8b984a2cebbd 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -1666,6 +1666,20 @@ static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src, | |||
1666 | return 0; | 1666 | return 0; |
1667 | } | 1667 | } |
1668 | 1668 | ||
1669 | /* Make sure iov_length() won't overflow */ | ||
1670 | static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count) | ||
1671 | { | ||
1672 | size_t n; | ||
1673 | u32 max = FUSE_MAX_PAGES_PER_REQ << PAGE_SHIFT; | ||
1674 | |||
1675 | for (n = 0; n < count; n++) { | ||
1676 | if (iov->iov_len > (size_t) max) | ||
1677 | return -ENOMEM; | ||
1678 | max -= iov->iov_len; | ||
1679 | } | ||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1669 | /* | 1683 | /* |
1670 | * For ioctls, there is no generic way to determine how much memory | 1684 | * For ioctls, there is no generic way to determine how much memory |
1671 | * needs to be read and/or written. Furthermore, ioctls are allowed | 1685 | * needs to be read and/or written. Furthermore, ioctls are allowed |
@@ -1858,6 +1872,14 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, | |||
1858 | in_iov = page_address(iov_page); | 1872 | in_iov = page_address(iov_page); |
1859 | out_iov = in_iov + in_iovs; | 1873 | out_iov = in_iov + in_iovs; |
1860 | 1874 | ||
1875 | err = fuse_verify_ioctl_iov(in_iov, in_iovs); | ||
1876 | if (err) | ||
1877 | goto out; | ||
1878 | |||
1879 | err = fuse_verify_ioctl_iov(out_iov, out_iovs); | ||
1880 | if (err) | ||
1881 | goto out; | ||
1882 | |||
1861 | goto retry; | 1883 | goto retry; |
1862 | } | 1884 | } |
1863 | 1885 | ||