* [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow
@ 2026-04-03 21:28 Aditya Rajan
2026-04-04 13:15 ` Gary Guo
2026-04-05 9:51 ` kernel test robot
0 siblings, 2 replies; 7+ messages in thread
From: Aditya Rajan @ 2026-04-03 21:28 UTC (permalink / raw)
To: dakr, ojeda
Cc: abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun,
gary, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core,
rust-for-linux, linux-kernel, Aditya Rajan
In alloc_slice_with_attrs(), the checked_mul() guards against
arithmetic overflow when computing the total byte size
(size_of::<T>() * len). If this overflows, the current code returns
ENOMEM, which is misleading -- the system is not out of memory, the
requested size simply cannot be represented in a usize.
Return EOVERFLOW instead, which accurately describes the failure. This
also distinguishes it from the actual allocation failure two lines
below, which correctly returns ENOMEM when dma_alloc_attrs() yields a
null pointer.
Fixes: d9aee73c56ee ("rust: dma: add generalized container for types other than slices")
Link: https://lore.kernel.org/all/20260320194626.36263-3-dakr@kernel.org/
Signed-off-by: Aditya Rajan <adi.dev.github@gmail.com>
---
rust/kernel/dma.rs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 4995ee5dc689..179bc8832947 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -832,7 +832,7 @@ fn alloc_slice_with_attrs(
Err(EINVAL)?;
}
- let size = core::mem::size_of::<T>().checked_mul(len).ok_or(ENOMEM)?;
+ let size = core::mem::size_of::<T>().checked_mul(len).ok_or(EOVERFLOW)?;
let mut dma_handle = 0;
// SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`.
let addr = unsafe {
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread* Re: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow 2026-04-03 21:28 [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow Aditya Rajan @ 2026-04-04 13:15 ` Gary Guo 2026-04-04 17:24 ` Aditya Rajan 2026-04-05 9:51 ` kernel test robot 1 sibling, 1 reply; 7+ messages in thread From: Gary Guo @ 2026-04-04 13:15 UTC (permalink / raw) To: Aditya Rajan, dakr, ojeda Cc: abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun, gary, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core, rust-for-linux, linux-kernel On Fri Apr 3, 2026 at 10:28 PM BST, Aditya Rajan wrote: > In alloc_slice_with_attrs(), the checked_mul() guards against > arithmetic overflow when computing the total byte size > (size_of::<T>() * len). If this overflows, the current code returns > ENOMEM, which is misleading -- the system is not out of memory, the > requested size simply cannot be represented in a usize. > > Return EOVERFLOW instead, which accurately describes the failure. This > also distinguishes it from the actual allocation failure two lines > below, which correctly returns ENOMEM when dma_alloc_attrs() yields a > null pointer. > > Fixes: d9aee73c56ee ("rust: dma: add generalized container for types other than slices") > Link: https://lore.kernel.org/all/20260320194626.36263-3-dakr@kernel.org/ > > Signed-off-by: Aditya Rajan <adi.dev.github@gmail.com> > --- > rust/kernel/dma.rs | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs > index 4995ee5dc689..179bc8832947 100644 > --- a/rust/kernel/dma.rs > +++ b/rust/kernel/dma.rs > @@ -832,7 +832,7 @@ fn alloc_slice_with_attrs( > Err(EINVAL)?; > } > > - let size = core::mem::size_of::<T>().checked_mul(len).ok_or(ENOMEM)?; > + let size = core::mem::size_of::<T>().checked_mul(len).ok_or(EOVERFLOW)?; > let mut dma_handle = 0; > // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. > let addr = unsafe { Hi Aditya, Thanks for the patch, but the behaviour here is intended. Neither our `KVec` implementation nor upstream Rust distinguishes between allocation error caused by array size exceeding address space or running out of memory to allocate (`AllocError` is returned and it converts to ENOMEM). `kmalloc_array` also just returns `NULL` when overflows, so arguably this behaviour also aligns us with C side. Abstractly, the system is indeed running out memory because it cannot allocate something larger than its address space. Best, Gary ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow 2026-04-04 13:15 ` Gary Guo @ 2026-04-04 17:24 ` Aditya Rajan 2026-04-04 19:43 ` Danilo Krummrich 2026-04-04 20:13 ` Gary Guo 0 siblings, 2 replies; 7+ messages in thread From: Aditya Rajan @ 2026-04-04 17:24 UTC (permalink / raw) To: Gary Guo, Aditya Rajan, dakr, ojeda Cc: abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core, rust-for-linux, linux-kernel On Sat Apr 4, 2026 at 6:15 AM PDT, Gary Guo wrote: > Thanks for the patch, but the behaviour here is intended. > > Neither our `KVec` implementation nor upstream Rust distinguishes between > allocation error caused by array size exceeding address space or running out of > memory to allocate (`AllocError` is returned and it converts to ENOMEM). > > `kmalloc_array` also just returns `NULL` when overflows, so arguably this > behaviour also aligns us with C side. > > Abstractly, the system is indeed running out memory because it cannot allocate > something larger than its address space. Hi Gary, Thanks for the reply, I saw at some similar places where EOVERFLOW is used, that is why i thought we should change this error code: * In nouveau_drv.h, `u_memcpya()` does `check_mul_overflow(nmemb, size, &bytes)` and returns ERR_PTR(-EOVERFLOW), it is kind of same multiplication overflow on `nmemb*size` before an allocation. Similarly `mm/mmap.c` returns EOVERFLOW for arithmetic overflow in offset calculations, it also has a comment `/* offset overflow? */`. * Also I saw existing Rust kernel code already follows similar convention, see `rust/kernel/uaccess.rs` it uses `offset.checked_add(count).ok_or(EOVERFLOW)?` for the same kind of arithmetic overflow check. * For `kmalloc_array` i think it conflates overflow with OOM because its return type (pointer) can't express distinct errors, maybe it should be improved as well ?. When the API can distinguish (like here, or in nouveau), the kernel does use (or maybe should use?) `EOVERFLOW`. IMO two failures have different semantics for callers, ENOMEM is transient (retry may succeed under less memory pressure), EOVERFLOW is deterministic (the input will never work). Using ENOMEM for overflow could mislead a caller into retrying a request that can never succeed. Thanks, Aditya ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow 2026-04-04 17:24 ` Aditya Rajan @ 2026-04-04 19:43 ` Danilo Krummrich 2026-04-04 20:13 ` Gary Guo 1 sibling, 0 replies; 7+ messages in thread From: Danilo Krummrich @ 2026-04-04 19:43 UTC (permalink / raw) To: Aditya Rajan Cc: Gary Guo, ojeda, abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core, rust-for-linux, linux-kernel On Sat Apr 4, 2026 at 7:24 PM CEST, Aditya Rajan wrote: > On Sat Apr 4, 2026 at 6:15 AM PDT, Gary Guo wrote: > >> Thanks for the patch, but the behaviour here is intended. >> >> Neither our `KVec` implementation nor upstream Rust distinguishes between >> allocation error caused by array size exceeding address space or running out of >> memory to allocate (`AllocError` is returned and it converts to ENOMEM). >> >> `kmalloc_array` also just returns `NULL` when overflows, so arguably this >> behaviour also aligns us with C side. >> >> Abstractly, the system is indeed running out memory because it cannot allocate >> something larger than its address space. > > Thanks for the reply, I saw at some similar places where EOVERFLOW is used, > that is why i thought we should change this error code: > > * In nouveau_drv.h, `u_memcpya()` does `check_mul_overflow(nmemb, size, > &bytes)` and returns ERR_PTR(-EOVERFLOW), it is kind of same multiplication > overflow on `nmemb*size` before an allocation. Similarly `mm/mmap.c` returns > EOVERFLOW for arithmetic overflow in offset calculations, it also has a > comment `/* offset overflow? */`. > > * Also I saw existing Rust kernel code already follows similar convention, see > `rust/kernel/uaccess.rs` it uses `offset.checked_add(count).ok_or(EOVERFLOW)?` > for the same kind of arithmetic overflow check. > > * For `kmalloc_array` i think it conflates overflow with OOM because its > return type (pointer) can't express distinct errors, maybe it should be > improved as well ?. When the API can distinguish (like here, or in nouveau), > the kernel does use (or maybe should use?) `EOVERFLOW`. You mentioned u_memcpya() from nouveau, which follows memdup_array_user() and vmemdup_array_user(); and I think there are even more such examples that use -EOVERFLOW besides those and the also mentioned uaccess code. That said, they all have on common that they are semantically different compared to a raw memory allocation, as they also access existing buffers the user wants those functions to copy from. Thus, a multiplication overflow also implies a potential out of bounds access of the given buffer. So, it makes sense to distinguish between -EOVERFLOW and -ENOMEM in those cases. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow 2026-04-04 17:24 ` Aditya Rajan 2026-04-04 19:43 ` Danilo Krummrich @ 2026-04-04 20:13 ` Gary Guo 2026-04-04 20:28 ` Danilo Krummrich 1 sibling, 1 reply; 7+ messages in thread From: Gary Guo @ 2026-04-04 20:13 UTC (permalink / raw) To: Aditya Rajan, Gary Guo, dakr, ojeda Cc: abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core, rust-for-linux, linux-kernel On Sat Apr 4, 2026 at 6:24 PM BST, Aditya Rajan wrote: > On Sat Apr 4, 2026 at 6:15 AM PDT, Gary Guo wrote: > >> Thanks for the patch, but the behaviour here is intended. >> >> Neither our `KVec` implementation nor upstream Rust distinguishes between >> allocation error caused by array size exceeding address space or running out of >> memory to allocate (`AllocError` is returned and it converts to ENOMEM). >> >> `kmalloc_array` also just returns `NULL` when overflows, so arguably this >> behaviour also aligns us with C side. >> >> Abstractly, the system is indeed running out memory because it cannot allocate >> something larger than its address space. > > Hi Gary, > > Thanks for the reply, I saw at some similar places where EOVERFLOW is used, > that is why i thought we should change this error code: > > * In nouveau_drv.h, `u_memcpya()` does `check_mul_overflow(nmemb, size, > &bytes)` and returns ERR_PTR(-EOVERFLOW), it is kind of same multiplication > overflow on `nmemb*size` before an allocation. Similarly `mm/mmap.c` returns > EOVERFLOW for arithmetic overflow in offset calculations, it also has a > comment `/* offset overflow? */`. I think these cases are all related to values ultimately controlled by userspace, and the error conditions are propagated back to userspace, so it makes more sense to distinguish errors. On the other hand, for KVec/Coherent cases, it is less useful to distinguish between the cases. If we want to add EOVERFLOW, then we'd need to extend AllocError to have two enums, which I wouldn't be against, but I think it's not worth having. (I wanted Coherent to use AllocError as error too, but as it does not support zero-size allocation, so I didn't change the error type. I guess one option is to handle zero-size case by using a dangling pointer similar to `KVec`.) > > * Also I saw existing Rust kernel code already follows similar convention, see > `rust/kernel/uaccess.rs` it uses `offset.checked_add(count).ok_or(EOVERFLOW)?` > for the same kind of arithmetic overflow check. > > * For `kmalloc_array` i think it conflates overflow with OOM because its > return type (pointer) can't express distinct errors, maybe it should be > improved as well ?. When the API can distinguish (like here, or in nouveau), > the kernel does use (or maybe should use?) `EOVERFLOW`. > > IMO two failures have different semantics for callers, ENOMEM is transient > (retry may succeed under less memory pressure), EOVERFLOW is deterministic > (the input will never work). Using ENOMEM for overflow could mislead a caller > into retrying a request that can never succeed. If I allocate `usize::MAX`, it'll never work but the error would still be ENOMEM, and I see no reason to differentiate `usize::MAX` and `usize::MAX + 1`. Best, Gary ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow 2026-04-04 20:13 ` Gary Guo @ 2026-04-04 20:28 ` Danilo Krummrich 0 siblings, 0 replies; 7+ messages in thread From: Danilo Krummrich @ 2026-04-04 20:28 UTC (permalink / raw) To: Gary Guo Cc: Aditya Rajan, ojeda, abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core, rust-for-linux, linux-kernel On Sat Apr 4, 2026 at 10:13 PM CEST, Gary Guo wrote: > On Sat Apr 4, 2026 at 6:24 PM BST, Aditya Rajan wrote: >> On Sat Apr 4, 2026 at 6:15 AM PDT, Gary Guo wrote: >> >>> Thanks for the patch, but the behaviour here is intended. >>> >>> Neither our `KVec` implementation nor upstream Rust distinguishes between >>> allocation error caused by array size exceeding address space or running out of >>> memory to allocate (`AllocError` is returned and it converts to ENOMEM). >>> >>> `kmalloc_array` also just returns `NULL` when overflows, so arguably this >>> behaviour also aligns us with C side. >>> >>> Abstractly, the system is indeed running out memory because it cannot allocate >>> something larger than its address space. >> >> Hi Gary, >> >> Thanks for the reply, I saw at some similar places where EOVERFLOW is used, >> that is why i thought we should change this error code: >> >> * In nouveau_drv.h, `u_memcpya()` does `check_mul_overflow(nmemb, size, >> &bytes)` and returns ERR_PTR(-EOVERFLOW), it is kind of same multiplication >> overflow on `nmemb*size` before an allocation. Similarly `mm/mmap.c` returns >> EOVERFLOW for arithmetic overflow in offset calculations, it also has a >> comment `/* offset overflow? */`. > > I think these cases are all related to values ultimately controlled by > userspace, and the error conditions are propagated back to userspace, so it > makes more sense to distinguish errors. That's not the main difference, any of those primitives may be called on behalf of userspace with the error propagated back to userspace. Please also see my considerations in [1]. [1] https://lore.kernel.org/lkml/DHKMLRW67JB9.2VGA6EGTLYSCU@kernel.org/ > On the other hand, for KVec/Coherent cases, it is less useful to distinguish > between the cases. If we want to add EOVERFLOW, then we'd need to extend > AllocError to have two enums, which I wouldn't be against, but I think it's not > worth having. I'd rather not, let's keep it consistent with other memory allocation primitives. > (I wanted Coherent to use AllocError as error too, but as it does not support > zero-size allocation, so I didn't change the error type. I guess one option is > to handle zero-size case by using a dangling pointer similar to `KVec`.) I'm against this, a zero-sized dma::Coherent allocation does not make sense; I'd really want to see a real use-case for this. >> * Also I saw existing Rust kernel code already follows similar convention, see >> `rust/kernel/uaccess.rs` it uses `offset.checked_add(count).ok_or(EOVERFLOW)?` >> for the same kind of arithmetic overflow check. >> >> * For `kmalloc_array` i think it conflates overflow with OOM because its >> return type (pointer) can't express distinct errors, maybe it should be >> improved as well ?. When the API can distinguish (like here, or in nouveau), >> the kernel does use (or maybe should use?) `EOVERFLOW`. >> >> IMO two failures have different semantics for callers, ENOMEM is transient >> (retry may succeed under less memory pressure), EOVERFLOW is deterministic >> (the input will never work). Using ENOMEM for overflow could mislead a caller >> into retrying a request that can never succeed. > > If I allocate `usize::MAX`, it'll never work but the error would still be > ENOMEM, and I see no reason to differentiate `usize::MAX` and `usize::MAX + 1`. Agreed. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow 2026-04-03 21:28 [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow Aditya Rajan 2026-04-04 13:15 ` Gary Guo @ 2026-04-05 9:51 ` kernel test robot 1 sibling, 0 replies; 7+ messages in thread From: kernel test robot @ 2026-04-05 9:51 UTC (permalink / raw) To: Aditya Rajan, dakr, ojeda Cc: oe-kbuild-all, abdiel.janulgue, daniel.almeida, robin.murphy, a.hindborg, boqun, gary, bjorn3_gh, lossin, aliceryhl, tmgross, driver-core, rust-for-linux, linux-kernel, Aditya Rajan Hi Aditya, kernel test robot noticed the following build errors: [auto build test ERROR on linux-next/master] [cannot apply to linus/master v7.0-rc6] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Aditya-Rajan/rust-dma-return-EOVERFLOW-instead-of-ENOMEM-on-size-overflow/20260405-094049 base: linux-next/master patch link: https://lore.kernel.org/r/20260403212822.294288-1-adi.dev.github%40gmail.com patch subject: [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow config: x86_64-rhel-9.4-rust (https://download.01.org/0day-ci/archive/20260405/202604051110.OC0tBUnh-lkp@intel.com/config) compiler: clang version 20.1.8 (https://github.com/llvm/llvm-project 87f0227cb60147a26a1eeb4fb06e3b505e9c7261) rustc: rustc 1.88.0 (6b00bc388 2025-06-23) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260405/202604051110.OC0tBUnh-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202604051110.OC0tBUnh-lkp@intel.com/ All errors (new ones prefixed by >>): PATH=/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin INFO PATH=/opt/cross/rustc-1.88.0-bindgen-0.72.1/cargo/bin:/opt/cross/clang-20/bin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin /usr/bin/timeout -k 100 12h /usr/bin/make KCFLAGS=\ -fno-crash-diagnostics\ -Wno-error=return-type\ -Wreturn-type\ -funsigned-char\ -Wundef\ -falign-functions=64 W=1 --keep-going LLVM=1 -j32 -C source O=/kbuild/obj/consumer/x86_64-rhel-9.4-rust ARCH=x86_64 SHELL=/bin/bash rustfmtcheck make: Entering directory '/kbuild/src/consumer' make[1]: Entering directory '/kbuild/obj/consumer/x86_64-rhel-9.4-rust' >> Diff in rust/kernel/dma.rs:832: Err(EINVAL)?; } - let size = core::mem::size_of::<T>().checked_mul(len).ok_or(EOVERFLOW)?; + let size = core::mem::size_of::<T>() + .checked_mul(len) + .ok_or(EOVERFLOW)?; let mut dma_handle = 0; // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. let addr = unsafe { >> Diff in rust/kernel/dma.rs:832: Err(EINVAL)?; } - let size = core::mem::size_of::<T>().checked_mul(len).ok_or(EOVERFLOW)?; + let size = core::mem::size_of::<T>() + .checked_mul(len) + .ok_or(EOVERFLOW)?; let mut dma_handle = 0; // SAFETY: Device pointer is guaranteed as valid by the type invariant on `Device`. let addr = unsafe { make[2]: *** [Makefile:1932: rustfmt] Error 123 make[2]: Target 'rustfmtcheck' not remade because of errors. make[1]: Leaving directory '/kbuild/obj/consumer/x86_64-rhel-9.4-rust' make[1]: *** [Makefile:248: __sub-make] Error 2 make: *** [Makefile:248: __sub-make] Error 2 make[1]: Target 'rustfmtcheck' not remade because of errors. make: Target 'rustfmtcheck' not remade because of errors. make: Leaving directory '/kbuild/src/consumer' -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-04-05 9:52 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-04-03 21:28 [PATCH] rust: dma: return EOVERFLOW instead of ENOMEM on size overflow Aditya Rajan 2026-04-04 13:15 ` Gary Guo 2026-04-04 17:24 ` Aditya Rajan 2026-04-04 19:43 ` Danilo Krummrich 2026-04-04 20:13 ` Gary Guo 2026-04-04 20:28 ` Danilo Krummrich 2026-04-05 9:51 ` kernel test robot
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox