CVE-2026-89665: nfsd: reject out-of-range useconds in NFSv2 SETATTR/CREATE
In the Linux kernel, the following vulnerability has been resolved:
nfsd: reject out-of-range useconds in NFSv2 SETATTR/CREATE
The NFSv2 sattr decoder converts the wire useconds to nanoseconds in svcxdrdecodesattr():
iap->iaatime.tvnsec = tmp2 NSECPERUSEC;
tmp2 is a u32 and NSECPERUSEC is 1000, so the product is computed in unsigned long. On ILP32 that is 32 bits, and an out-of-range useconds value such as 4294968 wraps to tvnsec == 704. The corruption therefore happens during decode, before any proc function can inspect the value, and a later range check on tvnsec would see an in-range result and accept it. Rejecting in the decoder yields an RPC GARBAGEARGS reply. NFSv2 defines no NFSERRINVAL, so there is no NFS-level status to return for a malformed time argument, and the check cannot move to the proc function the way the v3/v4 nsec range checks do.
Guard the raw useconds before the multiplication and reject values greater than 1000000. useconds == 1000000 is kept: it is the Sun convention for "set to the current server time", and the in-tree Linux NFSv2 client emits it in both the atime and the mtime field for a plain touch / utimes(file, NULL) (see encodesattr() and xdrencodecurrentservertime() in fs/nfs/nfs2xdr.c). Rejecting 1000000 would turn that common operation into a hard decode failure for both SETATTR and CREATE. 1000000 NSECPERUSEC is 10^9, which does not wrap on ILP32, so the Sun convention value passes through safely. Only genuinely out-of-range values (> 1000000) are rejected. The atime and mtime guards are therefore symmetric.
The decoder only applied the Sun convention in the mtime block, which clears ATTRATIMESET|ATTRMTIMESET when mtime useconds == 1000000. If a client puts 1000000 in the atime field but not in the mtime field, the atime block stored an out-of-range tvnsec (10^9) and left ATTRATIMESET set, so the bogus value reached the filesystem. Apply the convention in the atime block as well, clearing ATTRATIMESET so the server uses its current time and ignores the value. Only ATTRATIMESET is cleared there. The mtime block keeps its existing behavior, where 1000000 means "set both atime and mtime to now".
[ cel: various tweaks, addenda, and clean-ups ]
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Upgrade
Upgrade
Linux kernel NFSv2 client/server vulnerabilityto a version that resolves this vulnerability.Patch nfsd: reject out-of-range useconds in NFSv2 SETATTR/CREATE - Configuration
In the NFSv2 sattr decoder, guard the raw useconds before multiplying by NSEC_PER_USEC to compute tv_nsec (on ILP32), and reject malformed out-of-range useconds during decode to avoid computing an in-range result via overflow.
NFSv2 sattr decoder (svcxdr_decode_sattr / NFSv2 SETATTR/CREATE path) NFSv2 useconds->nanoseconds conversion handling = Reject out-of-range useconds and guard raw useconds before multiplication (prevent wrap) - Configuration
Update the decoder so that when the mtime useconds equals 1000000 (Sun convention), it clears ATTR_ATIME_SET|ATTR_MTIME_SET; keep mtime block existing behavior while also clearing ATTR_ATIME_SET for symmetric handling.
NFSv2 sattr decoder ATTR_ATIME_SET clearing behavior = Clear ATTR_ATIME_SET and ATTR_MTIME_SET when mtime useconds == 1000000 (Sun convention 'set to current server time') - Compensating control
Because malformed time arguments cause an RPC GARBAGE_ARGS reply, ensure clients are configured to send valid NFSv2 SETATTR/CREATE time values (useconds <= 1000000, with 1000000 meaning set to current server time) to avoid hard decode failures.
Event History
Frequently Asked Questions
Which systems are exposed to the time-value wraparound?
The issue affects Linux kernel NFS server decoding of NFSv2 SETATTR and CREATE attributes on ILP32 systems, where the useconds-to-nanoseconds multiplication is performed in a 32-bit unsigned long.
What input is required to trigger the flawed decoding?
An NFSv2 client must supply an out-of-range useconds value in a time attribute, such as 4294968. Values greater than 1000000 are malformed; 1000000 remains accepted as the Sun convention for setting the time to the current server time.
How does the corrected server handle malformed NFSv2 time attributes?
The corrected decoder rejects an out-of-range raw useconds value before multiplication and returns an RPC GARBAGE_ARGS reply. NFSv2 has no NFSERR_INVAL status for this malformed time argument.