β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-2671

extattr syscalls copyin() the 255-byte attribute name without a NUL-termination guarantee (latent stack OOB read)

Field Value
ID DF-2671
Status new
Severity Info
CVSS 3.1 CVSS:3.1/AV:L/AC:H/PR:L/UI:N/S:U/C:L/I:N/A:N
CWE CWE-170 Improper Null Termination
File sys/kern/vfs_syscalls.c
Lines 5224, 5274, 5322
Area kern
Confidence certain
Discovered 2026-08-29
Pass 2 (GLM 5.3 second pass)
Bucket base:kern
Reported pending
Known CVE none
CVE match novel

Summary

sys_extattr_set_file/get_file/delete_file fill char attrname[EXTATTR_MAXNAMELEN] (255) with raw copyin() and pass it to VOP_SETEXTATTR/VOP_GETEXTATTR as a C string; a 255-nonzero-byte user buffer leaves it unterminated and any strlen/strcmp consumer reads past the stack buffer. No in-tree filesystem implements these VOPs today (all default to vop_eopnotsupp), so it is latent hardening; sys_extattrctl() already uses copyinstr() correctly at :5189.

Replace copyin() with copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL) at the three call sites (ENAMETOOLONG when unterminated), matching sys_extattrctl().

Timeline

  • 2026-08-29 Discovered during pass-2 audit of vfs_syscalls.c (GLM 5.3).

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2671 Β· 3 files
FileTypeDescriptionSize
README.md β€” 1.8 KB ↓ raw
verdict.json β€” 1.4 KB view raw
manifest.json β€” 561 B view raw

DF-2671 β€” extattr syscalls copyin() the attribute name without NUL-termination guarantee (latent stack OOB read)

Impact: latent (hardening)

sys_extattr_set_file(), sys_extattr_get_file() and sys_extattr_delete_file() fill char attrname[EXTATTR_MAXNAMELEN] (EXTATTR_MAXNAMELEN == NAME_MAX == 255, sys/sys/extattr.h:62) with a plain

copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);

(sys/kern/vfs_syscalls.c:5224, :5274, :5322). If the user buffer contains 255 non-zero bytes there is no NUL terminator, yet attrname is handed to VOP_SETEXTATTR/VOP_GETEXTATTR as a C string β€” any filesystem consumer doing strlen(attrname)/strcmp walks past the 255-byte stack buffer (kernel stack info read / KASAN-class OOB read). sys_extattrctl() uses copyinstr() (NUL-guaranteed) at :5189; the other three use raw copyin().

Currently no in-tree filesystem implements vop_setextattr/getextattr (all route to vop_eopnotsupp, sys/kern/vfs_default.c), so the unterminated buffer is never dereferenced today β€” this is a latent trap that turns into a live stack OOB read the moment any FS gains extattr support (e.g. re-import of UFS extattr). Filed as Info/hardening.

--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ sys_extattr_set_file() / sys_extattr_get_file() / sys_extattr_delete_file()
-   error = copyin(uap->attrname, attrname, EXTATTR_MAXNAMELEN);
-   if (error)
-       return (error);
+   attrname[EXTATTR_MAXNAMELEN - 1] = 0;
+   error = copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL);
+   if (error)
+       return (error);

(copyinstr fails with ENAMETOOLONG when the name is not NUL-terminated within 255 bytes β€” matching sys_extattrctl()'s existing behavior.)

Fix verification

not_testable
per-fix-DF-2671

Confirmed kernel references

Detail

Evidence (decisive lines)

['findings/poc/DF-2671/README.md (code excerpts + line refs + suggested fix)']

PoC changes

n/a β€” inspection-only finding

Verified recommended fix

Use copyinstr(uap->attrname, attrname, EXTATTR_MAXNAMELEN, NULL) in the three extattr syscalls so the name is guaranteed NUL-terminated.

Verdict

Latent hardening defect (Info): sys_extattr_set_file/get_file/delete_file copy exactly EXTATTR_MAXNAMELEN (255) attacker bytes into a stack buffer with plain copyin() (sys/kern/vfs_syscalls.c:5224, :5274, :5322) with no NUL-termination guarantee, then pass it as a C string to VOP_SETEXTATTR/VOP_GETEXTATTR. No in-tree filesystem implements those VOPs today (all route to vop_eopnotsupp), so no OOB read is currently reachable; any future FS extattr implementation doing strlen()/strcmp on attrname inherits a stack OOB read. sys_extattrctl():5189 already uses copyinstr() correctly.