git: 13bcc9a88260 - main - libc: Fix stack buffer overflow in cgetnext()
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 29 Oct 2026 12:10:48 UTC
The branch main has been updated by kfv:
URL: https://cgit.FreeBSD.org/src/commit/?id=13bcc9a882603da216c7c38c086fcb501bd9d0ec
commit 13bcc9a882603da216c7c38c086fcb501bd9d0ec
Author: Faraz Vahedi <kfv@FreeBSD.org>
AuthorDate: 2026-07-05 15:03:31 +0000
Commit: Faraz Vahedi <kfv@FreeBSD.org>
CommitDate: 2026-10-29 12:09:45 +0000
libc: Fix stack buffer overflow in cgetnext()
`cgetnext()` copies a capability record's name field into a fixed
1024 byte on-stack buffer (`nbuf[BSIZE]`) one character at a time,
but never checks that the write pointer stays within the buffer.
Therefore, a record name that is longer than `BSIZE` (either on a
single line, or accumulated across several `\`-continued lines as
the pointer is not reset amidst continuation) writes past the end
of `nbuf` and smashes the stack.
The name field is read directly from the capability file, so any
consumer of `cgetnext()`/`cgetfirst()` that processes an untrusted
`termcap(5)`- or `printcap(5)`-style database (e.g. `cap_mkdb(1)`,
`lpr(1)`, or any third-party caller) can be exposed and hence made
to corrupt the stack.
Reviewed by: fuz, dteske
Approved by: fuz (mentor), dteske (mentor)
MFC after: 1 week
Pull Request: https://github.com/freebsd/freebsd-src/pull/2309
---
lib/libc/gen/getcap.3 | 20 ++++++++++++++++++--
lib/libc/gen/getcap.c | 5 +++++
2 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/lib/libc/gen/getcap.3 b/lib/libc/gen/getcap.3
index 00c7edd8026f..9edf947877fc 100644
--- a/lib/libc/gen/getcap.3
+++ b/lib/libc/gen/getcap.3
@@ -28,7 +28,7 @@
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd March 22, 2002
+.Dd July 23, 2026
.Dt GETCAP 3
.Os
.Sh NAME
@@ -258,7 +258,10 @@ expansion, \-1 is returned if a system error occurred, and \-2
is returned if a potential reference loop is detected (see
.Ic tc=
comments below).
-Upon completion of database (0 return) the database is closed.
+Upon completion of database (0 return) or occurrence of an error (negative
+return), the database is closed and a subsequent call to
+.Fn cgetnext
+starts again from the first record.
.Pp
The
.Fn cgetclose
@@ -550,6 +553,19 @@ as follows:
.It Bq Er ENOMEM
No memory to allocate.
.El
+.Pp
+The
+.Fn cgetfirst
+and
+.Fn cgetnext
+functions
+may fail and set
+.Va errno
+as follows:
+.Bl -tag -width Er
+.It Bq Er ENAMETOOLONG
+The name field of a capability record is too long.
+.El
.Sh SEE ALSO
.Xr cap_mkdb 1 ,
.Xr malloc 3
diff --git a/lib/libc/gen/getcap.c b/lib/libc/gen/getcap.c
index cfb81ed0d065..1ee83c8ca28b 100644
--- a/lib/libc/gen/getcap.c
+++ b/lib/libc/gen/getcap.c
@@ -709,6 +709,11 @@ cgetnext(char **bp, char **db_array)
np = nbuf;
for (;;) {
for (cp = line; *cp != '\0'; cp++) {
+ if (np >= nbuf + sizeof(nbuf) - 1) {
+ (void)cgetclose();
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
if (*cp == ':') {
*np++ = ':';
done = 1;