Skip to content

Commit

Permalink
tools: add option --unique to capable.py
Browse files Browse the repository at this point in the history
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

Documentation (man page and example text) updated.
  • Loading branch information
alban authored and yonghong-song committed Mar 9, 2020
1 parent 15e998d commit 9d7feee
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
6 changes: 5 additions & 1 deletion man/man8/capable.8
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
.TH capable 8 "2020-03-06" "USER COMMANDS"
.TH capable 8 "2020-03-08" "USER COMMANDS"
.SH NAME
capable \- Trace security capability checks (cap_capable()).
.SH SYNOPSIS
.B capable [\-h] [\-v] [\-p PID] [\-K] [\-U] [\-x] [\-\-cgroupmap MAPPATH]
[--unique]
.SH DESCRIPTION
This traces security capability checks in the kernel, and prints details for
each call. This can be useful for general debugging, and also security
Expand Down Expand Up @@ -31,6 +32,9 @@ Show extra fields in TID and INSETID columns.
.TP
\-\-cgroupmap MAPPATH
Trace cgroups in this BPF map only (filtered in-kernel).
.TP
\-\-unique
Don't repeat stacks for the same PID or cgroup.
.SH EXAMPLES
.TP
Trace all capability checks system-wide:
Expand Down
46 changes: 46 additions & 0 deletions tools/capable.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
./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
"""
parser = argparse.ArgumentParser(
Expand All @@ -45,6 +46,8 @@
help="show extra fields in TID and INSETID columns")
parser.add_argument("--cgroupmap",
help="trace cgroups in this BPF map only")
parser.add_argument("--unique", action="store_true",
help="don't repeat stacks for the same pid or cgroup")
args = parser.parse_args()
debug = 0

Expand Down Expand Up @@ -125,6 +128,23 @@ def __getattr__(self, name):
BPF_PERF_OUTPUT(events);
#if UNIQUESET
struct repeat_t {
int cap;
u32 tgid;
#if CGROUPSET
u64 cgroupid;
#endif
#ifdef KERNEL_STACKS
int kernel_stack_id;
#endif
#ifdef USER_STACKS
int user_stack_id;
#endif
};
BPF_HASH(seen, struct repeat_t, u64);
#endif
#if CGROUPSET
BPF_TABLE_PINNED("hash", u64, u64, cgroupset, 1024, "CGROUPPATH");
#endif
Expand Down Expand Up @@ -168,6 +188,28 @@ def __getattr__(self, name):
#ifdef USER_STACKS
data.user_stack_id = stacks.get_stackid(ctx, BPF_F_USER_STACK);
#endif
#if UNIQUESET
struct repeat_t repeat = {0,};
repeat.cap = cap;
#if CGROUPSET
repeat.cgroupid = bpf_get_current_cgroup_id(),
#else
repeat.tgid = tgid;
#endif
#ifdef KERNEL_STACKS
repeat.kernel_stack_id = data.kernel_stack_id;
#endif
#ifdef USER_STACKS
repeat.user_stack_id = data.user_stack_id;
#endif
if (seen.lookup(&repeat) != NULL) {
return 0;
}
u64 zero = 0;
seen.update(&repeat, &zero);
#endif
bpf_get_current_comm(&data.comm, sizeof(data.comm));
events.perf_submit(ctx, &data, sizeof(data));
Expand All @@ -192,6 +234,10 @@ def __getattr__(self, name):
bpf_text = bpf_text.replace('CGROUPPATH', args.cgroupmap)
else:
bpf_text = bpf_text.replace('CGROUPSET', '0')
if args.unique:
bpf_text = bpf_text.replace('UNIQUESET', '1')
else:
bpf_text = bpf_text.replace('UNIQUESET', '0')
if debug:
print(bpf_text)

Expand Down
10 changes: 10 additions & 0 deletions tools/capable_example.txt
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ TIME UID PID COMM CAP NAME AUDIT
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.

Expand All @@ -100,6 +107,7 @@ USAGE:

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

Trace security capability checks

Expand All @@ -112,6 +120,7 @@ optional arguments:
-x, --extra show extra fields in TID and INSETID columns
--cgroupmap CGROUPMAP
trace cgroups in this BPF map only
--unique don't repeat stacks for the same pid or cgroup

examples:
./capable # trace capability checks
Expand All @@ -120,4 +129,5 @@ examples:
./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

0 comments on commit 9d7feee

Please sign in to comment.