Message ID | 20191120143810.8852-1-jolsa@kernel.org |
---|---|
State | RFC |
Delegated to: | BPF Maintainers |
Headers | show |
Series | [RFC] bpf: emit audit messages upon successful prog load and unload | expand |
On Wed, Nov 20, 2019 at 03:38:10PM +0100, Jiri Olsa wrote: > > The only info really needed from BPF side is the globally unique > prog ID where then audit user space tooling can query / dump all > info needed about the specific BPF program right upon load event > and enrich the record, thus these changes needed here can be kept > small and non-intrusive to the core. ... > +static void bpf_audit_prog(const struct bpf_prog *prog, enum bpf_event event) > +{ > + bool has_task_context = event == BPF_EVENT_LOAD; > + struct audit_buffer *ab; > + > + if (audit_enabled == AUDIT_OFF) > + return; > + ab = audit_log_start(audit_context(), GFP_ATOMIC, AUDIT_BPF); > + if (unlikely(!ab)) > + return; > + if (has_task_context) > + audit_log_task(ab); > + audit_log_format(ab, "%sprog-id=%u event=%s", > + has_task_context ? " " : "", > + prog->aux->id, bpf_event_audit_str[event]); > + audit_log_end(ab); Single prog ID is enough for perf_event based framework to track everything about the programs and should be enough for audit. Could you please resend as proper patch with explicit 'From:' ? Since I'm not sure what is the proper authorship of the patch.. Daniel's or yours.
On Wed, Nov 20, 2019 at 01:14:40PM -0800, Alexei Starovoitov wrote: > On Wed, Nov 20, 2019 at 03:38:10PM +0100, Jiri Olsa wrote: > > > > The only info really needed from BPF side is the globally unique > > prog ID where then audit user space tooling can query / dump all > > info needed about the specific BPF program right upon load event > > and enrich the record, thus these changes needed here can be kept > > small and non-intrusive to the core. > > ... > > > +static void bpf_audit_prog(const struct bpf_prog *prog, enum bpf_event event) > > +{ > > + bool has_task_context = event == BPF_EVENT_LOAD; > > + struct audit_buffer *ab; > > + > > + if (audit_enabled == AUDIT_OFF) > > + return; > > + ab = audit_log_start(audit_context(), GFP_ATOMIC, AUDIT_BPF); > > + if (unlikely(!ab)) > > + return; > > + if (has_task_context) > > + audit_log_task(ab); > > + audit_log_format(ab, "%sprog-id=%u event=%s", > > + has_task_context ? " " : "", > > + prog->aux->id, bpf_event_audit_str[event]); > > + audit_log_end(ab); > > Single prog ID is enough for perf_event based framework to track everything > about the programs and should be enough for audit. > Could you please resend as proper patch with explicit 'From:' ? > Since I'm not sure what is the proper authorship of the patch.. Daniel's or yours. it's Daniel's I'll resend jirka
diff --git a/include/linux/audit.h b/include/linux/audit.h index aee3dc9eb378..edd006f4597d 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h @@ -159,6 +159,7 @@ extern void audit_log_key(struct audit_buffer *ab, extern void audit_log_link_denied(const char *operation); extern void audit_log_lost(const char *message); +extern void audit_log_task(struct audit_buffer *ab); extern int audit_log_task_context(struct audit_buffer *ab); extern void audit_log_task_info(struct audit_buffer *ab); @@ -219,6 +220,8 @@ static inline void audit_log_key(struct audit_buffer *ab, char *key) { } static inline void audit_log_link_denied(const char *string) { } +static inline void audit_log_task(struct audit_buffer *ab) +{ } static inline int audit_log_task_context(struct audit_buffer *ab) { return 0; diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index c89c6495983d..32a5db900f47 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -116,6 +116,7 @@ #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ #define AUDIT_TIME_INJOFFSET 1332 /* Timekeeping offset injected */ #define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */ +#define AUDIT_BPF 1334 /* BPF subsystem */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 4effe01ebbe2..9bf1045fedfa 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c @@ -2545,7 +2545,7 @@ void __audit_ntp_log(const struct audit_ntp_data *ad) audit_log_ntp_val(ad, "adjust", AUDIT_NTP_ADJUST); } -static void audit_log_task(struct audit_buffer *ab) +void audit_log_task(struct audit_buffer *ab) { kuid_t auid, uid; kgid_t gid; diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index bac3becf9f90..17f4254495f2 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -23,6 +23,7 @@ #include <linux/timekeeping.h> #include <linux/ctype.h> #include <linux/nospec.h> +#include <linux/audit.h> #include <uapi/linux/btf.h> #define IS_FD_ARRAY(map) ((map)->map_type == BPF_MAP_TYPE_PROG_ARRAY || \ @@ -1318,6 +1319,34 @@ static void free_used_maps(struct bpf_prog_aux *aux) kfree(aux->used_maps); } +enum bpf_event { + BPF_EVENT_LOAD, + BPF_EVENT_UNLOAD, +}; + +static const char * const bpf_event_audit_str[] = { + [BPF_EVENT_LOAD] = "LOAD", + [BPF_EVENT_UNLOAD] = "UNLOAD", +}; + +static void bpf_audit_prog(const struct bpf_prog *prog, enum bpf_event event) +{ + bool has_task_context = event == BPF_EVENT_LOAD; + struct audit_buffer *ab; + + if (audit_enabled == AUDIT_OFF) + return; + ab = audit_log_start(audit_context(), GFP_ATOMIC, AUDIT_BPF); + if (unlikely(!ab)) + return; + if (has_task_context) + audit_log_task(ab); + audit_log_format(ab, "%sprog-id=%u event=%s", + has_task_context ? " " : "", + prog->aux->id, bpf_event_audit_str[event]); + audit_log_end(ab); +} + int __bpf_prog_charge(struct user_struct *user, u32 pages) { unsigned long memlock_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT; @@ -1434,6 +1463,7 @@ static void __bpf_prog_put(struct bpf_prog *prog, bool do_idr_lock) { if (atomic64_dec_and_test(&prog->aux->refcnt)) { perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_UNLOAD, 0); + bpf_audit_prog(prog, BPF_EVENT_UNLOAD); /* bpf_prog_free_id() must be called first */ bpf_prog_free_id(prog, do_idr_lock); __bpf_prog_put_noref(prog, true); @@ -1843,6 +1873,7 @@ static int bpf_prog_load(union bpf_attr *attr, union bpf_attr __user *uattr) */ bpf_prog_kallsyms_add(prog); perf_event_bpf_event(prog, PERF_BPF_EVENT_PROG_LOAD, 0); + bpf_audit_prog(prog, BPF_EVENT_LOAD); err = bpf_prog_new_fd(prog); if (err < 0)