File: intercept-library.md

package info (click to toggle)
bear 3.1.6-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,904 kB
  • sloc: cpp: 9,184; sh: 706; ansic: 497; python: 175; makefile: 29
file content (87 lines) | stat: -rw-r--r-- 3,132 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# Intercept Library

This sub project implements intercept logic which is using the operating
system [dynamic loader][DYN_LOADER] pre-load functionality.

  [DYN_LOADER]: https://en.wikipedia.org/wiki/Dynamic_linker

## When to use this way of intercepting?

This method of intercepting compiler calls can work only if the following
conditions are met:

- The operating system is supported by this code.
  (Linux, FreeBSD, OSX were tried and tested)
- The operating system do support (or enable) library preload.
  (Notable example for enabled security modes is the [SIP][OSX_SIP] in
  recent OSX versions.)
- Executables which are linked dynamically.
  (Few distribution does ship statically linked compilers, which will be
  not working this method.)

  [OSX_SIP]: https://support.apple.com/en-us/HT204899

## How it works?

This project implements a shared library and a statically linked executable.

The library can be pre-loaded by the dynamic linker of the Operating System.
It implements a few function related to process creation. By pre-load this
library the executed process uses these functions instead of those from the
standard library.

The idea here is to hijack the process creation methods: do not execute
the requested file, but execute another one. The another process is a
supervisor process, which executes the requested file, but it also
reports the lifecycle related events, like start, stop or signal received.

## Limitations

* If a process can be executed it will execute it. But if the execution request
would fail for some reason, it might report a successful execution because
the statically linked executable will start (but the child process might
fail).

  The type of errors that are might not detected by the library are: `E2BIG`,
`EAGAIN`, `EINVAL`, `EIO`, `ELIBAD`, `ELOOP`, `ENFILE`, `ENAMETOOLONG`, `ENOEXEC`
and `EPERM`.

* The IO redirection might not working properly. Since the requested execution
is not a direct child process (indirect child process relationship) the standard
input/output might not be closed/forwarded as requested.

* `posix_spawn` and `posix_spawn` some of the attributes might not making
effect, because the indirect child process relationship.

* There are still a few POSIX system call that are not covered by the library.
(Like `execveat` or `fexecve` which are using file descriptor to identify
the file to execute.)

With these limitation, an average build process can still be intercepted.

## Implementation details

### `libexec`

It's a shared library.

- It's written in C++ 17.
- It's using symbols only from the `libc` and `libdl`.
- Memory handling:
   - It does not allocates heap memory. (no malloc, no new)
   - It allocates static memory and uses the stack.
- Error handling:
   - Any error is fatal.
   - Errors are reported on `stderr` only if requested.

## `wrapper` supervisor

It's an executable.

- It's written in C++ 17.
- It's using the standard library and some 3rd party libraries.
- Memory handling:
   - It does allocates heap memory.
- Error handling:
   - Any error is fatal.
   - Errors are reported on `stderr` only if requested.