Crate linux_libc_auxv

Source
Expand description

§linux-libc-auxv

A parser and builder for the Linux process initial stack layout - use it to decode or construct argc, argv, envp/envv, and auxv (auxiliary vector).

Keywords: crt0, stack layout, AT values, AT pairs, auxvec, auxiliary vector

§Terminology

I use argv, envv, and auxv as names for the null-terminated arrays (vectors) of the corresponding data. They have corresponding “data areas” where pointers point to: argv data area, envp data area, and auxv data area.

§About the Stack Layout

Linux passes an initial stack layout to applications that contains argc, argv, envp/envv, and the auxiliary vector. Normal applications don’t see this as the libc (crt0 component) abstracts this away. For more low-level developers and kernel hackers creating and parsing this feature becomes relevant.

This crate has been tested successfully by myself in a custom runtime system for a Microkernel which loads and starts unmodified Linux binaries. The Linux binary (the libc) was able to find all arguments, environment variables, and the data from the auxiliary vector. Everything was printed properly to stdout.

§Layout Structure

The following figure shows the technical details of the layout. The figure is taken from https://lwn.net/Articles/631631/. As the structure needs to know the pointers beforehand, creating the structure is not trivial. The builder helps to construct this complex binary structure with references into itself.

   ------------------------------------------------------------- 0x7fff6c845000
    0x7fff6c844ff8: 0x0000000000000000
           _  4fec: './stackdump\0'                      <------+
     env  /   4fe2: 'ENVVAR2=2\0'                               |    <----+
          \_  4fd8: 'ENVVAR1=1\0'                               |   <---+ |
          /   4fd4: 'two\0'                                     |       | |     <----+
    args |    4fd0: 'one\0'                                     |       | |    <---+ |
          \_  4fcb: 'zero\0'                                    |       | |   <--+ | |
              3020: random gap padded to 16B boundary           |       | |      | | |
   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|       | |      | | |
              3019: 'x86_64\0'                        <-+       |       | |      | | |
    auxv      3009: random data: ed99b6...2adcc7        | <-+   |       | |      | | |
    data      3000: zero padding to align stack         |   |   |       | |      | | |
   . . . . . . . . . . . . . . . . . . . . . . . . . . .|. .|. .|       | |      | | |
              2ff0: AT_NULL(0)=0                        |   |   |       | |      | | |
              2fe0: AT_PLATFORM(15)=0x7fff6c843019    --+   |   |       | |      | | |
              2fd0: AT_EXECFN(31)=0x7fff6c844fec      ------|---+       | |      | | |
              2fc0: AT_RANDOM(25)=0x7fff6c843009      ------+           | |      | | |
     ELF      2fb0: AT_SECURE(23)=0                                     | |      | | |
   auxiliary  2fa0: AT_EGID(14)=1000                                    | |      | | |
    vector:   2f90: AT_GID(13)=1000                                     | |      | | |
   (id,val)   2f80: AT_EUID(12)=1000                                    | |      | | |
     pairs    2f70: AT_UID(11)=1000                                     | |      | | |
              2f60: AT_ENTRY(9)=0x4010c0                                | |      | | |
              2f50: AT_FLAGS(8)=0                                       | |      | | |
              2f40: AT_BASE(7)=0x7ff6c1122000                           | |      | | |
              2f30: AT_PHNUM(5)=9                                       | |      | | |
              2f20: AT_PHENT(4)=56                                      | |      | | |
              2f10: AT_PHDR(3)=0x400040                                 | |      | | |
              2f00: AT_CLKTCK(17)=100                                   | |      | | |
              2ef0: AT_PAGESZ(6)=4096                                   | |      | | |
              2ee0: AT_HWCAP(16)=0xbfebfbff                             | |      | | |
              2ed0: AT_SYSINFO_EHDR(33)=0x7fff6c86b000                  | |      | | |
   . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .        | |      | | |
              2ec8: environ[2]=(nil)                                    | |      | | |
              2ec0: environ[1]=0x7fff6c844fe2         ------------------|-+      | | |
              2eb8: environ[0]=0x7fff6c844fd8         ------------------+        | | |
              2eb0: argv[3]=(nil)                                                | | |
              2ea8: argv[2]=0x7fff6c844fd4            ---------------------------|-|-+
              2ea0: argv[1]=0x7fff6c844fd0            ---------------------------|-+
              2e98: argv[0]=0x7fff6c844fcb            ---------------------------+
    0x7fff6c842e90: argc=3

Credits: https://lwn.net/Articles/631631/

§Differences to Crates crt0stack and auxv

This crate supports no_std-contexts plus allows construction of the data structure for a different address space, i.e. the address space of a user application.

§Functionality

✅ build data structure for current address space
✅ build data structure for different address space
✅ parse data structure for current address space + output referenced data/pointers
✅ parse data structure for different address space + prevent memory error / no dereferencing of pointers

§MSRV

1.85.0 stable

Structs§

AuxVarFlags
Flags for the auxiliary vector. See https://elixir.bootlin.com/linux/v5.15.5/source/include/uapi/linux/binfmts.h#L23.
AuxVarRaw
Serialized form of an AuxVar as used in the Linux ABI.
StackLayoutBuilder
Builder to create a stack layout as described by the StackLayoutRef type.
StackLayoutRef
Wraps a slice of bytes representing a Linux stack layout allowing to conveniently parse its content.

Enums§

AuxVar
High-level version of an auxiliary vector (auxv) entry. Also called Auxiliary Variable or AT Variable.
AuxVarType
Rust-style representation of the auxiliary variable’s type.