Skip to content

libbacktrace crash and os::self_exe_name race condition #21889

Closed
@semarie

Description

@semarie

This issue is to report several problems linked:

  • libbacktrace (embeded in every rust-compiled program) is fragile (a bad input could generate a crash, I don't have checked for code-execution at this moment)
  • a race condition exists with os::self_exe_name that could permit to exploit the previous issue by replacing at runtime the binary by a specially crafted elf.

I will first speak about the race, and next about libbacktrace.

First, about os::self_exe_name: it is a function that return an Option about the running binary (the filepath to the binary used for launch the running processus).

The function is used in rustc:

  • by librustc to infer the default sysroot directory (rustc and rustdoc use it)
  • by libbacktrace under bsd system for gets the binary symbols
    (but note that for others platforms, libbacktrace obtain symbols by itself using similar method than os::self_exe_name, so there is the same problem)
  • by severals tests

The implementation (sys::os::load_self) is platform dependant:

  • freebsd: sysctl()
  • dragonfly: readlink(/proc)
  • linux, android: readlink(/proc)
  • macos, ios: _NSGetExecutablePath()
  • windows: GetModuleFileNameW()

Just returning a filepath is subject to race condition for many usages. The libbacktrace usage is one of them.

libbacktrace is initialized on sys::backtrace::print() call (so not at the beginning of the processus). This function is called by sys::backtrace::write(). And on panic, a backtrace is showed if RUST_BACKTRACE environment is setted.

So, when a panic occurs, libbacktrace will read the previously obtained filepath (from os::self_exe_name or by itself). It will open this filepath, parse the ELF structure, search for symbols and addresses... and do all the thing it need for print a pretty backtrace.

The problem is libbacktrace seems not robust enought for specially crafted ELF. I have started to test it with afl-fuzzer, and it reports severals crashs (that may or not be suceptible to produce code-execution).

As libbacktrace is embeded in (near to) every rust-compiled programs, it could be a dangerous thing.

To successfully exploit it, the following conditions are required:

  • run libbacktrace code:
    • RUST_BACKTRACE environment variable to be setted
    • trigger a panic in running process
  • have libbacktrace read a crafted-elf:
    • replace the file of the running program by another one after the start of the program, and before the panic

The conditions are relatively high for simple exploitation, but as it is a problem present in (near to) every rust-compiled code, some attention should be need.

Metadata

Metadata

Assignees

No one assigned

    Labels

    P-mediumMedium priorityT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions