Skip to main content

Module exec

Module exec 

Source
Expand description

execve handling at the ptrace stop.

The kernel resolves the program path and its PT_INTERP on the host, so both must be rewritten before the syscall proceeds:

  1. the program path is translated, and #! scripts are expanded into interpreter plus argument, repeatedly, until an ELF is reached;
  2. a dynamically linked ELF is not executed directly. One of the host’s machine is exec’d through the loader the exec shim installs (see shim::loader_path), with the program’s guest path as an argument: the loader opens the program and the interpreter its PT_INTERP names through openat, which the handlers translate, maps them where the kernel would and jumps to the interpreter, which then runs as if the kernel had loaded the program. Any other, a 32-bit one or one where the loader cannot run, is re-targeted at the host copy of its dynamic loader, with the program’s guest path as the dynamic loader’s argument;
  3. the new argv is written on the tracee’s stack and the registers point at it. envp is untouched.

Set PROOT_EXEC_DEBUG=1 to print every rewritten exec on stderr.

Without ptrace the same plan is carried out by a trampoline inside the tracee instead of a register rewrite, see shim. An exec of proot or bwrap themselves is a nested launch, planned by nested and carried out by the trampoline in both modes.

Known gaps: at the kernel level /proc/<pid>/exe names the loader, or the dynamic loader; the supervisor answers readlink on /proc/self/exe from the record kept here. A program the loader started reads the path its caller named as AT_EXECFN; one started by its dynamic loader reads the alias it was exec’d through.

Both ABIs are handled: argv is read and written with the caller’s pointer width (the kernel interprets execve arguments in the caller’s ABI), and a 32-bit ELF is re-targeted at its own 32-bit loader.

Modules§

elf
Minimal ELF reader, 32- and 64-bit: enough to find PT_INTERP.
nested
Nested proot and bwrap: a view of their own instead of a supervisor of their own.
shebang
#! line parsing with the kernel’s rules.
shim
The exec trampoline: a static binary installed in the alias directory as e, and the record files that tell it what to run.

Structs§

ExecPlan
What the kernel should load in place of what the tracee asked for.
Trampoline
What the trampoline does inside the tracee before exec’ing the plan.

Constants§

HOST_MACHINE 🔒
e_machine of the host’s programs, the ones the loader maps.
LOADER_ARGS
Number of entries the loader takes before the program’s own argument vector: its alias, the program and the path to report as AT_EXECFN.
MAX_ARGV 🔒
Upper bound on argv entries read from the tracee.
MAX_SHEBANG_DEPTH 🔒
Maximum nesting of #! interpreters (the kernel allows 4).

Statics§

ALIAS_DIR 🔒

Functions§

alias_dir
Directory holding the loader aliases, private to this supervisor.
alias_subdir 🔒
The directory of the aliases of one target, named by a hash of its path.
debug_exec
Prints the rewritten exec when PROOT_EXEC_DEBUG is set.
exec_name 🔒
The name the kernel would give a process exec’d as user_path: the last component of that path, or of guest_prog when the path is empty (execveat of a descriptor) or ends in a slash.
finish_pending
Completes a pending exec at the trampoline’s exec of the real target: records the program and moves the process into its new view, if any.
handle_execve
Rewrites an execve/execveat so the kernel loads host-side files only.
is_loader_alias
Whether path is an alias of the loader, the argv[0] of a program it loaded.
loader_alias 🔒
A symlink to host_interp whose basename is the program’s, for execve.
loader_supports_argv0 🔒
Whether the loader at host_interp understands --argv0.
pending_of
What to remember about a process between its exec of the trampoline and the trampoline’s exec of the real target.
plan
Works out what to exec for a program the tracee named.
plan_in
plan in a given view.
push_argv 🔒
Writes a path and an argv array onto the tracee’s stack.
read_argv
Reads the tracee’s argument vector.
set_alias_dir
Fixes the alias directory before anything used it (the shim installer).