forked from chandlerc/rr
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSeccompFilterRewriter.h
67 lines (56 loc) · 2.37 KB
/
SeccompFilterRewriter.h
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
/* -*- Mode: C++; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
#ifndef RR_SECCOMP_FILTER_REWRITER_H_
#define RR_SECCOMP_FILTER_REWRITER_H_
#include <assert.h>
#include <cstdint>
#include <unordered_map>
#include <vector>
/**
* When seccomp decides not to execute a syscall the kernel returns to userspace
* without modifying the registers. There is no negative return value to
* indicate that whatever side effects the syscall would happen did not take
* place. This is a problem for rr, because for syscalls that require special
* handling, we'll be performing that handling even though the syscall didn't
* actually happen.
*
* To get around this we can use the same mechanism that is used to skip the
* syscall in the kernel to skip it ourselves: original_syscallno. We can't
* use the traditional value of -1 though, because the kernel initializes
* original_syscallno to -1 when delivering signals, and exiting sigreturn
* will restore that. Not recording the side effects of sigreturn would be
* bad. Instead we use -2, which still causes skipping the syscall when
* given to the kernel as original_syscallno, but is never generated by the
* kernel itself.
*/
#define SECCOMP_MAGIC_SKIP_ORIGINAL_SYSCALLNO -2
namespace rr {
class RecordTask;
/**
* Object to support install_patched_seccomp_filter.
*/
class SeccompFilterRewriter {
public:
/**
* Assuming |t| is set up for a prctl or seccomp syscall that
* installs a seccomp-bpf filter, patch the filter to signal the tracer
* instead of silently delivering an errno, and install it.
*/
void install_patched_seccomp_filter(RecordTask* t);
uint32_t map_filter_data_to_real_result(uint16_t value) {
assert(value < index_to_result.size());
return index_to_result[value];
}
private:
/**
* Seccomp filters can return 32-bit result values. We need to map all of
* them into a single 16 bit data field. Fortunately (so far) all the
* filters we've seen return constants, so there aren't too many distinct
* values we need to deal with. For each constant value that gets returned,
* we'll add it as the key in |result_map|, with the corresponding value
* being the 16-bit data value that our rewritten filter returns.
*/
std::unordered_map<uint32_t, uint16_t> result_to_index;
std::vector<uint32_t> index_to_result;
};
} // namespace rr
#endif // RR_SECCOMP_FILTER_REWRITER_H_