aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/fuse/file.c')
-rw-r--r--fs/fuse/file.c66
1 files changed, 54 insertions, 12 deletions
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 8b984a2cebbd..95da1bc1c826 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1634,9 +1634,9 @@ static int fuse_ioctl_copy_user(struct page **pages, struct iovec *iov,
1634 * and 64bit. Fortunately we can determine which structure the server 1634 * and 64bit. Fortunately we can determine which structure the server
1635 * used from the size of the reply. 1635 * used from the size of the reply.
1636 */ 1636 */
1637static int fuse_copy_ioctl_iovec(struct iovec *dst, void *src, 1637static int fuse_copy_ioctl_iovec_old(struct iovec *dst, void *src,
1638 size_t transferred, unsigned count, 1638 size_t transferred, unsigned count,
1639 bool is_compat) 1639 bool is_compat)
1640{ 1640{
1641#ifdef CONFIG_COMPAT 1641#ifdef CONFIG_COMPAT
1642 if (count * sizeof(struct compat_iovec) == transferred) { 1642 if (count * sizeof(struct compat_iovec) == transferred) {
@@ -1680,6 +1680,42 @@ static int fuse_verify_ioctl_iov(struct iovec *iov, size_t count)
1680 return 0; 1680 return 0;
1681} 1681}
1682 1682
1683static int fuse_copy_ioctl_iovec(struct fuse_conn *fc, struct iovec *dst,
1684 void *src, size_t transferred, unsigned count,
1685 bool is_compat)
1686{
1687 unsigned i;
1688 struct fuse_ioctl_iovec *fiov = src;
1689
1690 if (fc->minor < 16) {
1691 return fuse_copy_ioctl_iovec_old(dst, src, transferred,
1692 count, is_compat);
1693 }
1694
1695 if (count * sizeof(struct fuse_ioctl_iovec) != transferred)
1696 return -EIO;
1697
1698 for (i = 0; i < count; i++) {
1699 /* Did the server supply an inappropriate value? */
1700 if (fiov[i].base != (unsigned long) fiov[i].base ||
1701 fiov[i].len != (unsigned long) fiov[i].len)
1702 return -EIO;
1703
1704 dst[i].iov_base = (void __user *) (unsigned long) fiov[i].base;
1705 dst[i].iov_len = (size_t) fiov[i].len;
1706
1707#ifdef CONFIG_COMPAT
1708 if (is_compat &&
1709 (ptr_to_compat(dst[i].iov_base) != fiov[i].base ||
1710 (compat_size_t) dst[i].iov_len != fiov[i].len))
1711 return -EIO;
1712#endif
1713 }
1714
1715 return 0;
1716}
1717
1718
1683/* 1719/*
1684 * For ioctls, there is no generic way to determine how much memory 1720 * For ioctls, there is no generic way to determine how much memory
1685 * needs to be read and/or written. Furthermore, ioctls are allowed 1721 * needs to be read and/or written. Furthermore, ioctls are allowed
@@ -1740,18 +1776,25 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1740 struct fuse_ioctl_out outarg; 1776 struct fuse_ioctl_out outarg;
1741 struct fuse_req *req = NULL; 1777 struct fuse_req *req = NULL;
1742 struct page **pages = NULL; 1778 struct page **pages = NULL;
1743 struct page *iov_page = NULL; 1779 struct iovec *iov_page = NULL;
1744 struct iovec *in_iov = NULL, *out_iov = NULL; 1780 struct iovec *in_iov = NULL, *out_iov = NULL;
1745 unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages; 1781 unsigned int in_iovs = 0, out_iovs = 0, num_pages = 0, max_pages;
1746 size_t in_size, out_size, transferred; 1782 size_t in_size, out_size, transferred;
1747 int err; 1783 int err;
1748 1784
1785#if BITS_PER_LONG == 32
1786 inarg.flags |= FUSE_IOCTL_32BIT;
1787#else
1788 if (flags & FUSE_IOCTL_COMPAT)
1789 inarg.flags |= FUSE_IOCTL_32BIT;
1790#endif
1791
1749 /* assume all the iovs returned by client always fits in a page */ 1792 /* assume all the iovs returned by client always fits in a page */
1750 BUILD_BUG_ON(sizeof(struct iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); 1793 BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE);
1751 1794
1752 err = -ENOMEM; 1795 err = -ENOMEM;
1753 pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL); 1796 pages = kzalloc(sizeof(pages[0]) * FUSE_MAX_PAGES_PER_REQ, GFP_KERNEL);
1754 iov_page = alloc_page(GFP_KERNEL); 1797 iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
1755 if (!pages || !iov_page) 1798 if (!pages || !iov_page)
1756 goto out; 1799 goto out;
1757 1800
@@ -1760,7 +1803,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1760 * RETRY from server is not allowed. 1803 * RETRY from server is not allowed.
1761 */ 1804 */
1762 if (!(flags & FUSE_IOCTL_UNRESTRICTED)) { 1805 if (!(flags & FUSE_IOCTL_UNRESTRICTED)) {
1763 struct iovec *iov = page_address(iov_page); 1806 struct iovec *iov = iov_page;
1764 1807
1765 iov->iov_base = (void __user *)arg; 1808 iov->iov_base = (void __user *)arg;
1766 iov->iov_len = _IOC_SIZE(cmd); 1809 iov->iov_len = _IOC_SIZE(cmd);
@@ -1841,7 +1884,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1841 1884
1842 /* did it ask for retry? */ 1885 /* did it ask for retry? */
1843 if (outarg.flags & FUSE_IOCTL_RETRY) { 1886 if (outarg.flags & FUSE_IOCTL_RETRY) {
1844 char *vaddr; 1887 void *vaddr;
1845 1888
1846 /* no retry if in restricted mode */ 1889 /* no retry if in restricted mode */
1847 err = -EIO; 1890 err = -EIO;
@@ -1862,14 +1905,14 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1862 goto out; 1905 goto out;
1863 1906
1864 vaddr = kmap_atomic(pages[0], KM_USER0); 1907 vaddr = kmap_atomic(pages[0], KM_USER0);
1865 err = fuse_copy_ioctl_iovec(page_address(iov_page), vaddr, 1908 err = fuse_copy_ioctl_iovec(fc, iov_page, vaddr,
1866 transferred, in_iovs + out_iovs, 1909 transferred, in_iovs + out_iovs,
1867 (flags & FUSE_IOCTL_COMPAT) != 0); 1910 (flags & FUSE_IOCTL_COMPAT) != 0);
1868 kunmap_atomic(vaddr, KM_USER0); 1911 kunmap_atomic(vaddr, KM_USER0);
1869 if (err) 1912 if (err)
1870 goto out; 1913 goto out;
1871 1914
1872 in_iov = page_address(iov_page); 1915 in_iov = iov_page;
1873 out_iov = in_iov + in_iovs; 1916 out_iov = in_iov + in_iovs;
1874 1917
1875 err = fuse_verify_ioctl_iov(in_iov, in_iovs); 1918 err = fuse_verify_ioctl_iov(in_iov, in_iovs);
@@ -1891,8 +1934,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
1891 out: 1934 out:
1892 if (req) 1935 if (req)
1893 fuse_put_request(fc, req); 1936 fuse_put_request(fc, req);
1894 if (iov_page) 1937 free_page((unsigned long) iov_page);
1895 __free_page(iov_page);
1896 while (num_pages) 1938 while (num_pages)
1897 __free_page(pages[--num_pages]); 1939 __free_page(pages[--num_pages]);
1898 kfree(pages); 1940 kfree(pages);