The cgetnext() function in lib/libc/gen/getcap.c has a stack
buffer overflow. At line 782-783:
char nbuf[BSIZE]; /* BSIZE = 1024 */
...
len = strcspn(record, "|:");
memcpy(nbuf, record, len);
The record buffer grows dynamically via realloc (line 757), but
nbuf is a fixed 1024-byte stack buffer. A capability record
with no '|' or ':' character longer than 1024 bytes overflows
nbuf, overwriting the return address and saved registers.
Confirmed on OpenBSD 7.8/arm64 via cap_mkdb(1) with a corrupted
termcap file. GDB shows the stack is overwritten with data from
the record:
#0 _libc_cgetnext at getcap.c:803
buf = <Cannot access memory at address 0x5e5e5e5e5e5e5a56>
#1 0x5e5e5e5e5e5e5e5e in ?? ()
Backtrace stopped: corrupt stack
Registers x19-x30 (including frame pointer and return address)
are all 0x5e5e5e5e5e5e5e5e ('^' characters from the input).
Fix: truncate the name to fit nbuf before the memcpy.
Found by AFL++ fuzzing of cap_mkdb(1).
Index: lib/libc/gen/getcap.c
===================================================================
RCS file: /cvs/src/lib/libc/gen/getcap.c,v
retrieving revision 1.38
diff -u -p -r1.38 getcap.c
--- lib/libc/gen/getcap.c 9 Mar 2026 12:22:44 -0000 1.38
+++ lib/libc/gen/getcap.c
@@ -780,6 +780,8 @@ cgetnext(char **cap, char **db_array)
lookup:
/* extract name from record */
len = strcspn(record, "|:");
+ if (len >= sizeof(nbuf))
+ len = sizeof(nbuf) - 1;
memcpy(nbuf, record, len);
nbuf[len] = '\0';