Skip to content

Commit c56fe33

Browse files
committed
Merge: iov_iter: fix ubuf iter
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6763 Hello JIRA: https://issues.redhat.com/browse/RHEL-87739 So far, we just run one partial backport on the following upstream PR to rhel9, and cause bug in code which depends on ITER_UBUF. https://lore.kernel.org/all/f16053ea-d3b8-a8a2-0178-3981fea5a656@kernel.dk/ This MR pulls the other 4 missed patches to rhel9. Signed-off-by: Ming Lei <ming.lei@redhat.com> Approved-by: Jeff Moyer <jmoyer@redhat.com> Approved-by: Ewan D. Milne <emilne@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Approved-by: Rafael Aquini <raquini@redhat.com> Merged-by: Augusto Caringi <acaringi@redhat.com>
2 parents c1ac588 + 1354d7a commit c56fe33

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

include/linux/uio.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,8 @@ static inline void iov_iter_ubuf(struct iov_iter *i, unsigned int direction,
396396
.user_backed = true,
397397
.data_source = direction,
398398
.ubuf = buf,
399-
.count = count
399+
.count = count,
400+
.nr_segs = 1
400401
};
401402
}
402403
/* Flags for iov_iter_get/extract_pages*() */

lib/iov_iter.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1747,7 +1747,7 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags)
17471747
}
17481748
EXPORT_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+
18321857
ssize_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
}
19231949
EXPORT_SYMBOL(import_single_range);

0 commit comments

Comments
 (0)