1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-30 22:43:12 +03:00

debug: Improve '%n' fortify detection (BZ 30932)

The 7bb8045ec0 path made the '%n' fortify check ignore EMFILE errors
while trying to open /proc/self/maps, and this added a security
issue where EMFILE can be attacker-controlled thus making it
ineffective for some cases.

The EMFILE failure is reinstated but with a different error
message.  Also, to improve the false positive of the hardening for
the cases where no new files can be opened, the
_dl_readonly_area now uses  _dl_find_object to check if the
memory area is within a writable ELF segment.  The procfs method is
still used as fallback.

Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Arjun Shankar <arjun@redhat.com>
This commit is contained in:
Adhemerval Zanella
2025-03-14 16:09:57 -03:00
parent 1894e219dc
commit ed6a68bac7
15 changed files with 371 additions and 63 deletions

View File

@ -324,16 +324,24 @@ LABEL (form_pointer):
LABEL (form_number):
if ((mode_flags & PRINTF_FORTIFY) != 0)
{
if (! readonly_format)
{
extern int __readonly_area (const void *, size_t)
attribute_hidden;
readonly_format
= __readonly_area (format, ((STR_LEN (format) + 1)
* sizeof (CHAR_T)));
}
if (readonly_format < 0)
__libc_fatal ("*** %n in writable segment detected ***\n");
if (readonly_format == readonly_noerror)
readonly_format = __readonly_area (format, ((STR_LEN (format) + 1)
* sizeof (CHAR_T)));
switch (readonly_format)
{
case readonly_area_writable:
__libc_fatal ("*** %n in writable segments detected ***\n");
/* The format is not within ELF segments and opening /proc/self/maps
failed because there are too many files. */
case readonly_procfs_open_fail:
__libc_fatal ("*** procfs could not open ***\n");
/* The /proc/self/maps can not be opened either because it is not
available or the process does not have the right permission. Since
it should not be attacker-controlled we can avoid failure. */
case readonly_procfs_inaccessible:
case readonly_noerror:
break;
}
}
/* Answer the count of characters written. */
void *ptrptr = process_arg_pointer ();