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.
Recommended fix
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)
PoC verification
Evidence pack
findings/poc/DF-2671 Β· 3 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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.
Recommended fix (defense in depth)
--- 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_testableConfirmed 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.
No comments yet.