Loading glibc in a new namespace fails vtable check

Moshe Rubin moshe.rubin@gmail.com
Thu Sep 26 15:43:49 GMT 2024


The search goes on ...

I added a test for dlsym(handle, "fwrite"):

<code>
// Get the address of fileno() from the new glibc
int (*libc_fileno)(FILE *fp);
libc_fileno = reinterpret_cast<decltype(libc_fileno)>(dlsym(handle,
"fileno"));
int fd = libc_fileno(stderr);
printf("fd = %d\n", fd);

// Get the address of fwrite() from the new glibc, use stderr
size_t (*libc_fwrite)(const void *ptr, size_t size, size_t nmemb, FILE
*stream);
libc_fwrite = reinterpret_cast<decltype(libc_fwrite)>(dlsym(handle,
"fwrite"));
size_t ret = libc_fwrite("Hello, world!\n", 1, 14, stderr);
printf("ret = %lu\n", ret);
</code>

Here is the run's output:

<output>
$ ./minimal_example /usr/lib/x86_64-linux-gnu/libc.so.6
glibc path: /usr/lib/x86_64-linux-gnu/libc.so.6
fd = 2
Hello, world!
ret = 14
</output>

Still no fatal error.  I really want to reproduce the fatal error.

BTW, here's what Copilot has to say about glibc and vtable
verification.Note
especially its comment about loading a second copy of glibc:

<quote>
The GNU C Library (glibc) performs vtable verification for functions that
operate
on `FILE *` objects. This is part of glibc's internal mechanisms to ensure
the
integrity of `FILE *` objects and prevent potential security issues.

The vtable verification is performed by the `_IO_vtable_check` function in
glibc.
This function is called by other functions that operate on `FILE *`
objects, such
as `fread`, `fwrite`, `fputs`, `fgetc`, `fputc`, `fprintf`, `fscanf`, and
others.

The vtable verification checks that the vtable of a `FILE *` object is
within the
expected range. If the vtable is not within the expected range, glibc
raises a
fatal error with the message "glibc detected an invalid stdio handle".

This mechanism is designed to prevent attacks that attempt to exploit
vulnerabilities in the handling of `FILE *` objects by modifying the vtable
to
point to malicious code. However, it can also cause issues in legitimate
programs
that do unusual things with `FILE *` objects, such as loading a second copy
of
glibc into a new namespace.
</quote>

Moshe


On Thu, Sep 26, 2024 at 6:20 PM Florian Weimer <fweimer@redhat.com> wrote:

> * Moshe Rubin:
>
> >   // Get the address of fileno() from the new glibc
> >   int (*libc_fileno)(FILE *fp);
> >   libc_fileno = reinterpret_cast<decltype(libc_fileno)>(dlsym(handle,
> "fileno"));
> >
> >   int fd = libc_fileno(stderr);
>
> I think fileno does not go through vtable dispatch, so it doesn't
> perform vtable verfication.
>
> Thanks,
> Florian
>
>


More information about the Libc-help mailing list