Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf bpf filter: Add uid and gid terms

Allow the BPF filter to use the uid and gid terms determined by the
bpf_get_current_uid_gid BPF helper. For example, the following will
record the cpu-clock event system wide discarding samples that don't
belong to the current user.

$ perf record -e cpu-clock --filter "uid == $(id -u)" -a sleep 0.1

Signed-off-by: Ian Rogers <irogers@google.com>
Acked-by: Namhyung Kim <namhyung@kernel.org>
Cc: John Fastabend <john.fastabend@gmail.com>
Cc: Changbin Du <changbin.du@huawei.com>
Cc: Yang Jihong <yangjihong1@huawei.com>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: bpf@vger.kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Link: https://lore.kernel.org/r/20240524205227.244375-3-irogers@google.com

authored by

Ian Rogers and committed by
Namhyung Kim
d92aa899 63b9cbd7

+15 -1
+1 -1
tools/perf/Documentation/perf-record.txt
··· 200 200 ip, id, tid, pid, cpu, time, addr, period, txn, weight, phys_addr, 201 201 code_pgsz, data_pgsz, weight1, weight2, weight3, ins_lat, retire_lat, 202 202 p_stage_cyc, mem_op, mem_lvl, mem_snoop, mem_remote, mem_lock, 203 - mem_dtlb, mem_blk, mem_hops 203 + mem_dtlb, mem_blk, mem_hops, uid, gid 204 204 205 205 The <operator> can be one of: 206 206 ==, !=, >, >=, <, <=, &
+5
tools/perf/util/bpf-filter.c
··· 63 63 (evsel->core.attr.sample_type & (1 << (expr->term - PBF_TERM_SAMPLE_START)))) 64 64 return 0; 65 65 66 + if (expr->term == PBF_TERM_UID || expr->term == PBF_TERM_GID) { 67 + /* Not dependent on the sample_type as computed from a BPF helper. */ 68 + return 0; 69 + } 70 + 66 71 if (expr->op == PBF_OP_GROUP_BEGIN) { 67 72 struct perf_bpf_filter_expr *group; 68 73
+2
tools/perf/util/bpf-filter.l
··· 95 95 mem_dtlb { return sample_part(PBF_TERM_DATA_SRC, 6); } 96 96 mem_blk { return sample_part(PBF_TERM_DATA_SRC, 7); } 97 97 mem_hops { return sample_part(PBF_TERM_DATA_SRC, 8); } 98 + uid { return sample(PBF_TERM_UID); } 99 + gid { return sample(PBF_TERM_GID); } 98 100 99 101 "==" { return operator(PBF_OP_EQ); } 100 102 "!=" { return operator(PBF_OP_NEQ); }
+3
tools/perf/util/bpf_skel/sample-filter.h
··· 47 47 PBF_TERM_CODE_PAGE_SIZE = PBF_TERM_SAMPLE_START + 23, /* SAMPLE_CODE_PAGE_SIZE = 1U << 23 */ 48 48 PBF_TERM_WEIGHT_STRUCT = PBF_TERM_SAMPLE_START + 24, /* SAMPLE_WEIGHT_STRUCT = 1U << 24 */ 49 49 PBF_TERM_SAMPLE_END = PBF_TERM_WEIGHT_STRUCT, 50 + /* Terms computed from BPF helpers. */ 51 + PBF_TERM_UID, 52 + PBF_TERM_GID, 50 53 }; 51 54 52 55 /* BPF map entry for filtering */
+4
tools/perf/util/bpf_skel/sample_filter.bpf.c
··· 140 140 } 141 141 /* return the whole word */ 142 142 return kctx->data->data_src.val; 143 + case PBF_TERM_UID: 144 + return bpf_get_current_uid_gid() & 0xFFFFFFFF; 145 + case PBF_TERM_GID: 146 + return bpf_get_current_uid_gid() >> 32; 143 147 case PBF_TERM_NONE: 144 148 case __PBF_UNUSED_TERM4: 145 149 case __PBF_UNUSED_TERM5: