@@ -1747,7 +1747,7 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
17471747}
17481748EXPORT_SYMBOL (dup_iter );
17491749
1750- static int copy_compat_iovec_from_user (struct iovec * iov ,
1750+ static __noclone int copy_compat_iovec_from_user (struct iovec * iov ,
17511751 const struct iovec __user * uvec , unsigned long nr_segs )
17521752{
17531753 const struct compat_iovec __user * uiov =
@@ -1779,7 +1779,7 @@ static int copy_compat_iovec_from_user(struct iovec *iov,
17791779 return ret ;
17801780}
17811781
1782- static int copy_iovec_from_user (struct iovec * iov ,
1782+ static __noclone int copy_iovec_from_user (struct iovec * iov ,
17831783 const struct iovec __user * uvec , unsigned long nr_segs )
17841784{
17851785 unsigned long seg ;
@@ -1829,6 +1829,31 @@ struct iovec *iovec_from_user(const struct iovec __user *uvec,
18291829 return iov ;
18301830}
18311831
1832+ /*
1833+ * Single segment iovec supplied by the user, import it as ITER_UBUF.
1834+ */
1835+ static ssize_t __import_iovec_ubuf (int type , const struct iovec __user * uvec ,
1836+ struct iovec * * iovp , struct iov_iter * i ,
1837+ bool compat )
1838+ {
1839+ struct iovec * iov = * iovp ;
1840+ ssize_t ret ;
1841+
1842+ * iovp = NULL ;
1843+
1844+ if (compat )
1845+ ret = copy_compat_iovec_from_user (iov , uvec , 1 );
1846+ else
1847+ ret = copy_iovec_from_user (iov , uvec , 1 );
1848+ if (unlikely (ret ))
1849+ return ret ;
1850+
1851+ ret = import_ubuf (type , iov -> iov_base , iov -> iov_len , i );
1852+ if (unlikely (ret ))
1853+ return ret ;
1854+ return i -> count ;
1855+ }
1856+
18321857ssize_t __import_iovec (int type , const struct iovec __user * uvec ,
18331858 unsigned nr_segs , unsigned fast_segs , struct iovec * * iovp ,
18341859 struct iov_iter * i , bool compat )
@@ -1837,6 +1862,9 @@ ssize_t __import_iovec(int type, const struct iovec __user *uvec,
18371862 unsigned long seg ;
18381863 struct iovec * iov ;
18391864
1865+ if (nr_segs == 1 )
1866+ return __import_iovec_ubuf (type , uvec , iovp , i , compat );
1867+
18401868 iov = iovec_from_user (uvec , nr_segs , fast_segs , * iovp , compat );
18411869 if (IS_ERR (iov )) {
18421870 * iovp = NULL ;
@@ -1915,9 +1943,7 @@ int import_single_range(int rw, void __user *buf, size_t len,
19151943 if (unlikely (!access_ok (buf , len )))
19161944 return - EFAULT ;
19171945
1918- iov -> iov_base = buf ;
1919- iov -> iov_len = len ;
1920- iov_iter_init (i , rw , iov , 1 , len );
1946+ iov_iter_ubuf (i , rw , buf , len );
19211947 return 0 ;
19221948}
19231949EXPORT_SYMBOL (import_single_range );
0 commit comments