Local Privilege Escalation in the glibc's ld.so
A buffer overflow vulnerability was introduced in a 2021 patch to glibc’s dynamic loader when processing GLIBC_TUNABLES
environment variables. Tunables are basically configuration settings of the runtime that can be set via key/value pairs in the form of key=val
. All GLIBC_TUNABLES
variables will be processed via __tunables_init()
, and will pass the duplicated tunable name and value through parse_tunables()
. Before the 2021 commit, you could pass any tunables you wanted including malformed ones, including tunables with the TUNABLE_SECLEVEL_SXID_ERASE
security level. The commit addressed this to remove SXID_ERASE
tunables as they were considered dangerous tunables that shouldn’t be passed through.
Buffer overflow in tunable processing
The problem is, due to how the argument parsing code is written, you can set a tunable to a tunable key/value pair string, and it’ll then also copy and process that second tunable, which goes out of bounds of the duplicated string when attempting to append the value. This duplicated string also resides in mmap()
‘d memory, which they could leverage to overflow into adjacent mappings.
Exploitation
This bug was leveraged to target link_map
objects used for dynamic linking. Since the map came from mmap()
, it was assumed to be zeroed memory and thus not explicitly zero-initialized. This is fine in normal cases, however, due to the overflow, this assumption could be violated. By overwriting the zeroed data with setup pointers, they could create an uninitialized use type scenario to setup an attacker-controlled l_info
field, which is used for searching for libraries. An attacker could smash this pointer to point to a controlled path setup on the stack to load arbitrary libraries.