Bug 30039 - __vsprintf_internal does not handle unspecified buffer length in fortify mode
Summary: __vsprintf_internal does not handle unspecified buffer length in fortify mode
Status: RESOLVED FIXED
Alias: None
Product: glibc
Classification: Unclassified
Component: stdio (show other bugs)
Version: 2.37
: P1 normal
Target Milestone: 2.37
Assignee: Florian Weimer
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2023-01-24 09:44 UTC by Florian Weimer
Modified: 2023-01-25 10:19 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Florian Weimer 2023-01-24 09:44:56 UTC
From libio/iovsprintf.c:

  /* When called from fortified sprintf/vsprintf, erase the destination
     buffer and try to detect overflows.  When called from regular
     sprintf/vsprintf, do not erase the destination buffer, because
     known user code relies on this behavior (even though its undefined
     by ISO C), nor try to detect overflows.  */
  if ((mode_flags & PRINTF_CHK) != 0)
    {
      string[0] = '\0';
      __printf_buffer_init (&buf, string, maxlen,
			    __printf_buffer_mode_sprintf_chk);
    }
  else
    {
      __printf_buffer_init (&buf, string, 0, __printf_buffer_mode_sprintf);
      buf.write_end = (char *) ~(uintptr_t) 0; /* End of address space.  */
    }

However, in some cases, this code is called for an inline expansion of sprintf where the buffer size is not known and maxlen == -1. This makes buf->write_end == buf->write_ptr - 1 (so end before active write position). This causes an assertion failure in __printf_buffer_as_file_commit:

Fatal glibc error: printf_buffer_as_file.c:31 (__printf_buffer_as_file_commit): assertion failed: file->stream._IO_write_ptr <= file->next->write_end

I believe the assertion is not unreasonable, so I think we need to fix the buffer setup.
Comment 1 Florian Weimer 2023-01-24 11:33:18 UTC
Patch posted:

[PATCH] stdio-common: Handle -1 buffer size in __sprintf_chk & co (bug 30039)
<https://sourceware.org/pipermail/libc-alpha/2023-January/144931.html>
Comment 2 Florian Weimer 2023-01-25 10:19:51 UTC
Fixed for 2.37 via:

commit 0d50f477f47ba637b54fb03ac48d769ec4543e8d
Author: Florian Weimer <fweimer@redhat.com>
Date:   Wed Jan 25 08:01:00 2023 +0100

    stdio-common: Handle -1 buffer size in __sprintf_chk & co (bug 30039)
    
    This shows up as an assertion failure when sprintf is called with
    a specifier like "%.8g" and libquadmath is linked in:
    
    Fatal glibc error: printf_buffer_as_file.c:31
      (__printf_buffer_as_file_commit): assertion failed:
      file->stream._IO_write_ptr <= file->next->write_end
    
    Fix this by detecting pointer wraparound in __vsprintf_internal
    and saturate the addition to the end of the address space instead.
    
    Reviewed-by: Carlos O'Donell <carlos@redhat.com>
    Tested-by: Carlos O'Donell <carlos@redhat.com>

Introduce in the vfprintf refactoring, so need for backporting.