File: capable_example.txt

package info (click to toggle)
bpfcc 0.18.0%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 12,368 kB
  • sloc: ansic: 132,727; python: 36,226; cpp: 26,973; sh: 710; yacc: 525; makefile: 141; lex: 94
file content (135 lines) | stat: -rw-r--r-- 6,655 bytes parent folder | download | duplicates (5)
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
Demonstrations of capable, the Linux eBPF/bcc version.


capable traces calls to the kernel cap_capable() function, which does security
capability checks, and prints details for each call. For example:

# ./capable.py
TIME      UID    PID    COMM             CAP  NAME                 AUDIT
22:11:23  114    2676   snmpd            12   CAP_NET_ADMIN        1
22:11:23  0      6990   run              24   CAP_SYS_RESOURCE     1
22:11:23  0      7003   chmod            3    CAP_FOWNER           1
22:11:23  0      7003   chmod            4    CAP_FSETID           1
22:11:23  0      7005   chmod            4    CAP_FSETID           1
22:11:23  0      7005   chmod            4    CAP_FSETID           1
22:11:23  0      7006   chown            4    CAP_FSETID           1
22:11:23  0      7006   chown            4    CAP_FSETID           1
22:11:23  0      6990   setuidgid        6    CAP_SETGID           1
22:11:23  0      6990   setuidgid        6    CAP_SETGID           1
22:11:23  0      6990   setuidgid        7    CAP_SETUID           1
22:11:24  0      7013   run              24   CAP_SYS_RESOURCE     1
22:11:24  0      7026   chmod            3    CAP_FOWNER           1
22:11:24  0      7026   chmod            4    CAP_FSETID           1
22:11:24  0      7028   chmod            4    CAP_FSETID           1
22:11:24  0      7028   chmod            4    CAP_FSETID           1
22:11:24  0      7029   chown            4    CAP_FSETID           1
22:11:24  0      7029   chown            4    CAP_FSETID           1
22:11:24  0      7013   setuidgid        6    CAP_SETGID           1
22:11:24  0      7013   setuidgid        6    CAP_SETGID           1
22:11:24  0      7013   setuidgid        7    CAP_SETUID           1
22:11:25  0      7036   run              24   CAP_SYS_RESOURCE     1
22:11:25  0      7049   chmod            3    CAP_FOWNER           1
22:11:25  0      7049   chmod            4    CAP_FSETID           1
22:11:25  0      7051   chmod            4    CAP_FSETID           1
22:11:25  0      7051   chmod            4    CAP_FSETID           1

Checks where AUDIT is 0 are ignored by default, which can be changed
with -v but is more verbose.

We can show the TID and INSETID columns with -x.
Since only a recent kernel version >= 5.1 reports the INSETID bit to cap_capable(),
the fallback value "N/A" will be displayed on older kernels.

# ./capable.py -x
TIME      UID    PID    TID    COMM             CAP  NAME                 AUDIT  INSETID
08:22:36  0      12869  12869  chown            0    CAP_CHOWN            1      0
08:22:36  0      12869  12869  chown            0    CAP_CHOWN            1      0
08:22:36  0      12869  12869  chown            0    CAP_CHOWN            1      0
08:23:02  0      13036  13036  setuidgid        6    CAP_SETGID           1      0
08:23:02  0      13036  13036  setuidgid        6    CAP_SETGID           1      0
08:23:02  0      13036  13036  setuidgid        7    CAP_SETUID           1      1
08:23:13  0      13085  13085  chmod            3    CAP_FOWNER           1      0
08:23:13  0      13085  13085  chmod            4    CAP_FSETID           1      0
08:23:13  0      13085  13085  chmod            3    CAP_FOWNER           1      0
08:23:13  0      13085  13085  chmod            4    CAP_FSETID           1      0
08:23:13  0      13085  13085  chmod            4    CAP_FSETID           1      0
08:24:27  0      13522  13522  ping             13   CAP_NET_RAW          1      0
[...]

This can be useful for general debugging, and also security enforcement:
determining a whitelist of capabilities an application needs.

The output above includes various capability checks: snmpd checking
CAP_NET_ADMIN, run checking CAP_SYS_RESOURCES, then some short-lived processes
checking CAP_FOWNER, CAP_FSETID, etc.

To see what each of these capabilities does, check the capabilities(7) man
page and the kernel source.

It is possible to include a kernel stack trace to the capable events by passing
-K to the command:

# ./capable.py -K
TIME      UID    PID    COMM             CAP  NAME                 AUDIT
15:32:21  1000   10708  fetchmail        7    CAP_SETUID           1
        cap_capable+0x1 [kernel]
        ns_capable_common+0x7a [kernel]
        __sys_setresuid+0xc8 [kernel]
        do_syscall_64+0x56 [kernel]
        entry_SYSCALL_64_after_hwframe+0x49 [kernel]
15:32:21  1000   30047  procmail         6    CAP_SETGID           1
        cap_capable+0x1 [kernel]
        ns_capable_common+0x7a [kernel]
        may_setgroups+0x2f [kernel]
        __x64_sys_setgroups+0x18 [kernel]
        do_syscall_64+0x56 [kernel]
        entry_SYSCALL_64_after_hwframe+0x49 [kernel]

Similarly, it is possible to include user-space stack with -U (or they can be
used both at the same time to include user and kernel stack).

Some processes can do a lot of security capability checks, generating a lot of
ouput. In this case, the --unique option is useful to only print once the same
set of capability, pid (or cgroup if --cgroupmap is used) and kernel/user
stacks (if -K or -U are used).

# ./capable.py -K -U --unique

The --cgroupmap option filters based on a cgroup set. It is meant to be used
with an externally created map.

# ./capable.py --cgroupmap /sys/fs/bpf/test01

For more details, see docs/special_filtering.md


USAGE:

# ./capable.py -h
usage: capable.py [-h] [-v] [-p PID] [-K] [-U] [-x] [--cgroupmap CGROUPMAP]
                  [--mntnsmap MNTNSMAP] [--unique]

Trace security capability checks

optional arguments:
  -h, --help            show this help message and exit
  -v, --verbose         include non-audit checks
  -p PID, --pid PID     trace this PID only
  -K, --kernel-stack    output kernel stack trace
  -U, --user-stack      output user stack trace
  -x, --extra           show extra fields in TID and INSETID columns
  --cgroupmap CGROUPMAP
                        trace cgroups in this BPF map only
  --mntnsmap MNTNSMAP   trace mount namespaces in this BPF map only
  --unique              don't repeat stacks for the same pid or cgroup

examples:
    ./capable             # trace capability checks
    ./capable -v          # verbose: include non-audit checks
    ./capable -p 181      # only trace PID 181
    ./capable -K          # add kernel stacks to trace
    ./capable -U          # add user-space stacks to trace
    ./capable -x          # extra fields: show TID and INSETID columns
    ./capable --unique    # don't repeat stacks for the same pid or cgroup
    ./capable --cgroupmap mappath  # only trace cgroups in this BPF map
    ./capable --mntnsmap mappath   # only trace mount namespaces in the map