[LTS 9.2] udmabuf: fix a buf size overflow issue during udmabuf creation #389
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
[LTS 9.2]
CVE-2025-37803
VULN-67673
Problem
https://nvd.nist.gov/vuln/detail/CVE-2025-37803
Background
The problem applies to the
udmabuf
module which provides a mechanism for user-space applications to allocate and manage DMA (Direct Memory Access) buffers. The module has two parameters adjustable from the user space:Their meaning:
The overflow mentioned in 021ba7f's message occurs during the conversion of
size_limit_mb
into the number of pages upon the allocation of a new DMA buffer.drivers/dma-buf/udmabuf.c
:Applicability: yes
The
udmabuf
module is enabled withy
in all configuration variants for LTS 9.2:The conversion found in
kernel-src-tree/drivers/dma-buf/udmabuf.c
Line 189 in fe9c582
u64
cast mentioned in the CVE.Solution
Mainline fix contained in 021ba7f. Applies to
ciqlts9_2
without any issues.kABI check: passed
Boot test: passed
boot-test.log
Kselftests
Module: passed
A selftest exists in LTS 9.2 testing the
udmabuf
module directly:drivers/dma-buf:udmabuf
. It was run several times on a reference and patched kernelReference
kselftest-udmabuf–ciqlts9_2–run1.log
kselftest-udmabuf–ciqlts9_2–run2.log
kselftest-udmabuf–ciqlts9_2–run3.log
kselftest-udmabuf–ciqlts9_2–run4.log
kselftest-udmabuf–ciqlts9_2–run5.log
kselftest-udmabuf–ciqlts9_2–run6.log
Patch
kselftest-udmabuf–ciqlts9_2-CVE-2025-37803–run1.log
kselftest-udmabuf–ciqlts9_2-CVE-2025-37803–run2.log
kselftest-udmabuf–ciqlts9_2-CVE-2025-37803–run3.log
kselftest-udmabuf–ciqlts9_2-CVE-2025-37803–run4.log
kselftest-udmabuf–ciqlts9_2-CVE-2025-37803–run5.log
kselftest-udmabuf–ciqlts9_2-CVE-2025-37803–run6.log
Comparison
The test passes consistently in both reference and patched kernel.
General: passed relative
Coverage
All available tests except unstable ones.
bpf
(excepttest_progs
,test_kmod.sh
,test_sockmap
,test_progs-no_alu32
,test_xsk.sh
),breakpoints
(exceptstep_after_suspend_test
),capabilities
,cgroup
(excepttest_freezer
,test_memcontrol
),clone3
,core
,cpu-hotplug
,cpufreq
,drivers/dma-buf
,drivers/net/bonding
,drivers/net/team
,filesystems/binderfs
,firmware
,fpu
,ftrace
,futex
,gpio
,intel_pstate
,ipc
,ir
,kcmp
,kexec
,kvm
,landlock
,lib
,livepatch
,membarrier
,memfd
,memory-hotplug
,mincore
,mount
,mqueue
,nci
,net/forwarding
(exceptmirror_gre_vlan_bridge_1q.sh
,tc_actions.sh
,q_in_vni.sh
,sch_tbf_root.sh
,mirror_gre_bridge_1d_vlan.sh
,dual_vxlan_bridge.sh
,sch_tbf_prio.sh
,vxlan_bridge_1d_ipv6.sh
,sch_ets.sh
,gre_inner_v6_multipath.sh
,tc_police.sh
,sch_red.sh
,sch_tbf_ets.sh
,ipip_hier_gre_keys.sh
),net/mptcp
(exceptuserspace_pm.sh
,simult_flows.sh
,mptcp_join.sh
),net
(excepttxtimestamp.sh
,xfrm_policy.sh
,udpgso_bench.sh
,udpgro_fwd.sh
,gro.sh
,reuseport_addr_any.sh
,ip_defrag.sh
,fib_nexthops.sh
,reuseaddr_conflict
),netfilter
(exceptnft_trans_stress.sh
),nsfs
,openat2
,pid_namespace
,pidfd
,proc
(exceptproc-uptime-001
,proc-pid-vm
),pstore
,ptrace
,rlimits
,rseq
,seccomp
,sgx
,sigaltstack
,size
,splice
,static_keys
,syscall_user_dispatch
,tc-testing
,tdx
,timens
,timers
(exceptraw_skew
),tmpfs
,tpm2
,vDSO
,vm
,x86
,zram
Reference
kselftests–ciqlts9_2–run1.log
Patch
kselftests–ciqlts9_2-CVE-2025-37803–run1.log
Comparison
The test results in reference and patch are the same
Commentary and the specific tests
Commentary
The bug is not a vulnerability, or at least not in the sense that's implied in the CVE, which is classified by NIST as "CWE-120 Buffer Copy without Checking Size of Input ('Classic Buffer Overflow')".
The
pglimit
variable during the calculation of which the overflow may occur is local to theudmabuf_create
function and is used in exactly two placeskernel-src-tree/drivers/dma-buf/udmabuf.c
Line 189 in fe9c582
kernel-src-tree/drivers/dma-buf/udmabuf.c
Lines 196 to 197 in fe9c582
The variable serves as a limit on the DMA buffer's number of pages, imposed by the system administrator, like
For the system with the
PAGE_SIZE
of 4096 (PAGE_SHIFT
= 12), this translates throughto
pglimit = 128 * 1024 * 1024 / 4096 = 32768
pages.The overflow in the calculation of
pglimit
is indistinguishable from the case of the administrator setting the "overflown" value directly. Assuming the module handles the limiting logic correctly the bug therefore cannot have any influence on the module's memory safety - there is no buffer overflow occuring. (If this assumption is wrong then the module has a bigger problem which the 021ba7f commit doesn't fix anyway).Moreover, the overflow, if occurs, always results in the
pglimit
value being no greater than intended. This can be proved by considering the only two possible scenarios for the overflow ofsize_limit_mb * 1024 * 1024
expression:size_limit_mb * 1024 * 1024
is0
: The "classic" overflow of a positive integerx
resulting in a truncated valuex' = x mod 2ᴺ
, further reduced by dividing byPAGE_SIZE
(forN
= number of bits in int)size_limit_mb * 1024 * 1024
is1
: the "negative" overflow, with the original positive integerx
becomingx' - 2ᴺ < 0
, wherex' = x mod 2ᴺ
. Right-shifting such value increases it, but keeps it negative, by the virtue of right shift preserving the most significant bit of the int.Bug reproduction
Bug reproduction is especially easy given that the selftest
drivers/dma-buf:udmabuf
(https://github.com/ctrliq/kernel-src-tree/blob/ciqlts9_2/tools/testing/selftests/drivers/dma-buf/udmabuf.c) is alsso a nice example of the basic usage of theudmabuf
module, so there is no need to write any specific testing POCs. Thedrivers/dma-buf:udmabuf
test tries to allocate a DMA buffer of the size of 4 pageskernel-src-tree/tools/testing/selftests/drivers/dma-buf/udmabuf.c
Line 16 in fe9c582
Using
size_limit_mb = 1
:which translates on the testing machine to 256 pages, the test works fine, since 4 < 256:
After setting the MB limit to 0 the test fails:
at the
ioctl
call where the limit is checked:kernel-src-tree/tools/testing/selftests/drivers/dma-buf/udmabuf.c
Lines 88 to 96 in fe9c582
An int overflow resulting in
pglimit = 0
can be achieved withsize_limit_mb * 1024 * 1024 = 2³²
, for the int size of 32, which solved forsize_limit_mb
givessize_limit_mb = 4096
:Setting it to
4096 + 1
makes the test working againThis is equivalent to setting
size_limit_mb
to1
as in the beginning.Specific patch test: passed
Repeating the condition for
pglimit
overflow on the patched kernel results in the selftest working fine: