Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/akawashiro/sloader

sloader is an ELF loader which aims to replace ld-linux.so of glibc.
https://github.com/akawashiro/sloader

elf elf-binaries elf-loader glibc linux

Last synced: about 7 hours ago
JSON representation

sloader is an ELF loader which aims to replace ld-linux.so of glibc.

Awesome Lists containing this project

README

        

# sloader
`sloader` is an ELF loader that aims to replace `ld-linux.so.2` of glibc.

## Notice
`sloader` haven't implmented almost all security related features. Please be careful.

## Table of Contents
- [Current status](#current-status)
- [How to build and use](#how-to-build-and-use)
- [Why I am making alternative loader](#why-i-am-making-alternative-loader)
- [What is a loader](#what-is-a-loader)
- [Problem of `ld-linux.so`](#problem-of-ld-linuxso)
- [Motivation of making sloader](#motivation-of-making-sloader)
- [Developement principles of sloader](#developement-principles-of-sloader)
- [For developpers](#for-developpers)
- [How to build and run tests](#how-to-build-and-run-tests)
- [Test using custom build glibc](#test-using-custom-build-glibc)

## Current status
`sloader` can load many practical programs such as `cmake`, `g++`, `ld`, `htop`, etc. Furthermore, `sloader` can launche some GUI applications.
![GUI applications launched by sloader](./xapps-launched-by-sloader.png)

However, `sloader` depends on `ld-linux.so` because I cannot statically link `sloader` now.

## How to build and use
```
$ git clone https://github.com/akawashiro/sloader.git
$ cd sloader
$ mkdir build
$ cmake -S . -B build -G Ninja
$ cmake --build build
$ ./build/sloader ls
```

## Why I am making alternative loader
### What is a loader
When you run an executable binary file on Linux using execve(2), there are two execution paths.
- Linux kernel loads the file to the memory space.
- The loader specified by the file loads the file to the memory space.

You can check the specified loader path using `readelf -l`. In most cases, you will find `Requesting program interpreter: /lib64/ld-linux-x86-64.so.2` which means the loader loads the binary. Although the path includes `-x86-64` because my machine is x86-64, I call it `ld-linux.so` from now for generality.

```
$ readelf -l $(which nvim) | grep INTERP -A 2
INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318
0x000000000000001c 0x000000000000001c R 0x1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
```

`ld-linux.so` does three things when loading binary files.
- Seaches shared libraries that the file needs.
- Loads all shared libraries and the file to the memory.
- Resolves symbols of shared libraries and the file.

It is important to understand precisely how `ld-linux.so` works. For example, valuable hacks with environment variables such as LD_PRELOAD and LD_AUDIT are implemented by changing their behavior. Understanding the behavior of `ld-linux.so` will allow you to infer what these environment variables can and cannot do. Also, understanding it is essential for creating software like [https://github.com/akawashiro/sold](https://github.com/akawashiro/sold) that forcibly links shared libraries.

### Problem of `ld-linux.so`
`ld-linux.so` is installed on Linux as part of GNU libc, and its complete source code is publicly available. However, two problems exist in understanding the behavior of `ld-linux.so` from the published source code.

The first problem is that the GNU libc source code is hard to read. GNU libc is a software with a long history written in C language. It also requires portability to multiple architectures such as x86-84, Alpha, ARM, and PowerPC. As a result, macros are used extensively throughout the source code, making it difficult to follow the flow of the program.

The second problem is that `libc.so` is simultaneously initialized when `ld-linux.so` loads an executable file. And it is hard to understand the initialization and the loading process separately. libc.so is the so-called standard C library, which is almost certainly loaded when the binary file is loaded by `ld-linux.so`. `libc.so` and `ld-linux.so` are in the same package, and glibc doesn't explicitly document the relationship between the two components.

### Motivation of making sloader
To solve the above problems and understand `ld-linux.so` behavior, I decided to develop a new loader that can replace `ld-linux.so` . In other words, I am trying to load all the programs that start on Linux (`systemd`, `cat`, `find`, `firefox`, etc.).

### Developement principles of sloader
I decided the following two principles when I started the development.

The first principle is to use modern C++ instead of C. I try to use modern C++ features up to C++20 to improve readability. I considered using Rust, but I decided that a language compatible with the C language would be better because I would be developing while referring to the GNU libc source code.

The second principle is not to initialize `libc.so`. The purpose is to understand only the load part, so I will not do the complicated `libc.so`.

## For developpers
### How to build and run tests
```
$ git clone https://github.com/akawashiro/sloader.git
$ cd sloader
$ mkdir build
$ cmake -S . -B build -G Ninja
$ cmake --build build
$ cd build
$ ctest -V
```

### Test using custom build glibc
```
$ git clone https://github.com/akawashiro/sloader.git
$ cd sloader
$ mkdir build
$ cmake -S . -B build -G Ninja
$ cmake --build build
$ ./misc/clone_glibc.sh
$ ./misc/build_glibc.sh
$ SLOADER_LIBRARY_PATH=/home/akira/sloader/glibc-install/lib ./build/sloader ./build/tests/hello_glibc/hello_glibc
```