Skip to content

Conversation

pvts-mat
Copy link
Contributor

[LTS 9.4]
CVE-2025-22026
VULN-64896

Problem

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=930b64ca0c511521f0abdd1d57ce52b2a6e3476b

nfsd: don't ignore the return code of svc_proc_register()

Currently, nfsd_proc_stat_init() ignores the return value of
svc_proc_register(). If the procfile creation fails, then the kernel
will WARN when it tries to remove the entry later.

Fix nfsd_proc_stat_init() to return the same type of pointer as
svc_proc_register(), and fix up nfsd_net_init() to check that and fail
the nfsd_net construction if it occurs.

svc_proc_register() can fail if the dentry can't be allocated, or if an
identical dentry already exists. The second case is pretty unlikely in
the nfsd_net construction codepath, so if this happens, return -ENOMEM.

Affected: yes

The affected nfsd module is enabled with CONFIG_NFSD which is m for all config variants

$ grep 'CONFIG_NFSD\b' configs/*.config

configs/kernel-aarch64-64k-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-aarch64-64k-rhel.config:CONFIG_NFSD=m
configs/kernel-aarch64-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-aarch64-rhel.config:CONFIG_NFSD=m
configs/kernel-aarch64-rt-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-aarch64-rt-rhel.config:CONFIG_NFSD=m
configs/kernel-ppc64le-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-ppc64le-rhel.config:CONFIG_NFSD=m
configs/kernel-s390x-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-s390x-rhel.config:CONFIG_NFSD=m
configs/kernel-s390x-zfcpdump-rhel.config:CONFIG_NFSD=m
configs/kernel-x86_64-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-x86_64-rhel.config:CONFIG_NFSD=m
configs/kernel-x86_64-rt-debug-rhel.config:CONFIG_NFSD=m
configs/kernel-x86_64-rt-rhel.config:CONFIG_NFSD=m

The return value of svc_proc_register(…) function is clearly not being checked:

svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops);

Solution

Cherry-picking the mainline fix 930b64c is meaningless, as the code underwent considerable architectural changes related to the exposition of network stats in the user space since ciqlts9_4 branched off. Picking them as "cve-pre" would be impractical and risky, could also affect the /proc interface. It was chosen instead to apply a change equivalent to 930b64c in meaning but fitting ciqlts9_4 codebase. As a result it differs completely from the upstream.

  1. The modified function was nfsd_stat_init(…) instead of nfsd_proc_stat_init(…). It's logically the same function, but was renamed in 93483ac. Observe the evolution of nfsd_stat_init(…) between ciqlts9_4 and kernel-mainline for the full context, with the last change coming from the upstream CVE-2025-22026 fix:
    int nfsd_stat_init(void)
    {
    int err;
    err = nfsd_stat_counters_init();
    if (err)
    return err;
    svc_proc_register(&init_net, &nfsd_svcstats, &nfsd_proc_ops);
    return 0;
    }

    void nfsd_proc_stat_init(struct net *net)
    {
    svc_proc_register(net, &nfsd_svcstats, &nfsd_proc_ops);
    }

    void nfsd_proc_stat_init(struct net *net)
    {
    struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
    }

    struct proc_dir_entry *nfsd_proc_stat_init(struct net *net)
    {
    struct nfsd_net *nn = net_generic(net, nfsd_net_id);
    return svc_proc_register(net, &nn->nfsd_svcstats, &nfsd_proc_ops);
    }
  2. The int return value of nfsd_stat_init(…) was left unchanged, unlike the voidstruct proc_dir_entry * change in the upstream. The function in the older version already returns a status code so it could have been utilized. This nullified any changes to the header file fs/nfsd/stats.h found in the upstream.
  3. The -ENOMEM return code in case of svc_proc_register(…) call failure was retained, based on the justification given in the upstream fix which remained valid:

    svc_proc_register() can fail if the dentry can't be allocated, or if an
    identical dentry already exists. The second case is pretty unlikely in
    the nfsd_net construction codepath, so if this happens, return -ENOMEM.

  4. The original changes in 930b64c included additional cleanup steps in the nfsd_net_init(…) function of fs/nfsd/nfsctl.c in case nfsd_proc_stat_init(…) failed: 930b64c#diff-540a099ea05e266ccb0e9fa515be1e018baf46cef98f0f169e509fa43e1b4878R2228-R2229
    In ciqlts9_4 this is not necessary, because nfsd_stat_init(…) is not even used inside nfsd_net_init(…). Instead it's called in init_nfsd() (and only there) in a way which already covers a jump to an appropriate cleanup routine when nfsd_stat_init(…) fails:
    retval = nfsd_stat_init(); /* Statistics */
    if (retval)
    goto out_free_pnfs;

    As a result there are no changes to the fs/nfsd/nfsctl.c file, unlike in the upstream.

kABI check: passed

$ DEBUG=1 CVE=CVE-2025-22026 ./ninja.sh _kabi_checked__x86_64--test--ciqlts9_4-CVE-2025-22026

[0/1] Check ABI of kernel [ciqlts9_4-CVE-2025-22026]
++ uname -m
+ python3 /data/src/ctrliq-github/kernel-dist-git-el-9.4/SOURCES/check-kabi -k /data/src/ctrliq-github/kernel-dist-git-el-9.4/SOURCES/Module.kabi_x86_64 -s vms/x86_64--build--ciqlts9_4/build_files/kernel-src-tree-ciqlts9_4-CVE-2025-22026/Module.symvers
kABI check passed
+ touch state/kernels/ciqlts9_4-CVE-2025-22026/x86_64/kabi_checked

Boot test: passed

boot-test.log

Kselftests: passed relative

Coverage

bpf (only test_lpm_map, test_lru_map, test_sock, test_verifier, test_cgroup_storage, test_tag, test_tcpnotify_user, test_sysctl), breakpoints (only breakpoint_test), capabilities, clone3, cpu-hotplug, cpufreq, drivers/dma-buf, drivers/net/bonding (all except bond_macvlan.sh), drivers/net/team, exec, filesystems/binderfs, filesystems/epoll, firmware, fpu, ftrace, futex, gpio, intel_pstate, iommu, ipc, ir, kcmp, kexec, kvm, landlock, lib, livepatch, membarrier, memfd, memory-hotplug, mincore, mount, mqueue, nci, net/forwarding (all except sch_red.sh, sch_ets.sh, sch_tbf_ets.sh, vxlan_bridge_1d_ipv6.sh, ip6gre_inner_v6_multipath.sh, mirror_gre_vlan_bridge_1q.sh, router_bridge_lag.sh, mirror_gre_bridge_1d_vlan.sh, bridge_igmp.sh, sch_tbf_root.sh, tc_police.sh, q_in_vni.sh, dual_vxlan_bridge.sh, ipip_hier_gre_keys.sh, gre_inner_v6_multipath.sh, sch_tbf_prio.sh, tc_actions.sh, router_bridge_1d_lag.sh), net/hsr, net/mptcp (all except userspace_pm.sh, simult_flows.sh, mptcp_join.sh), net (all except reuseport_addr_any.sh, srv6_end_dt6_l3vpn_test.sh, srv6_end_flavors_test.sh, udpgro_fwd.sh, udpgso_bench.sh, fib_nexthops.sh, ip_defrag.sh, reuseaddr_conflict, srv6_end_dt46_l3vpn_test.sh, srv6_end_dt4_l3vpn_test.sh, gro.sh, xfrm_policy.sh, txtimestamp.sh), netfilter (all except nft_trans_stress.sh), nsfs, pid_namespace, pidfd, proc (all except proc-pid-vm, proc-uptime-001), pstore, ptrace, rlimits, rseq, seccomp, sgx, sigaltstack, size, splice, static_keys, syscall_user_dispatch, tc-testing, tdx, timens, timers, tmpfs, tpm2, tty, vDSO, x86, zram

Reference

kselftests–ciqlts9_4–run1.log

Patch

kselftests–ciqlts9_4-CVE-2025-22026–run1.log
kselftests–ciqlts9_4-CVE-2025-22026–run2.log

Comparison

The tests results between the reference and patched kernel are the same

$ ktests.xsh diff -d kselftests*.log

Column    File
--------  ----------------------------------------------
Status0   kselftests--ciqlts9_4--run1.log
Status1   kselftests--ciqlts9_4-CVE-2025-22026--run1.log
Status2   kselftests--ciqlts9_4-CVE-2025-22026--run2.log

Specific tests: passed

Considering that the change deals with module's initialization routine a simple loading of the nfsd module constitutes a reasonable patch test, at least of the success branch.

[root@ciqlts-9-4 pvts]# modprobe nfsd
[root@ciqlts-9-4 pvts]# lsmod
Module                  Size  Used by
nfsd                  958464  0
auth_rpcgss           196608  1 nfsd
nfs_acl                16384  1 nfsd
lockd                 196608  1 nfsd
grace                  16384  2 nfsd,lockd
rfkill                 40960  1
vfat                   20480  1
fat                   102400  1 vfat
intel_rapl_msr         20480  0
intel_rapl_common      45056  1 intel_rapl_msr
intel_uncore_frequency_common    16384  0
isst_if_common         24576  0
nfit                   86016  0
libnvdimm             245760  1 nfit
kvm_intel             442368  0
kvm                  1335296  1 kvm_intel
virtio_gpu            102400  0
irqbypass              16384  1 kvm
iTCO_wdt               16384  0
virtio_dma_buf         16384  1 virtio_gpu
iTCO_vendor_support    16384  1 iTCO_wdt
rapl                   28672  0
drm_shmem_helper       28672  1 virtio_gpu
i2c_i801               40960  0
i2c_smbus              20480  1 i2c_i801
pcspkr                 16384  0
virtio_balloon         28672  0
drm_kms_helper        245760  3 virtio_gpu
syscopyarea            16384  1 drm_kms_helper
sysfillrect            16384  1 drm_kms_helper
sysimgblt              16384  1 drm_kms_helper
lpc_ich                28672  0
fb_sys_fops            16384  1 drm_kms_helper
joydev                 28672  0
drm                   741376  4 drm_kms_helper,drm_shmem_helper,virtio_gpu
xfs                  2510848  2
libcrc32c              16384  1 xfs
sr_mod                 28672  0
cdrom                  90112  1 sr_mod
sg                     53248  0
virtio_console         45056  1
crct10dif_pclmul       16384  1
crc32_pclmul           16384  0
crc32c_intel           24576  1
ahci                   49152  0
libahci                61440  1 ahci
ghash_clmulni_intel    16384  0
virtio_blk             36864  3
libata                479232  2 libahci,ahci
virtio_net             81920  0
net_failover           24576  1 virtio_net
failover               16384  1 net_failover
virtiofs               36864  3
serio_raw              20480  0
sunrpc                851968  5 nfsd,auth_rpcgss,lockd,nfs_acl
dm_mirror              32768  0
dm_region_hash         28672  1 dm_mirror
dm_log                 28672  2 dm_region_hash,dm_mirror
dm_mod                237568  2 dm_log,dm_mirror
fuse                  212992  2 virtiofs

The nfsd statistics implemented by the modified file are available in /proc/net/rpc/nfsd:

[root@ciqlts-9-4 pvts]# cat /proc/net/rpc/nfsd

rc 0 0 0
fh 0 0 0 0 0
io 0 0
th 0 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
ra 0 0 0 0 0 0 0 0 0 0 0 0
net 0 0 0 0
rpc 0 0 0 0 0
proc3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
proc4 2 0 0
proc4ops 76 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
wdeleg_getattr 0

PlaidCat
PlaidCat previously approved these changes Sep 10, 2025
Copy link
Collaborator

@PlaidCat PlaidCat left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this makes sense to me

:shipit:

bmastbergen
bmastbergen previously approved these changes Sep 10, 2025
Copy link
Collaborator

@bmastbergen bmastbergen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥌

jira VULN-64896
cve CVE-2025-22026
commit-author Jeff Layton <[email protected]>
commit 930b64c
upstream-diff |
  nfsd underwent considerable architectural changes related to the
  exposition of network stats in the user space since `ciqlts9_4' branched
  off, which are assumed by the upstream fix
  930b64c to be in place - see patches
  d98416c, 93483ac, 4b14885, e41ee44, 16fb980. This backport
  addresses the core of the issue without pulling in all of these changes,
  which is checking the value returned by `svc_proc_register'.

Currently, nfsd_proc_stat_init() ignores the return value of
svc_proc_register(). If the procfile creation fails, then the kernel
will WARN when it tries to remove the entry later.

Fix nfsd_proc_stat_init() to return the same type of pointer as
svc_proc_register(), and fix up nfsd_net_init() to check that and fail
the nfsd_net construction if it occurs.

svc_proc_register() can fail if the dentry can't be allocated, or if an
identical dentry already exists. The second case is pretty unlikely in
the nfsd_net construction codepath, so if this happens, return -ENOMEM.

	Reported-by: [email protected]
Closes: https://lore.kernel.org/linux-nfs/[email protected]/
	Cc: [email protected] # v6.9
	Signed-off-by: Jeff Layton <[email protected]>
	Signed-off-by: Chuck Lever <[email protected]>
(cherry picked from commit 930b64c)
	Signed-off-by: Marcin Wcisło <[email protected]>
@pvts-mat pvts-mat dismissed stale reviews from bmastbergen and PlaidCat via 3d32877 September 12, 2025 19:16
@pvts-mat pvts-mat force-pushed the ciqlts9_4-CVE-2025-22026 branch from 3e4c5d5 to 3d32877 Compare September 12, 2025 19:16
@pvts-mat
Copy link
Contributor Author

kselftests–ciqlts94-CVE-2025-22026–fix–run1.log
kselftests–ciqlts94-CVE-2025-22026–fix–run2.log

Same results, except for timers:raw_skew, but this one proved to be flappy before

$ ktests.xsh diff -d  \
  kselftests--ciqlts9_4--run1.log \
  kselftests--ciqlts9_4-CVE-2025-22026--fix--run1.log \
  kselftests--ciqlts9_4-CVE-2025-22026--fix--run2.log

Column    File
--------  ---------------------------------------------------
Status0   kselftests--ciqlts9_4--run1.log
Status1   kselftests--ciqlts9_4-CVE-2025-22026--fix--run1.log
Status2   kselftests--ciqlts9_4-CVE-2025-22026--fix--run2.log

TestCase         Status0  Status1  Status2  Summary
timers:raw_skew  pass     fail     fail     diff

Module loading:

[root@ciqlts-9-4 pvts]# modprobe nfsd

[root@ciqlts-9-4 pvts]# lsmod
lsmod
Module                  Size  Used by
nfsd                  958464  0
auth_rpcgss           196608  1 nfsd
nfs_acl                16384  1 nfsd
lockd                 196608  1 nfsd
grace                  16384  2 nfsd,lockd
rfkill                 40960  1
vfat                   20480  1
fat                   102400  1 vfat
intel_rapl_msr         20480  0
intel_rapl_common      45056  1 intel_rapl_msr
intel_uncore_frequency_common    16384  0
isst_if_common         24576  0
nfit                   86016  0
libnvdimm             245760  1 nfit
virtio_gpu            102400  0
iTCO_wdt               16384  0
kvm_intel             442368  0
virtio_dma_buf         16384  1 virtio_gpu
drm_shmem_helper       28672  1 virtio_gpu
iTCO_vendor_support    16384  1 iTCO_wdt
kvm                  1335296  1 kvm_intel
drm_kms_helper        245760  3 virtio_gpu
irqbypass              16384  1 kvm
syscopyarea            16384  1 drm_kms_helper
sysfillrect            16384  1 drm_kms_helper
rapl                   28672  0
sysimgblt              16384  1 drm_kms_helper
pcspkr                 16384  0
i2c_i801               40960  0
fb_sys_fops            16384  1 drm_kms_helper
i2c_smbus              20480  1 i2c_i801
virtio_balloon         28672  0
lpc_ich                28672  0
joydev                 28672  0
drm                   741376  4 drm_kms_helper,drm_shmem_helper,virtio_gpu
xfs                  2510848  2
libcrc32c              16384  1 xfs
sr_mod                 28672  0
cdrom                  90112  1 sr_mod
sg                     53248  0
virtio_net             81920  0
net_failover           24576  1 virtio_net
virtio_console         45056  1
failover               16384  1 net_failover
crct10dif_pclmul       16384  1
crc32_pclmul           16384  0
crc32c_intel           24576  1
virtio_blk             36864  3
ghash_clmulni_intel    16384  0
ahci                   49152  0
libahci                61440  1 ahci
libata                479232  2 libahci,ahci
virtiofs               36864  3
serio_raw              20480  0
sunrpc                851968  5 nfsd,auth_rpcgss,lockd,nfs_acl
dm_mirror              32768  0
dm_region_hash         28672  1 dm_mirror
dm_log                 28672  2 dm_region_hash,dm_mirror
dm_mod                237568  2 dm_log,dm_mirror
fuse                  212992  2 virtiofs

[root@ciqlts-9-4 pvts]# cat /proc/net/rpc/nfsd
cat /proc/net/rpc/nfsd
rc 0 0 0
fh 0 0 0 0 0
io 0 0
th 0 0 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000 0.000
ra 0 0 0 0 0 0 0 0 0 0 0 0
net 0 0 0 0
rpc 0 0 0 0 0
proc3 22 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
proc4 2 0 0
proc4ops 76 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
wdeleg_getattr 0
[root@ciqlts-9-4 pvts]#

Copy link
Collaborator

@bmastbergen bmastbergen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🥌

@PlaidCat PlaidCat merged commit e46533c into ctrliq:ciqlts9_4 Sep 22, 2025
4 of 5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

4 participants