diff options
| author | Wang Haoran <haoranwangsec@gmail.com> | 2026-04-13 14:06:55 +0800 |
|---|---|---|
| committer | Christian Brauner <brauner@kernel.org> | 2026-05-21 09:32:47 +0200 |
| commit | 30beced6ec4931db201b77493d41d0df7d7eb5aa (patch) | |
| tree | ce87c1ddf8704cdfb2655172d157dab430195f37 | |
| parent | 1ca179a8538467ef770bfe68a184f6c74c657fef (diff) | |
iov_iter: use kmemdup_array for dup_iter to harden against overflow
While auditing the Linux 7.0-rc2 kernel, I identified a potential security
vulnerability in the iov_iter framework's memory allocation logic.
The dup_iter() function, which is exported via EXPORT_SYMBOL, currently
uses kmemdup() with a raw multiplication to allocate the duplicate iovec array:
new->iov = kmemdup(from->iov, nr_segs * sizeof(struct iovec), gfp);
The hazard here is that dup_iter() relies on a primitive multiplication without
any integrated overflow check. Since nr_segs is often derived from user-space
input, this line is vulnerable to integer overflow (on 32-bit systems or
via type narrowing), potentially leading to a small allocation followed by a
large out-of-bounds memory copy. Furthermore, it allows for unbounded memory
allocations, as the function lacks intrinsic knowledge of safe limits.
On the 7.0-rc2 branch, several high-impact callchains still rely on this
exported function:
drivers/usb/gadget/function/f_fs.c:
The ffs_epfile_read_iter() path demonstrates why relying on dup_iter() is
dangerous: it performs allocation based on user input before verifying driver
state. This confirms that dup_iter() must be hardened internally as it cannot
assume pre-validated input.
drivers/usb/gadget/legacy/inode.c:
The ep_read_iter() path illustrates how dup_iter()’s lack of boundary awareness
compounds resource risks. When combined with other allocations, it creates
a multiplier effect for kernel memory pressure.
This patch replaces kmemdup() with kmemdup_array(), which utilizes
check_mul_overflow() to ensure the allocation size is calculated safely,
hardening dup_iter() against malicious or malformed inputs from its callers
Signed-off-by: Wang Haoran <haoranwangsec@gmail.com>
Link: https://patch.msgid.link/20260413060655.1139141-1-haoranwangsec@gmail.com
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
| -rw-r--r-- | lib/iov_iter.c | 8 |
1 files changed, 4 insertions, 4 deletions
diff --git a/lib/iov_iter.c b/lib/iov_iter.c index 243662af1af7..273919b16161 100644 --- a/lib/iov_iter.c +++ b/lib/iov_iter.c @@ -1224,13 +1224,13 @@ const void *dup_iter(struct iov_iter *new, struct iov_iter *old, gfp_t flags) { *new = *old; if (iov_iter_is_bvec(new)) - return new->bvec = kmemdup(new->bvec, - new->nr_segs * sizeof(struct bio_vec), + return new->bvec = kmemdup_array(new->bvec, + new->nr_segs, sizeof(struct bio_vec), flags); else if (iov_iter_is_kvec(new) || iter_is_iovec(new)) /* iovec and kvec have identical layout */ - return new->__iov = kmemdup(new->__iov, - new->nr_segs * sizeof(struct iovec), + return new->__iov = kmemdup_array(new->__iov, + new->nr_segs, sizeof(struct iovec), flags); return NULL; } |
