From 9d7feeed87c5e2977e0e996cc097dcd9d3001c0d Mon Sep 17 00:00:00 2001 From: Alban Crequy Date: Sun, 8 Mar 2020 13:46:15 +0100 Subject: [PATCH] tools: add option --unique to capable.py 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. --- man/man8/capable.8 | 6 ++++- tools/capable.py | 46 +++++++++++++++++++++++++++++++++++++++ tools/capable_example.txt | 10 +++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) diff --git a/man/man8/capable.8 b/man/man8/capable.8 index 6f7768673938..dfb8a6aadfc4 100644 --- a/man/man8/capable.8 +++ b/man/man8/capable.8 @@ -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 @@ -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: diff --git a/tools/capable.py b/tools/capable.py index 64e6069f0aa9..c19cddb93c68 100755 --- a/tools/capable.py +++ b/tools/capable.py @@ -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( @@ -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 @@ -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 @@ -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)); @@ -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) diff --git a/tools/capable_example.txt b/tools/capable_example.txt index f82e6925cf91..bcd6d01ee46c 100644 --- a/tools/capable_example.txt +++ b/tools/capable_example.txt @@ -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. @@ -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 @@ -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 @@ -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