On Wed, 11 Mar 2026 at 22:31, Frederick Lawler <[email protected]> wrote:
>
> The primary use case is to provide LSM designers a direct API to report
> access allow/denies through the audit subsystem similar to how LSM's
> traditionally log their accesses.
>
> Left out from this API are functions that are potentially abuseable such as
> audit_log_format() where users may fill any field=value pair. Instead, the
> API mostly follows what is exposed through security/lsm_audit.c for
> consistency with user space audit expectations. Further calls to functions
> report once to avoid repeated-call abuse.
>
> Lastly, each audit record corresponds to the loaded BPF program's ID to
> track which program reported the log entry. This helps remove
> ambiguity in the event multiple programs are registered to the same
> security hook.
>
> Exposed functions:
>
>         bpf_audit_log_start()
>         bpf_audit_log_end()
>         bpf_audit_log_cause()
>         bpf_audit_log_cap()
>         bpf_audit_log_path()
>         bpf_audit_log_file()
>         bpf_audit_log_ioctl_op()
>         bpf_audit_log_dentry()
>         bpf_audit_log_inode()
>         bpf_audit_log_task()
>         bpf_audit_log_net_sock()
>         bpf_audit_log_net_sockaddr()
>
> Signed-off-by: Frederick Lawler <[email protected]>
> ---
>  include/linux/lsm_audit.h   |   1 +
>  include/uapi/linux/audit.h  |   1 +
>  security/lsm_audit_kfuncs.c | 306 
> ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 308 insertions(+)
>
> diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
> index 
> 382c56a97bba1d0e5efe082553338229d541e267..859f51590de417ac246309eb75a760b8632224be
>  100644
> --- a/include/linux/lsm_audit.h
> +++ b/include/linux/lsm_audit.h
> @@ -78,6 +78,7 @@ struct common_audit_data {
>  #define LSM_AUDIT_DATA_NOTIFICATION 16
>  #define LSM_AUDIT_DATA_ANONINODE       17
>  #define LSM_AUDIT_DATA_NLMSGTYPE       18
> +#define LSM_AUDIT_DATA_CAUSE 19 /* unused */
>         union   {
>                 struct path path;
>                 struct dentry *dentry;
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index 
> 14a1c1fe013acecb12ea6bf81690965421baa7ff..7a22e214fe3e421decfc4109d2e6a3cee996fe51
>  100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -150,6 +150,7 @@
>  #define AUDIT_LANDLOCK_DOMAIN  1424    /* Landlock domain status */
>  #define AUDIT_MAC_TASK_CONTEXTS        1425    /* Multiple LSM task contexts 
> */
>  #define AUDIT_MAC_OBJ_CONTEXTS 1426    /* Multiple LSM objext contexts */
> +#define AUDIT_BPF_LSM_ACCESS           1427    /* LSM BPF MAC events */
>
>  #define AUDIT_FIRST_KERN_ANOM_MSG   1700
>  #define AUDIT_LAST_KERN_ANOM_MSG    1799
> diff --git a/security/lsm_audit_kfuncs.c b/security/lsm_audit_kfuncs.c
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..0d4fb20be34a61db29aa2c48d2aefc39131e73bf
> --- /dev/null
> +++ b/security/lsm_audit_kfuncs.c
> @@ -0,0 +1,306 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/* Copyright (c) 2026 Cloudflare */
> +
> +#include <linux/audit.h>
> +#include <linux/bpf_mem_alloc.h>
> +#include <linux/gfp_types.h>
> +#include <linux/in6.h>
> +#include <linux/lsm_audit.h>
> +#include <linux/socket.h>
> +#include <linux/types.h>
> +
> +struct bpf_audit_context {
> +       struct audit_buffer *ab;
> +       u64 log_once_mask;
> +};
> +
> +static struct bpf_mem_alloc bpf_audit_context_ma;

bpf_mem_alloc will be deprecated, please use kmalloc_nolock().

> +
> +static inline u64 log_once(struct bpf_audit_context *ac, u64 mask)
> +{
> +       u64 set = (ac->log_once_mask & mask);
> +
> +       ac->log_once_mask |= mask;
> +       return set;
> +}
> +
> + [...]
> +
> +__bpf_kfunc int
> +bpf_audit_log_net_sockaddr(struct bpf_audit_context *ac, int netif,
> +                          const struct sockaddr *saddr__nullable,
> +                          const struct sockaddr *daddr__nullable, int 
> addrlen)
> +{
> +       struct lsm_network_audit net;
> +       struct common_audit_data ad;
> +
> +       net.netif = netif;
> +
> +       if (!saddr__nullable && !daddr__nullable)
> +               return -EINVAL;

Code look a lot cleaner if you just stashed these locally in a better
named variable.

> +
> +       if (saddr__nullable && daddr__nullable &&
> +           saddr__nullable->sa_family != daddr__nullable->sa_family)
> +               return -EINVAL;
> +
> [...]
> +
> +/* The following have a recursion opportunity if a LSM is attached to any of
> + * the following functions, and a bpf_audit_log_*() is called.
> + *  security_current_getlsmprop_subj,
> + *  security_lsmprop_to_secctx, or
> + *  security_release_secctx
> + */
> +BTF_ID_FLAGS(func, bpf_audit_log_cause, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_cap, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_path, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_file, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_ioctl_op, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_dentry, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_inode, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_task, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_net_sock, KF_DESTRUCTIVE);
> +BTF_ID_FLAGS(func, bpf_audit_log_net_sockaddr, KF_DESTRUCTIVE);
> +
> +BTF_KFUNCS_END(lsm_audit_set_ids)
> +
> +static int bpf_lsm_audit_kfuncs_filter(const struct bpf_prog *prog,
> +                                      u32 kfunc_id)
> +{
> +       if (!btf_id_set8_contains(&lsm_audit_set_ids, kfunc_id))
> +               return 0;
> +
> +       return prog->type != BPF_PROG_TYPE_LSM ? -EACCES : 0;
> +}
> +
> +static const struct btf_kfunc_id_set bpf_lsm_audit_set = {
> +       .owner = THIS_MODULE,
> +       .set = &lsm_audit_set_ids,
> +       .filter = bpf_lsm_audit_kfuncs_filter,
> +};
> +
> +static int lsm_audit_init_bpf(void)
> +{
> +       int ret;
> +
> +       ret = bpf_mem_alloc_init(&bpf_audit_context_ma,
> +                                sizeof(struct bpf_audit_context), false);

One you switch to kmalloc_nolock you can drop this too.

> +       return ret ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM,
> +                                                &bpf_lsm_audit_set);
> +}
> +
> +late_initcall(lsm_audit_init_bpf)
>
> --
> 2.43.0
>
>

Reply via email to