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