* [RFC PATCH 0/3] LSM: Hook registration exculsivity [not found] <20260225192143.14448-1-casey.ref@schaufler-ca.com> @ 2026-02-25 19:21 ` Casey Schaufler 2026-02-25 19:21 ` [RFC PATCH 1/3] LSM: add a flags field to the LSM hook definitions Casey Schaufler ` (2 more replies) 0 siblings, 3 replies; 11+ messages in thread From: Casey Schaufler @ 2026-02-25 19:21 UTC (permalink / raw) To: casey, paul, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux This patch set represents a reasonably radical change to the LSM stacking model. The notion of an "exclusive" LSM begins to give way to exclusive LSM hooks. Instead of disallowing more than one exclusive LSM, individual hooks are marked as exclusive and only one is allowed to be registered. Subsequent LSMs that attempt to register these hooks are denied them. This can have consequences. The hooks relative to secmarks have been used here to demonstrate that the scheme can work, and that it isn't always as clean as one might like. Please comment fully. Quite a bit of tinkering went into devising this approach, which is intended to address a number of concerns. Add a flags field to the LSM hook definition. The first LSM that requests a hook with the LSM_FLAG_EXCLUSIVE flag will be the only LSM that can register any hook thus marked. Attempts by other LSMs to register such hooks are ignored. Direct access to skb->secmark within LSMs are wrapped with a helper function lsm_secmark_from_skb(). This function checks to see if the secmark related LSM hooks, which are marked LSM_FLAG_EXCLUSIVE, are registered by the calling LSM. If they are, the secmark value is returned. Otherwise, the invalid secmark value 0 is returned. Future implementations of lsm_secmark_from_skb() could use some form of secmark encoding that would allow more than one LSM to use secmarks at the same time. The LSMs that currently support use of secmarks are taught how to identify if they are allowed use of the secmark. Each sets secmark values differently. At initialization the LSMs have the opportunity to take steps to ensure correct behavior if they don't have secmark access. https://github.com/cschaufler/lsm-stacking#secmark-6.19-rc8-v1 Casey Schaufler (3): LSM: add a flags field to the LSM hook definitions LSM: Enforce exclusive hooks LSM: Reserve use of secmarks include/linux/bpf_lsm.h | 2 +- include/linux/lsm_hook_defs.h | 614 ++++++++++++++++--------------- include/linux/lsm_hooks.h | 4 +- include/linux/security.h | 3 + kernel/bpf/bpf_lsm.c | 10 +- security/apparmor/lsm.c | 24 +- security/bpf/hooks.c | 2 +- security/lsm_init.c | 66 ++++ security/security.c | 21 +- security/selinux/hooks.c | 35 +- security/selinux/ss/services.c | 3 + security/smack/smack_lsm.c | 6 +- security/smack/smack_netfilter.c | 6 + 13 files changed, 473 insertions(+), 323 deletions(-) -- 2.52.0 ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 1/3] LSM: add a flags field to the LSM hook definitions 2026-02-25 19:21 ` [RFC PATCH 0/3] LSM: Hook registration exculsivity Casey Schaufler @ 2026-02-25 19:21 ` Casey Schaufler 2026-04-24 1:19 ` [PATCH RFC " Paul Moore 2026-02-25 19:21 ` [RFC PATCH 2/3] LSM: Enforce exclusive hooks Casey Schaufler 2026-02-25 19:21 ` [RFC PATCH 3/3] LSM: Reserve use of secmarks Casey Schaufler 2 siblings, 1 reply; 11+ messages in thread From: Casey Schaufler @ 2026-02-25 19:21 UTC (permalink / raw) To: casey, paul, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux Add a field for flags to the definition of LSM hooks. This allows for hooks to be identified at system initialization for special processing. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/bpf_lsm.h | 2 +- include/linux/lsm_hook_defs.h | 614 ++++++++++++++++++---------------- include/linux/lsm_hooks.h | 4 +- kernel/bpf/bpf_lsm.c | 10 +- security/bpf/hooks.c | 2 +- security/security.c | 6 +- 6 files changed, 331 insertions(+), 307 deletions(-) diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h index 643809cc78c3..d71ba8c87e79 100644 --- a/include/linux/bpf_lsm.h +++ b/include/linux/bpf_lsm.h @@ -14,7 +14,7 @@ #ifdef CONFIG_BPF_LSM -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ RET bpf_lsm_##NAME(__VA_ARGS__); #include <linux/lsm_hook_defs.h> #undef LSM_HOOK diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 8c42b4bde09c..acda3a02da97 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -18,451 +18,475 @@ * The macro LSM_HOOK is used to define the data structures required by * the LSM framework using the pattern: * - * LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...) + * LSM_HOOK(<return_type>, <default_value>, <flags>, <single>, + * <hook_name>, args...) * * struct security_hook_heads { - * #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; + * #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) struct hlist_head NAME; * #include <linux/lsm_hook_defs.h> * #undef LSM_HOOK * }; */ -LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) -LSM_HOOK(int, 0, binder_transaction, const struct cred *from, +LSM_HOOK(int, 0, 0, binder_set_context_mgr, const struct cred *mgr) +LSM_HOOK(int, 0, 0, binder_transaction, const struct cred *from, const struct cred *to) -LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from, +LSM_HOOK(int, 0, 0, binder_transfer_binder, const struct cred *from, const struct cred *to) -LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from, +LSM_HOOK(int, 0, 0, binder_transfer_file, const struct cred *from, const struct cred *to, const struct file *file) -LSM_HOOK(int, 0, ptrace_access_check, struct task_struct *child, +LSM_HOOK(int, 0, 0, ptrace_access_check, struct task_struct *child, unsigned int mode) -LSM_HOOK(int, 0, ptrace_traceme, struct task_struct *parent) -LSM_HOOK(int, 0, capget, const struct task_struct *target, kernel_cap_t *effective, - kernel_cap_t *inheritable, kernel_cap_t *permitted) -LSM_HOOK(int, 0, capset, struct cred *new, const struct cred *old, +LSM_HOOK(int, 0, 0, ptrace_traceme, struct task_struct *parent) +LSM_HOOK(int, 0, 0, capget, const struct task_struct *target, + kernel_cap_t *effective, kernel_cap_t *inheritable, + kernel_cap_t *permitted) +LSM_HOOK(int, 0, 0, capset, struct cred *new, const struct cred *old, const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) -LSM_HOOK(int, 0, capable, const struct cred *cred, struct user_namespace *ns, - int cap, unsigned int opts) -LSM_HOOK(int, 0, quotactl, int cmds, int type, int id, const struct super_block *sb) -LSM_HOOK(int, 0, quota_on, struct dentry *dentry) -LSM_HOOK(int, 0, syslog, int type) -LSM_HOOK(int, 0, settime, const struct timespec64 *ts, +LSM_HOOK(int, 0, 0, capable, const struct cred *cred, + struct user_namespace *ns, int cap, unsigned int opts) +LSM_HOOK(int, 0, 0, quotactl, int cmds, int type, int id, + const struct super_block *sb) +LSM_HOOK(int, 0, 0, quota_on, struct dentry *dentry) +LSM_HOOK(int, 0, 0, syslog, int type) +LSM_HOOK(int, 0, 0, settime, const struct timespec64 *ts, const struct timezone *tz) -LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages) -LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm) -LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, const struct file *file) -LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm) -LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, const struct linux_binprm *bprm) -LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, const struct linux_binprm *bprm) -LSM_HOOK(int, 0, fs_context_submount, struct fs_context *fc, struct super_block *reference) -LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc, +LSM_HOOK(int, 0, 0, vm_enough_memory, struct mm_struct *mm, long pages) +LSM_HOOK(int, 0, 0, bprm_creds_for_exec, struct linux_binprm *bprm) +LSM_HOOK(int, 0, 0, bprm_creds_from_file, struct linux_binprm *bprm, + const struct file *file) +LSM_HOOK(int, 0, 0, bprm_check_security, struct linux_binprm *bprm) +LSM_HOOK(void, LSM_RET_VOID, 0, bprm_committing_creds, + const struct linux_binprm *bprm) +LSM_HOOK(void, LSM_RET_VOID, 0, bprm_committed_creds, + const struct linux_binprm *bprm) +LSM_HOOK(int, 0, 0, fs_context_submount, struct fs_context *fc, + struct super_block *reference) +LSM_HOOK(int, 0, 0, fs_context_dup, struct fs_context *fc, struct fs_context *src_sc) -LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc, +LSM_HOOK(int, -ENOPARAM, 0, fs_context_parse_param, struct fs_context *fc, struct fs_parameter *param) -LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb) -LSM_HOOK(void, LSM_RET_VOID, sb_delete, struct super_block *sb) -LSM_HOOK(void, LSM_RET_VOID, sb_free_security, struct super_block *sb) -LSM_HOOK(void, LSM_RET_VOID, sb_free_mnt_opts, void *mnt_opts) -LSM_HOOK(int, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts) -LSM_HOOK(int, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) -LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts) -LSM_HOOK(int, 0, sb_kern_mount, const struct super_block *sb) -LSM_HOOK(int, 0, sb_show_options, struct seq_file *m, struct super_block *sb) -LSM_HOOK(int, 0, sb_statfs, struct dentry *dentry) -LSM_HOOK(int, 0, sb_mount, const char *dev_name, const struct path *path, +LSM_HOOK(int, 0, 0, sb_alloc_security, struct super_block *sb) +LSM_HOOK(void, LSM_RET_VOID, 0, sb_delete, struct super_block *sb) +LSM_HOOK(void, LSM_RET_VOID, 0, sb_free_security, struct super_block *sb) +LSM_HOOK(void, LSM_RET_VOID, 0, sb_free_mnt_opts, void *mnt_opts) +LSM_HOOK(int, 0, 0, sb_eat_lsm_opts, char *orig, void **mnt_opts) +LSM_HOOK(int, 0, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, 0, 0, sb_remount, struct super_block *sb, void *mnt_opts) +LSM_HOOK(int, 0, 0, sb_kern_mount, const struct super_block *sb) +LSM_HOOK(int, 0, 0, sb_show_options, struct seq_file *m, struct super_block *sb) +LSM_HOOK(int, 0, 0, sb_statfs, struct dentry *dentry) +LSM_HOOK(int, 0, 0, sb_mount, const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) -LSM_HOOK(int, 0, sb_umount, struct vfsmount *mnt, int flags) -LSM_HOOK(int, 0, sb_pivotroot, const struct path *old_path, +LSM_HOOK(int, 0, 0, sb_umount, struct vfsmount *mnt, int flags) +LSM_HOOK(int, 0, 0, sb_pivotroot, const struct path *old_path, const struct path *new_path) -LSM_HOOK(int, 0, sb_set_mnt_opts, struct super_block *sb, void *mnt_opts, +LSM_HOOK(int, 0, 0, sb_set_mnt_opts, struct super_block *sb, void *mnt_opts, unsigned long kern_flags, unsigned long *set_kern_flags) -LSM_HOOK(int, 0, sb_clone_mnt_opts, const struct super_block *oldsb, +LSM_HOOK(int, 0, 0, sb_clone_mnt_opts, const struct super_block *oldsb, struct super_block *newsb, unsigned long kern_flags, unsigned long *set_kern_flags) -LSM_HOOK(int, 0, move_mount, const struct path *from_path, +LSM_HOOK(int, 0, 0, move_mount, const struct path *from_path, const struct path *to_path) -LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry, +LSM_HOOK(int, -EOPNOTSUPP, 0, dentry_init_security, struct dentry *dentry, int mode, const struct qstr *name, const char **xattr_name, struct lsm_context *cp) -LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode, +LSM_HOOK(int, 0, 0, dentry_create_files_as, struct dentry *dentry, int mode, const struct qstr *name, const struct cred *old, struct cred *new) #ifdef CONFIG_SECURITY_PATH -LSM_HOOK(int, 0, path_unlink, const struct path *dir, struct dentry *dentry) -LSM_HOOK(int, 0, path_mkdir, const struct path *dir, struct dentry *dentry, +LSM_HOOK(int, 0, 0, path_unlink, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, 0, 0, path_mkdir, const struct path *dir, struct dentry *dentry, umode_t mode) -LSM_HOOK(int, 0, path_rmdir, const struct path *dir, struct dentry *dentry) -LSM_HOOK(int, 0, path_mknod, const struct path *dir, struct dentry *dentry, +LSM_HOOK(int, 0, 0, path_rmdir, const struct path *dir, struct dentry *dentry) +LSM_HOOK(int, 0, 0, path_mknod, const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) -LSM_HOOK(void, LSM_RET_VOID, path_post_mknod, struct mnt_idmap *idmap, +LSM_HOOK(void, LSM_RET_VOID, 0, path_post_mknod, struct mnt_idmap *idmap, struct dentry *dentry) -LSM_HOOK(int, 0, path_truncate, const struct path *path) -LSM_HOOK(int, 0, path_symlink, const struct path *dir, struct dentry *dentry, - const char *old_name) -LSM_HOOK(int, 0, path_link, struct dentry *old_dentry, +LSM_HOOK(int, 0, 0, path_truncate, const struct path *path) +LSM_HOOK(int, 0, 0, path_symlink, const struct path *dir, + struct dentry *dentry, const char *old_name) +LSM_HOOK(int, 0, 0, path_link, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) -LSM_HOOK(int, 0, path_rename, const struct path *old_dir, +LSM_HOOK(int, 0, 0, path_rename, const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry, unsigned int flags) -LSM_HOOK(int, 0, path_chmod, const struct path *path, umode_t mode) -LSM_HOOK(int, 0, path_chown, const struct path *path, kuid_t uid, kgid_t gid) -LSM_HOOK(int, 0, path_chroot, const struct path *path) +LSM_HOOK(int, 0, 0, path_chmod, const struct path *path, umode_t mode) +LSM_HOOK(int, 0, 0, path_chown, const struct path *path, kuid_t uid, kgid_t gid) +LSM_HOOK(int, 0, 0, path_chroot, const struct path *path) #endif /* CONFIG_SECURITY_PATH */ /* Needed for inode based security check */ -LSM_HOOK(int, 0, path_notify, const struct path *path, u64 mask, +LSM_HOOK(int, 0, 0, path_notify, const struct path *path, u64 mask, unsigned int obj_type) -LSM_HOOK(int, 0, inode_alloc_security, struct inode *inode) -LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode) -LSM_HOOK(void, LSM_RET_VOID, inode_free_security_rcu, void *inode_security) -LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode, +LSM_HOOK(int, 0, 0, inode_alloc_security, struct inode *inode) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_free_security, struct inode *inode) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_free_security_rcu, void *inode_security) +LSM_HOOK(int, -EOPNOTSUPP, 0, inode_init_security, struct inode *inode, struct inode *dir, const struct qstr *qstr, struct xattr *xattrs, int *xattr_count) -LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode, +LSM_HOOK(int, 0, 0, inode_init_security_anon, struct inode *inode, const struct qstr *name, const struct inode *context_inode) -LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, 0, 0, inode_create, struct inode *dir, struct dentry *dentry, umode_t mode) -LSM_HOOK(void, LSM_RET_VOID, inode_post_create_tmpfile, struct mnt_idmap *idmap, - struct inode *inode) -LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_create_tmpfile, + struct mnt_idmap *idmap, struct inode *inode) +LSM_HOOK(int, 0, 0, inode_link, struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) -LSM_HOOK(int, 0, inode_unlink, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, 0, inode_symlink, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, 0, 0, inode_unlink, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, 0, 0, inode_symlink, struct inode *dir, struct dentry *dentry, const char *old_name) -LSM_HOOK(int, 0, inode_mkdir, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, 0, 0, inode_mkdir, struct inode *dir, struct dentry *dentry, umode_t mode) -LSM_HOOK(int, 0, inode_rmdir, struct inode *dir, struct dentry *dentry) -LSM_HOOK(int, 0, inode_mknod, struct inode *dir, struct dentry *dentry, +LSM_HOOK(int, 0, 0, inode_rmdir, struct inode *dir, struct dentry *dentry) +LSM_HOOK(int, 0, 0, inode_mknod, struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) -LSM_HOOK(int, 0, inode_rename, struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -LSM_HOOK(int, 0, inode_readlink, struct dentry *dentry) -LSM_HOOK(int, 0, inode_follow_link, struct dentry *dentry, struct inode *inode, - bool rcu) -LSM_HOOK(int, 0, inode_permission, struct inode *inode, int mask) -LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry, - struct iattr *attr) -LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_rename, struct inode *old_dir, + struct dentry *old_dentry, struct inode *new_dir, + struct dentry *new_dentry) +LSM_HOOK(int, 0, 0, inode_readlink, struct dentry *dentry) +LSM_HOOK(int, 0, 0, inode_follow_link, struct dentry *dentry, + struct inode *inode, bool rcu) +LSM_HOOK(int, 0, 0, inode_permission, struct inode *inode, int mask) +LSM_HOOK(int, 0, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_setattr, struct mnt_idmap *idmap, struct dentry *dentry, int ia_valid) -LSM_HOOK(int, 0, inode_getattr, const struct path *path) -LSM_HOOK(int, 0, inode_xattr_skipcap, const char *name) -LSM_HOOK(int, 0, inode_setxattr, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_getattr, const struct path *path) +LSM_HOOK(int, 0, 0, inode_xattr_skipcap, const char *name) +LSM_HOOK(int, 0, 0, inode_setxattr, struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(void, LSM_RET_VOID, inode_post_setxattr, struct dentry *dentry, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_setxattr, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(int, 0, inode_getxattr, struct dentry *dentry, const char *name) -LSM_HOOK(int, 0, inode_listxattr, struct dentry *dentry) -LSM_HOOK(int, 0, inode_removexattr, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_getxattr, struct dentry *dentry, const char *name) +LSM_HOOK(int, 0, 0, inode_listxattr, struct dentry *dentry) +LSM_HOOK(int, 0, 0, inode_removexattr, struct mnt_idmap *idmap, struct dentry *dentry, const char *name) -LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_removexattr, struct dentry *dentry, const char *name) -LSM_HOOK(int, 0, inode_file_setattr, struct dentry *dentry, struct file_kattr *fa) -LSM_HOOK(int, 0, inode_file_getattr, struct dentry *dentry, struct file_kattr *fa) -LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_file_setattr, struct dentry *dentry, + struct file_kattr *fa) +LSM_HOOK(int, 0, 0, inode_file_getattr, struct dentry *dentry, + struct file_kattr *fa) +LSM_HOOK(int, 0, 0, inode_set_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) -LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_set_acl, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) -LSM_HOOK(int, 0, inode_get_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_get_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(void, LSM_RET_VOID, inode_post_remove_acl, struct mnt_idmap *idmap, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_post_remove_acl, struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) -LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry) -LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap, +LSM_HOOK(int, 0, 0, inode_need_killpriv, struct dentry *dentry) +LSM_HOOK(int, 0, 0, inode_killpriv, struct mnt_idmap *idmap, struct dentry *dentry) -LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct mnt_idmap *idmap, +LSM_HOOK(int, -EOPNOTSUPP, 0, inode_getsecurity, struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc) -LSM_HOOK(int, -EOPNOTSUPP, inode_setsecurity, struct inode *inode, +LSM_HOOK(int, -EOPNOTSUPP, 0, inode_setsecurity, struct inode *inode, const char *name, const void *value, size_t size, int flags) -LSM_HOOK(int, 0, inode_listsecurity, struct inode *inode, char *buffer, +LSM_HOOK(int, 0, 0, inode_listsecurity, struct inode *inode, char *buffer, size_t buffer_size) -LSM_HOOK(void, LSM_RET_VOID, inode_getlsmprop, struct inode *inode, +LSM_HOOK(void, LSM_RET_VOID, 0, inode_getlsmprop, struct inode *inode, struct lsm_prop *prop) -LSM_HOOK(int, 0, inode_copy_up, struct dentry *src, struct cred **new) -LSM_HOOK(int, -EOPNOTSUPP, inode_copy_up_xattr, struct dentry *src, +LSM_HOOK(int, 0, 0, inode_copy_up, struct dentry *src, struct cred **new) +LSM_HOOK(int, -EOPNOTSUPP, 0, inode_copy_up_xattr, struct dentry *src, const char *name) -LSM_HOOK(int, 0, inode_setintegrity, const struct inode *inode, +LSM_HOOK(int, 0, 0, inode_setintegrity, const struct inode *inode, enum lsm_integrity_type type, const void *value, size_t size) -LSM_HOOK(int, 0, kernfs_init_security, struct kernfs_node *kn_dir, +LSM_HOOK(int, 0, 0, kernfs_init_security, struct kernfs_node *kn_dir, struct kernfs_node *kn) -LSM_HOOK(int, 0, file_permission, struct file *file, int mask) -LSM_HOOK(int, 0, file_alloc_security, struct file *file) -LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file) -LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file) -LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd, +LSM_HOOK(int, 0, 0, file_permission, struct file *file, int mask) +LSM_HOOK(int, 0, 0, file_alloc_security, struct file *file) +LSM_HOOK(void, LSM_RET_VOID, 0, file_release, struct file *file) +LSM_HOOK(void, LSM_RET_VOID, 0, file_free_security, struct file *file) +LSM_HOOK(int, 0, 0, file_ioctl, struct file *file, unsigned int cmd, unsigned long arg) -LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd, +LSM_HOOK(int, 0, 0, file_ioctl_compat, struct file *file, unsigned int cmd, unsigned long arg) -LSM_HOOK(int, 0, mmap_addr, unsigned long addr) -LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot, +LSM_HOOK(int, 0, 0, mmap_addr, unsigned long addr) +LSM_HOOK(int, 0, 0, mmap_file, struct file *file, unsigned long reqprot, unsigned long prot, unsigned long flags) -LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma, +LSM_HOOK(int, 0, 0, file_mprotect, struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) -LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd) -LSM_HOOK(int, 0, file_fcntl, struct file *file, unsigned int cmd, +LSM_HOOK(int, 0, 0, file_lock, struct file *file, unsigned int cmd) +LSM_HOOK(int, 0, 0, file_fcntl, struct file *file, unsigned int cmd, unsigned long arg) -LSM_HOOK(void, LSM_RET_VOID, file_set_fowner, struct file *file) -LSM_HOOK(int, 0, file_send_sigiotask, struct task_struct *tsk, +LSM_HOOK(void, LSM_RET_VOID, 0, file_set_fowner, struct file *file) +LSM_HOOK(int, 0, 0, file_send_sigiotask, struct task_struct *tsk, struct fown_struct *fown, int sig) -LSM_HOOK(int, 0, file_receive, struct file *file) -LSM_HOOK(int, 0, file_open, struct file *file) -LSM_HOOK(int, 0, file_post_open, struct file *file, int mask) -LSM_HOOK(int, 0, file_truncate, struct file *file) -LSM_HOOK(int, 0, task_alloc, struct task_struct *task, - u64 clone_flags) -LSM_HOOK(void, LSM_RET_VOID, task_free, struct task_struct *task) -LSM_HOOK(int, 0, cred_alloc_blank, struct cred *cred, gfp_t gfp) -LSM_HOOK(void, LSM_RET_VOID, cred_free, struct cred *cred) -LSM_HOOK(int, 0, cred_prepare, struct cred *new, const struct cred *old, +LSM_HOOK(int, 0, 0, file_receive, struct file *file) +LSM_HOOK(int, 0, 0, file_open, struct file *file) +LSM_HOOK(int, 0, 0, file_post_open, struct file *file, int mask) +LSM_HOOK(int, 0, 0, file_truncate, struct file *file) +LSM_HOOK(int, 0, 0, task_alloc, struct task_struct *task, u64 clone_flags) +LSM_HOOK(void, LSM_RET_VOID, 0, task_free, struct task_struct *task) +LSM_HOOK(int, 0, 0, cred_alloc_blank, struct cred *cred, gfp_t gfp) +LSM_HOOK(void, LSM_RET_VOID, 0, cred_free, struct cred *cred) +LSM_HOOK(int, 0, 0, cred_prepare, struct cred *new, const struct cred *old, gfp_t gfp) -LSM_HOOK(void, LSM_RET_VOID, cred_transfer, struct cred *new, +LSM_HOOK(void, LSM_RET_VOID, 0, cred_transfer, struct cred *new, const struct cred *old) -LSM_HOOK(void, LSM_RET_VOID, cred_getsecid, const struct cred *c, u32 *secid) -LSM_HOOK(void, LSM_RET_VOID, cred_getlsmprop, const struct cred *c, +LSM_HOOK(void, LSM_RET_VOID, 0, cred_getsecid, const struct cred *c, u32 *secid) +LSM_HOOK(void, LSM_RET_VOID, 0, cred_getlsmprop, const struct cred *c, struct lsm_prop *prop) -LSM_HOOK(int, 0, kernel_act_as, struct cred *new, u32 secid) -LSM_HOOK(int, 0, kernel_create_files_as, struct cred *new, struct inode *inode) -LSM_HOOK(int, 0, kernel_module_request, char *kmod_name) -LSM_HOOK(int, 0, kernel_load_data, enum kernel_load_data_id id, bool contents) -LSM_HOOK(int, 0, kernel_post_load_data, char *buf, loff_t size, +LSM_HOOK(int, 0, 0, kernel_act_as, struct cred *new, u32 secid) +LSM_HOOK(int, 0, 0, kernel_create_files_as, struct cred *new, + struct inode *inode) +LSM_HOOK(int, 0, 0, kernel_module_request, char *kmod_name) +LSM_HOOK(int, 0, 0, kernel_load_data, enum kernel_load_data_id id, + bool contents) +LSM_HOOK(int, 0, 0, kernel_post_load_data, char *buf, loff_t size, enum kernel_load_data_id id, char *description) -LSM_HOOK(int, 0, kernel_read_file, struct file *file, +LSM_HOOK(int, 0, 0, kernel_read_file, struct file *file, enum kernel_read_file_id id, bool contents) -LSM_HOOK(int, 0, kernel_post_read_file, struct file *file, char *buf, +LSM_HOOK(int, 0, 0, kernel_post_read_file, struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) -LSM_HOOK(int, 0, task_fix_setuid, struct cred *new, const struct cred *old, +LSM_HOOK(int, 0, 0, task_fix_setuid, struct cred *new, const struct cred *old, int flags) -LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old, +LSM_HOOK(int, 0, 0, task_fix_setgid, struct cred *new, const struct cred *old, int flags) -LSM_HOOK(int, 0, task_fix_setgroups, struct cred *new, const struct cred * old) -LSM_HOOK(int, 0, task_setpgid, struct task_struct *p, pid_t pgid) -LSM_HOOK(int, 0, task_getpgid, struct task_struct *p) -LSM_HOOK(int, 0, task_getsid, struct task_struct *p) -LSM_HOOK(void, LSM_RET_VOID, current_getlsmprop_subj, struct lsm_prop *prop) -LSM_HOOK(void, LSM_RET_VOID, task_getlsmprop_obj, - struct task_struct *p, struct lsm_prop *prop) -LSM_HOOK(int, 0, task_setnice, struct task_struct *p, int nice) -LSM_HOOK(int, 0, task_setioprio, struct task_struct *p, int ioprio) -LSM_HOOK(int, 0, task_getioprio, struct task_struct *p) -LSM_HOOK(int, 0, task_prlimit, const struct cred *cred, +LSM_HOOK(int, 0, 0, task_fix_setgroups, struct cred *new, + const struct cred *old) +LSM_HOOK(int, 0, 0, task_setpgid, struct task_struct *p, pid_t pgid) +LSM_HOOK(int, 0, 0, task_getpgid, struct task_struct *p) +LSM_HOOK(int, 0, 0, task_getsid, struct task_struct *p) +LSM_HOOK(void, LSM_RET_VOID, 0, current_getlsmprop_subj, struct lsm_prop *prop) +LSM_HOOK(void, LSM_RET_VOID, 0, task_getlsmprop_obj, struct task_struct *p, + struct lsm_prop *prop) +LSM_HOOK(int, 0, 0, task_setnice, struct task_struct *p, int nice) +LSM_HOOK(int, 0, 0, task_setioprio, struct task_struct *p, int ioprio) +LSM_HOOK(int, 0, 0, task_getioprio, struct task_struct *p) +LSM_HOOK(int, 0, 0, task_prlimit, const struct cred *cred, const struct cred *tcred, unsigned int flags) -LSM_HOOK(int, 0, task_setrlimit, struct task_struct *p, unsigned int resource, - struct rlimit *new_rlim) -LSM_HOOK(int, 0, task_setscheduler, struct task_struct *p) -LSM_HOOK(int, 0, task_getscheduler, struct task_struct *p) -LSM_HOOK(int, 0, task_movememory, struct task_struct *p) -LSM_HOOK(int, 0, task_kill, struct task_struct *p, struct kernel_siginfo *info, - int sig, const struct cred *cred) -LSM_HOOK(int, -ENOSYS, task_prctl, int option, unsigned long arg2, +LSM_HOOK(int, 0, 0, task_setrlimit, struct task_struct *p, + unsigned int resource, struct rlimit *new_rlim) +LSM_HOOK(int, 0, 0, task_setscheduler, struct task_struct *p) +LSM_HOOK(int, 0, 0, task_getscheduler, struct task_struct *p) +LSM_HOOK(int, 0, 0, task_movememory, struct task_struct *p) +LSM_HOOK(int, 0, 0, task_kill, struct task_struct *p, + struct kernel_siginfo *info, int sig, const struct cred *cred) +LSM_HOOK(int, -ENOSYS, 0, task_prctl, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) -LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p, +LSM_HOOK(void, LSM_RET_VOID, 0, task_to_inode, struct task_struct *p, struct inode *inode) -LSM_HOOK(int, 0, userns_create, const struct cred *cred) -LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag) -LSM_HOOK(void, LSM_RET_VOID, ipc_getlsmprop, struct kern_ipc_perm *ipcp, +LSM_HOOK(int, 0, 0, userns_create, const struct cred *cred) +LSM_HOOK(int, 0, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag) +LSM_HOOK(void, LSM_RET_VOID, 0, ipc_getlsmprop, struct kern_ipc_perm *ipcp, struct lsm_prop *prop) -LSM_HOOK(int, 0, msg_msg_alloc_security, struct msg_msg *msg) -LSM_HOOK(void, LSM_RET_VOID, msg_msg_free_security, struct msg_msg *msg) -LSM_HOOK(int, 0, msg_queue_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(void, LSM_RET_VOID, msg_queue_free_security, +LSM_HOOK(int, 0, 0, msg_msg_alloc_security, struct msg_msg *msg) +LSM_HOOK(void, LSM_RET_VOID, 0, msg_msg_free_security, struct msg_msg *msg) +LSM_HOOK(int, 0, 0, msg_queue_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(void, LSM_RET_VOID, 0, msg_queue_free_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, 0, msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) -LSM_HOOK(int, 0, msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, 0, msg_queue_msgsnd, struct kern_ipc_perm *perm, +LSM_HOOK(int, 0, 0, msg_queue_associate, struct kern_ipc_perm *perm, int msqflg) +LSM_HOOK(int, 0, 0, msg_queue_msgctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, 0, 0, msg_queue_msgsnd, struct kern_ipc_perm *perm, struct msg_msg *msg, int msqflg) -LSM_HOOK(int, 0, msg_queue_msgrcv, struct kern_ipc_perm *perm, +LSM_HOOK(int, 0, 0, msg_queue_msgrcv, struct kern_ipc_perm *perm, struct msg_msg *msg, struct task_struct *target, long type, int mode) -LSM_HOOK(int, 0, shm_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(void, LSM_RET_VOID, shm_free_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, 0, shm_associate, struct kern_ipc_perm *perm, int shmflg) -LSM_HOOK(int, 0, shm_shmctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, 0, shm_shmat, struct kern_ipc_perm *perm, char __user *shmaddr, - int shmflg) -LSM_HOOK(int, 0, sem_alloc_security, struct kern_ipc_perm *perm) -LSM_HOOK(void, LSM_RET_VOID, sem_free_security, struct kern_ipc_perm *perm) -LSM_HOOK(int, 0, sem_associate, struct kern_ipc_perm *perm, int semflg) -LSM_HOOK(int, 0, sem_semctl, struct kern_ipc_perm *perm, int cmd) -LSM_HOOK(int, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, +LSM_HOOK(int, 0, 0, shm_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(void, LSM_RET_VOID, 0, shm_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, 0, 0, shm_associate, struct kern_ipc_perm *perm, int shmflg) +LSM_HOOK(int, 0, 0, shm_shmctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, 0, 0, shm_shmat, struct kern_ipc_perm *perm, + char __user *shmaddr, int shmflg) +LSM_HOOK(int, 0, 0, sem_alloc_security, struct kern_ipc_perm *perm) +LSM_HOOK(void, LSM_RET_VOID, 0, sem_free_security, struct kern_ipc_perm *perm) +LSM_HOOK(int, 0, 0, sem_associate, struct kern_ipc_perm *perm, int semflg) +LSM_HOOK(int, 0, 0, sem_semctl, struct kern_ipc_perm *perm, int cmd) +LSM_HOOK(int, 0, 0, sem_semop, struct kern_ipc_perm *perm, struct sembuf *sops, unsigned nsops, int alter) -LSM_HOOK(int, 0, netlink_send, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(void, LSM_RET_VOID, d_instantiate, struct dentry *dentry, +LSM_HOOK(int, 0, 0, netlink_send, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(void, LSM_RET_VOID, 0, d_instantiate, struct dentry *dentry, struct inode *inode) -LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr, +LSM_HOOK(int, -EOPNOTSUPP, 0, getselfattr, unsigned int attr, struct lsm_ctx __user *ctx, u32 *size, u32 flags) -LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr, +LSM_HOOK(int, -EOPNOTSUPP, 0, setselfattr, unsigned int attr, struct lsm_ctx *ctx, u32 size, u32 flags) -LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name, +LSM_HOOK(int, -EINVAL, 0, getprocattr, struct task_struct *p, const char *name, char **value) -LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size) -LSM_HOOK(int, 0, ismaclabel, const char *name) -LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, struct lsm_context *cp) -LSM_HOOK(int, -EOPNOTSUPP, lsmprop_to_secctx, struct lsm_prop *prop, +LSM_HOOK(int, -EINVAL, 0, setprocattr, const char *name, void *value, + size_t size) +LSM_HOOK(int, 0, 0, ismaclabel, const char *name) +LSM_HOOK(int, -EOPNOTSUPP, 0, secid_to_secctx, u32 secid, + struct lsm_context *cp) +LSM_HOOK(int, -EOPNOTSUPP, 0, lsmprop_to_secctx, struct lsm_prop *prop, struct lsm_context *cp) -LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid) -LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp) -LSM_HOOK(void, LSM_RET_VOID, inode_invalidate_secctx, struct inode *inode) -LSM_HOOK(int, 0, inode_notifysecctx, struct inode *inode, void *ctx, u32 ctxlen) -LSM_HOOK(int, 0, inode_setsecctx, struct dentry *dentry, void *ctx, u32 ctxlen) -LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode, +LSM_HOOK(int, 0, 0, secctx_to_secid, const char *secdata, u32 seclen, + u32 *secid) +LSM_HOOK(void, LSM_RET_VOID, 0, release_secctx, struct lsm_context *cp) +LSM_HOOK(void, LSM_RET_VOID, 0, inode_invalidate_secctx, struct inode *inode) +LSM_HOOK(int, 0, 0, inode_notifysecctx, struct inode *inode, void *ctx, + u32 ctxlen) +LSM_HOOK(int, 0, 0, inode_setsecctx, struct dentry *dentry, void *ctx, + u32 ctxlen) +LSM_HOOK(int, -EOPNOTSUPP, 0, inode_getsecctx, struct inode *inode, struct lsm_context *cp) #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE) -LSM_HOOK(int, 0, post_notification, const struct cred *w_cred, +LSM_HOOK(int, 0, 0, post_notification, const struct cred *w_cred, const struct cred *cred, struct watch_notification *n) #endif /* CONFIG_SECURITY && CONFIG_WATCH_QUEUE */ #if defined(CONFIG_SECURITY) && defined(CONFIG_KEY_NOTIFICATIONS) -LSM_HOOK(int, 0, watch_key, struct key *key) +LSM_HOOK(int, 0, 0, watch_key, struct key *key) #endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */ #ifdef CONFIG_SECURITY_NETWORK -LSM_HOOK(int, 0, unix_stream_connect, struct sock *sock, struct sock *other, +LSM_HOOK(int, 0, 0, unix_stream_connect, struct sock *sock, struct sock *other, struct sock *newsk) -LSM_HOOK(int, 0, unix_may_send, struct socket *sock, struct socket *other) -LSM_HOOK(int, 0, socket_create, int family, int type, int protocol, int kern) -LSM_HOOK(int, 0, socket_post_create, struct socket *sock, int family, int type, - int protocol, int kern) -LSM_HOOK(int, 0, socket_socketpair, struct socket *socka, struct socket *sockb) -LSM_HOOK(int, 0, socket_bind, struct socket *sock, struct sockaddr *address, - int addrlen) -LSM_HOOK(int, 0, socket_connect, struct socket *sock, struct sockaddr *address, +LSM_HOOK(int, 0, 0, unix_may_send, struct socket *sock, struct socket *other) +LSM_HOOK(int, 0, 0, socket_create, int family, int type, int protocol, + int kern) +LSM_HOOK(int, 0, 0, socket_post_create, struct socket *sock, int family, + int type, int protocol, int kern) +LSM_HOOK(int, 0, 0, socket_socketpair, struct socket *socka, + struct socket *sockb) +LSM_HOOK(int, 0, 0, socket_bind, struct socket *sock, struct sockaddr *address, int addrlen) -LSM_HOOK(int, 0, socket_listen, struct socket *sock, int backlog) -LSM_HOOK(int, 0, socket_accept, struct socket *sock, struct socket *newsock) -LSM_HOOK(int, 0, socket_sendmsg, struct socket *sock, struct msghdr *msg, +LSM_HOOK(int, 0, 0, socket_connect, struct socket *sock, + struct sockaddr *address, int addrlen) +LSM_HOOK(int, 0, 0, socket_listen, struct socket *sock, int backlog) +LSM_HOOK(int, 0, 0, socket_accept, struct socket *sock, struct socket *newsock) +LSM_HOOK(int, 0, 0, socket_sendmsg, struct socket *sock, struct msghdr *msg, int size) -LSM_HOOK(int, 0, socket_recvmsg, struct socket *sock, struct msghdr *msg, +LSM_HOOK(int, 0, 0, socket_recvmsg, struct socket *sock, struct msghdr *msg, int size, int flags) -LSM_HOOK(int, 0, socket_getsockname, struct socket *sock) -LSM_HOOK(int, 0, socket_getpeername, struct socket *sock) -LSM_HOOK(int, 0, socket_getsockopt, struct socket *sock, int level, int optname) -LSM_HOOK(int, 0, socket_setsockopt, struct socket *sock, int level, int optname) -LSM_HOOK(int, 0, socket_shutdown, struct socket *sock, int how) -LSM_HOOK(int, 0, socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, -ENOPROTOOPT, socket_getpeersec_stream, struct socket *sock, +LSM_HOOK(int, 0, 0, socket_getsockname, struct socket *sock) +LSM_HOOK(int, 0, 0, socket_getpeername, struct socket *sock) +LSM_HOOK(int, 0, 0, socket_getsockopt, struct socket *sock, int level, + int optname) +LSM_HOOK(int, 0, 0, socket_setsockopt, struct socket *sock, int level, + int optname) +LSM_HOOK(int, 0, 0, socket_shutdown, struct socket *sock, int how) +LSM_HOOK(int, 0, 0, socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb) +LSM_HOOK(int, -ENOPROTOOPT, 0, socket_getpeersec_stream, struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len) -LSM_HOOK(int, -ENOPROTOOPT, socket_getpeersec_dgram, struct socket *sock, +LSM_HOOK(int, -ENOPROTOOPT, 0, socket_getpeersec_dgram, struct socket *sock, struct sk_buff *skb, u32 *secid) -LSM_HOOK(int, 0, sk_alloc_security, struct sock *sk, int family, gfp_t priority) -LSM_HOOK(void, LSM_RET_VOID, sk_free_security, struct sock *sk) -LSM_HOOK(void, LSM_RET_VOID, sk_clone_security, const struct sock *sk, +LSM_HOOK(int, 0, 0, sk_alloc_security, struct sock *sk, int family, + gfp_t priority) +LSM_HOOK(void, LSM_RET_VOID, 0, sk_free_security, struct sock *sk) +LSM_HOOK(void, LSM_RET_VOID, 0, sk_clone_security, const struct sock *sk, struct sock *newsk) -LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, const struct sock *sk, u32 *secid) -LSM_HOOK(void, LSM_RET_VOID, sock_graft, struct sock *sk, struct socket *parent) -LSM_HOOK(int, 0, inet_conn_request, const struct sock *sk, struct sk_buff *skb, - struct request_sock *req) -LSM_HOOK(void, LSM_RET_VOID, inet_csk_clone, struct sock *newsk, +LSM_HOOK(void, LSM_RET_VOID, 0, sk_getsecid, const struct sock *sk, u32 *secid) +LSM_HOOK(void, LSM_RET_VOID, 0, sock_graft, struct sock *sk, + struct socket *parent) +LSM_HOOK(int, 0, 0, inet_conn_request, const struct sock *sk, + struct sk_buff *skb, struct request_sock *req) +LSM_HOOK(void, LSM_RET_VOID, 0, inet_csk_clone, struct sock *newsk, const struct request_sock *req) -LSM_HOOK(void, LSM_RET_VOID, inet_conn_established, struct sock *sk, +LSM_HOOK(void, LSM_RET_VOID, 0, inet_conn_established, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, 0, secmark_relabel_packet, u32 secid) -LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_inc, void) -LSM_HOOK(void, LSM_RET_VOID, secmark_refcount_dec, void) -LSM_HOOK(void, LSM_RET_VOID, req_classify_flow, const struct request_sock *req, - struct flowi_common *flic) -LSM_HOOK(int, 0, tun_dev_alloc_security, void *security) -LSM_HOOK(int, 0, tun_dev_create, void) -LSM_HOOK(int, 0, tun_dev_attach_queue, void *security) -LSM_HOOK(int, 0, tun_dev_attach, struct sock *sk, void *security) -LSM_HOOK(int, 0, tun_dev_open, void *security) -LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_association *asoc, +LSM_HOOK(int, 0, 0, secmark_relabel_packet, u32 secid) +LSM_HOOK(void, LSM_RET_VOID, 0, secmark_refcount_inc, void) +LSM_HOOK(void, LSM_RET_VOID, 0, secmark_refcount_dec, void) +LSM_HOOK(void, LSM_RET_VOID, 0, req_classify_flow, + const struct request_sock *req, struct flowi_common *flic) +LSM_HOOK(int, 0, 0, tun_dev_alloc_security, void *security) +LSM_HOOK(int, 0, 0, tun_dev_create, void) +LSM_HOOK(int, 0, 0, tun_dev_attach_queue, void *security) +LSM_HOOK(int, 0, 0, tun_dev_attach, struct sock *sk, void *security) +LSM_HOOK(int, 0, 0, tun_dev_open, void *security) +LSM_HOOK(int, 0, 0, sctp_assoc_request, struct sctp_association *asoc, struct sk_buff *skb) -LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname, +LSM_HOOK(int, 0, 0, sctp_bind_connect, struct sock *sk, int optname, struct sockaddr *address, int addrlen) -LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc, +LSM_HOOK(void, LSM_RET_VOID, 0, sctp_sk_clone, struct sctp_association *asoc, struct sock *sk, struct sock *newsk) -LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc, +LSM_HOOK(int, 0, 0, sctp_assoc_established, struct sctp_association *asoc, struct sk_buff *skb) -LSM_HOOK(int, 0, mptcp_add_subflow, struct sock *sk, struct sock *ssk) +LSM_HOOK(int, 0, 0, mptcp_add_subflow, struct sock *sk, struct sock *ssk) #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND -LSM_HOOK(int, 0, ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) -LSM_HOOK(int, 0, ib_endport_manage_subnet, void *sec, const char *dev_name, +LSM_HOOK(int, 0, 0, ib_pkey_access, void *sec, u64 subnet_prefix, u16 pkey) +LSM_HOOK(int, 0, 0, ib_endport_manage_subnet, void *sec, const char *dev_name, u8 port_num) -LSM_HOOK(int, 0, ib_alloc_security, void *sec) +LSM_HOOK(int, 0, 0, ib_alloc_security, void *sec) #endif /* CONFIG_SECURITY_INFINIBAND */ #ifdef CONFIG_SECURITY_NETWORK_XFRM -LSM_HOOK(int, 0, xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp, +LSM_HOOK(int, 0, 0, xfrm_policy_alloc_security, struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) -LSM_HOOK(int, 0, xfrm_policy_clone_security, struct xfrm_sec_ctx *old_ctx, +LSM_HOOK(int, 0, 0, xfrm_policy_clone_security, struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctx) -LSM_HOOK(void, LSM_RET_VOID, xfrm_policy_free_security, +LSM_HOOK(void, LSM_RET_VOID, 0, xfrm_policy_free_security, struct xfrm_sec_ctx *ctx) -LSM_HOOK(int, 0, xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) -LSM_HOOK(int, 0, xfrm_state_alloc, struct xfrm_state *x, +LSM_HOOK(int, 0, 0, xfrm_policy_delete_security, struct xfrm_sec_ctx *ctx) +LSM_HOOK(int, 0, 0, xfrm_state_alloc, struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) -LSM_HOOK(int, 0, xfrm_state_alloc_acquire, struct xfrm_state *x, - struct xfrm_sec_ctx *polsec, u32 secid) -LSM_HOOK(void, LSM_RET_VOID, xfrm_state_free_security, struct xfrm_state *x) -LSM_HOOK(int, 0, xfrm_state_delete_security, struct xfrm_state *x) -LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid) -LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x, +LSM_HOOK(int, 0, 0, xfrm_state_alloc_acquire, + struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) +LSM_HOOK(void, LSM_RET_VOID, 0, xfrm_state_free_security, struct xfrm_state *x) +LSM_HOOK(int, 0, 0, xfrm_state_delete_security, struct xfrm_state *x) +LSM_HOOK(int, 0, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid) +LSM_HOOK(int, 1, 0, xfrm_state_pol_flow_match, struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi_common *flic) -LSM_HOOK(int, 0, xfrm_decode_session, struct sk_buff *skb, u32 *secid, +LSM_HOOK(int, 0, 0, xfrm_decode_session, struct sk_buff *skb, u32 *secid, int ckall) #endif /* CONFIG_SECURITY_NETWORK_XFRM */ /* key management security hooks */ #ifdef CONFIG_KEYS -LSM_HOOK(int, 0, key_alloc, struct key *key, const struct cred *cred, +LSM_HOOK(int, 0, 0, key_alloc, struct key *key, const struct cred *cred, unsigned long flags) -LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred, - enum key_need_perm need_perm) -LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer) -LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring, +LSM_HOOK(int, 0, 0, key_permission, key_ref_t key_ref, + const struct cred *cred, enum key_need_perm need_perm) +LSM_HOOK(int, 0, 0, key_getsecurity, struct key *key, char **buffer) +LSM_HOOK(void, LSM_RET_VOID, 0, key_post_create_or_update, struct key *keyring, struct key *key, const void *payload, size_t payload_len, unsigned long flags, bool create) #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT -LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr, +LSM_HOOK(int, 0, 0, audit_rule_init, u32 field, u32 op, char *rulestr, void **lsmrule, gfp_t gfp) -LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule) -LSM_HOOK(int, 0, audit_rule_match, struct lsm_prop *prop, u32 field, u32 op, +LSM_HOOK(int, 0, 0, audit_rule_known, struct audit_krule *krule) +LSM_HOOK(int, 0, 0, audit_rule_match, struct lsm_prop *prop, u32 field, u32 op, void *lsmrule) -LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule) +LSM_HOOK(void, LSM_RET_VOID, 0, audit_rule_free, void *lsmrule) #endif /* CONFIG_AUDIT */ #ifdef CONFIG_BPF_SYSCALL -LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel) -LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode) -LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog) -LSM_HOOK(int, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr, - struct bpf_token *token, bool kernel) -LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map) -LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr, +LSM_HOOK(int, 0, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size, + bool kernel) +LSM_HOOK(int, 0, 0, bpf_map, struct bpf_map *map, fmode_t fmode) +LSM_HOOK(int, 0, 0, bpf_prog, struct bpf_prog *prog) +LSM_HOOK(int, 0, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr, struct bpf_token *token, bool kernel) -LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog) -LSM_HOOK(int, 0, bpf_token_create, struct bpf_token *token, union bpf_attr *attr, - const struct path *path) -LSM_HOOK(void, LSM_RET_VOID, bpf_token_free, struct bpf_token *token) -LSM_HOOK(int, 0, bpf_token_cmd, const struct bpf_token *token, enum bpf_cmd cmd) -LSM_HOOK(int, 0, bpf_token_capable, const struct bpf_token *token, int cap) +LSM_HOOK(void, LSM_RET_VOID, 0, bpf_map_free, struct bpf_map *map) +LSM_HOOK(int, 0, 0, bpf_prog_load, struct bpf_prog *prog, + union bpf_attr *attr, struct bpf_token *token, bool kernel) +LSM_HOOK(void, LSM_RET_VOID, 0, bpf_prog_free, struct bpf_prog *prog) +LSM_HOOK(int, 0, 0, bpf_token_create, struct bpf_token *token, + union bpf_attr *attr, const struct path *path) +LSM_HOOK(void, LSM_RET_VOID, 0, bpf_token_free, struct bpf_token *token) +LSM_HOOK(int, 0, 0, bpf_token_cmd, const struct bpf_token *token, + enum bpf_cmd cmd) +LSM_HOOK(int, 0, 0, bpf_token_capable, const struct bpf_token *token, int cap) #endif /* CONFIG_BPF_SYSCALL */ -LSM_HOOK(int, 0, locked_down, enum lockdown_reason what) +LSM_HOOK(int, 0, 0, locked_down, enum lockdown_reason what) #ifdef CONFIG_PERF_EVENTS -LSM_HOOK(int, 0, perf_event_open, int type) -LSM_HOOK(int, 0, perf_event_alloc, struct perf_event *event) -LSM_HOOK(int, 0, perf_event_read, struct perf_event *event) -LSM_HOOK(int, 0, perf_event_write, struct perf_event *event) +LSM_HOOK(int, 0, 0, perf_event_open, int type) +LSM_HOOK(int, 0, 0, perf_event_alloc, struct perf_event *event) +LSM_HOOK(int, 0, 0, perf_event_read, struct perf_event *event) +LSM_HOOK(int, 0, 0, perf_event_write, struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ #ifdef CONFIG_IO_URING -LSM_HOOK(int, 0, uring_override_creds, const struct cred *new) -LSM_HOOK(int, 0, uring_sqpoll, void) -LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd) -LSM_HOOK(int, 0, uring_allowed, void) +LSM_HOOK(int, 0, 0, uring_override_creds, const struct cred *new) +LSM_HOOK(int, 0, 0, uring_sqpoll, void) +LSM_HOOK(int, 0, 0, uring_cmd, struct io_uring_cmd *ioucmd) +LSM_HOOK(int, 0, 0, uring_allowed, void) #endif /* CONFIG_IO_URING */ -LSM_HOOK(void, LSM_RET_VOID, initramfs_populated, void) +LSM_HOOK(void, LSM_RET_VOID, 0, initramfs_populated, void) -LSM_HOOK(int, 0, bdev_alloc_security, struct block_device *bdev) -LSM_HOOK(void, LSM_RET_VOID, bdev_free_security, struct block_device *bdev) -LSM_HOOK(int, 0, bdev_setintegrity, struct block_device *bdev, +LSM_HOOK(int, 0, 0, bdev_alloc_security, struct block_device *bdev) +LSM_HOOK(void, LSM_RET_VOID, 0, bdev_free_security, struct block_device *bdev) +LSM_HOOK(int, 0, 0, bdev_setintegrity, struct block_device *bdev, enum lsm_integrity_type type, const void *value, size_t size) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index b92008641242..4411b47f9a8d 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -36,7 +36,7 @@ #include <linux/lsm_count.h> union security_list_options { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); + #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) RET (*NAME)(__VA_ARGS__); #include "lsm_hook_defs.h" #undef LSM_HOOK void *lsm_func_addr; @@ -65,7 +65,7 @@ struct lsm_static_call { * dynamic to adapt the number of static calls to the number of callbacks. */ struct lsm_static_calls_table { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ struct lsm_static_call NAME[MAX_LSM_COUNT]; #include <linux/lsm_hook_defs.h> #undef LSM_HOOK diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c index 7cb6e8d4282c..53d5c0b69b2c 100644 --- a/kernel/bpf/bpf_lsm.c +++ b/kernel/bpf/bpf_lsm.c @@ -20,16 +20,16 @@ /* For every LSM hook that allows attachment of BPF programs, declare a nop * function where a BPF program can be attached. */ -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ -noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ -{ \ - return DEFAULT; \ +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ +noinline RET bpf_lsm_##NAME(__VA_ARGS__) \ +{ \ + return DEFAULT; \ } #include <linux/lsm_hook_defs.h> #undef LSM_HOOK -#define LSM_HOOK(RET, DEFAULT, NAME, ...) BTF_ID(func, bpf_lsm_##NAME) +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) BTF_ID(func, bpf_lsm_##NAME) BTF_SET_START(bpf_lsm_hooks) #include <linux/lsm_hook_defs.h> #undef LSM_HOOK diff --git a/security/bpf/hooks.c b/security/bpf/hooks.c index 40efde233f3a..8c4b0ed2b22e 100644 --- a/security/bpf/hooks.c +++ b/security/bpf/hooks.c @@ -8,7 +8,7 @@ #include <uapi/linux/lsm.h> static struct security_hook_list bpf_lsm_hooks[] __ro_after_init = { - #define LSM_HOOK(RET, DEFAULT, NAME, ...) \ + #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ LSM_HOOK_INIT(NAME, bpf_lsm_##NAME), #include <linux/lsm_hook_defs.h> #undef LSM_HOOK diff --git a/security/security.c b/security/security.c index 31a688650601..25e7cfc96f20 100644 --- a/security/security.c +++ b/security/security.c @@ -117,7 +117,7 @@ do { \ *((RET(*)(__VA_ARGS__))NULL)); \ DEFINE_STATIC_KEY_FALSE(SECURITY_HOOK_ACTIVE_KEY(NAME, NUM)); -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ LSM_DEFINE_UNROLL(DEFINE_LSM_STATIC_CALL, NAME, RET, __VA_ARGS__) #include <linux/lsm_hook_defs.h> #undef LSM_HOOK @@ -142,7 +142,7 @@ struct lsm_static_calls_table .trampoline = LSM_HOOK_TRAMP(NAME, NUM), \ .active = &SECURITY_HOOK_ACTIVE_KEY(NAME, NUM), \ }, -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ .NAME = { \ LSM_DEFINE_UNROLL(INIT_LSM_STATIC_CALL, NAME) \ }, @@ -422,7 +422,7 @@ int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len, #define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME) #define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \ static const int __maybe_unused LSM_RET_DEFAULT(NAME) = (DEFAULT); -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ DECLARE_LSM_RET_DEFAULT_##RET(DEFAULT, NAME) #include <linux/lsm_hook_defs.h> -- 2.52.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 1/3] LSM: add a flags field to the LSM hook definitions 2026-02-25 19:21 ` [RFC PATCH 1/3] LSM: add a flags field to the LSM hook definitions Casey Schaufler @ 2026-04-24 1:19 ` Paul Moore 2026-04-24 15:24 ` Casey Schaufler 0 siblings, 1 reply; 11+ messages in thread From: Paul Moore @ 2026-04-24 1:19 UTC (permalink / raw) To: Casey Schaufler, casey, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: > > Add a field for flags to the definition of LSM hooks. This allows > for hooks to be identified at system initialization for special > processing. > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> > --- > include/linux/bpf_lsm.h | 2 +- > include/linux/lsm_hook_defs.h | 614 ++++++++++++++++++---------------- > include/linux/lsm_hooks.h | 4 +- > kernel/bpf/bpf_lsm.c | 10 +- > security/bpf/hooks.c | 2 +- > security/security.c | 6 +- > 6 files changed, 331 insertions(+), 307 deletions(-) > > diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h > index 643809cc78c3..d71ba8c87e79 100644 > --- a/include/linux/bpf_lsm.h > +++ b/include/linux/bpf_lsm.h > @@ -14,7 +14,7 @@ > > #ifdef CONFIG_BPF_LSM > > -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ > +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ > RET bpf_lsm_##NAME(__VA_ARGS__); > #include <linux/lsm_hook_defs.h> > #undef LSM_HOOK > diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > index 8c42b4bde09c..acda3a02da97 100644 > --- a/include/linux/lsm_hook_defs.h > +++ b/include/linux/lsm_hook_defs.h > @@ -18,451 +18,475 @@ > * The macro LSM_HOOK is used to define the data structures required by > * the LSM framework using the pattern: > * > - * LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...) > + * LSM_HOOK(<return_type>, <default_value>, <flags>, <single>, > + * <hook_name>, args...) > * > * struct security_hook_heads { > - * #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; > + * #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) struct hlist_head NAME; > * #include <linux/lsm_hook_defs.h> > * #undef LSM_HOOK > * }; > */ > -LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) > -LSM_HOOK(int, 0, binder_transaction, const struct cred *from, > +LSM_HOOK(int, 0, 0, binder_set_context_mgr, const struct cred *mgr) > +LSM_HOOK(int, 0, 0, binder_transaction, const struct cred *from, > const struct cred *to) I think adding a flag field to the LSM_HOOK() macro/definitions is a good and useful addition, but I'd prefer if we created a LSM_FLAG_NONE #define and used it here just so we could avoid the back-to-back 0's and do a bit of self-documentation. -- paul-moore.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 1/3] LSM: add a flags field to the LSM hook definitions 2026-04-24 1:19 ` [PATCH RFC " Paul Moore @ 2026-04-24 15:24 ` Casey Schaufler 2026-04-24 20:29 ` Paul Moore 0 siblings, 1 reply; 11+ messages in thread From: Casey Schaufler @ 2026-04-24 15:24 UTC (permalink / raw) To: Paul Moore, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux, Casey Schaufler On 4/23/2026 6:19 PM, Paul Moore wrote: > On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: >> Add a field for flags to the definition of LSM hooks. This allows >> for hooks to be identified at system initialization for special >> processing. >> >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> >> --- >> include/linux/bpf_lsm.h | 2 +- >> include/linux/lsm_hook_defs.h | 614 ++++++++++++++++++---------------- >> include/linux/lsm_hooks.h | 4 +- >> kernel/bpf/bpf_lsm.c | 10 +- >> security/bpf/hooks.c | 2 +- >> security/security.c | 6 +- >> 6 files changed, 331 insertions(+), 307 deletions(-) >> >> diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h >> index 643809cc78c3..d71ba8c87e79 100644 >> --- a/include/linux/bpf_lsm.h >> +++ b/include/linux/bpf_lsm.h >> @@ -14,7 +14,7 @@ >> >> #ifdef CONFIG_BPF_LSM >> >> -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ >> +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ >> RET bpf_lsm_##NAME(__VA_ARGS__); >> #include <linux/lsm_hook_defs.h> >> #undef LSM_HOOK >> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h >> index 8c42b4bde09c..acda3a02da97 100644 >> --- a/include/linux/lsm_hook_defs.h >> +++ b/include/linux/lsm_hook_defs.h >> @@ -18,451 +18,475 @@ >> * The macro LSM_HOOK is used to define the data structures required by >> * the LSM framework using the pattern: >> * >> - * LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...) >> + * LSM_HOOK(<return_type>, <default_value>, <flags>, <single>, >> + * <hook_name>, args...) >> * >> * struct security_hook_heads { >> - * #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; >> + * #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) struct hlist_head NAME; >> * #include <linux/lsm_hook_defs.h> >> * #undef LSM_HOOK >> * }; >> */ >> -LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) >> -LSM_HOOK(int, 0, binder_transaction, const struct cred *from, >> +LSM_HOOK(int, 0, 0, binder_set_context_mgr, const struct cred *mgr) >> +LSM_HOOK(int, 0, 0, binder_transaction, const struct cred *from, >> const struct cred *to) > I think adding a flag field to the LSM_HOOK() macro/definitions is a good > and useful addition, but I'd prefer if we created a LSM_FLAG_NONE #define > and used it here just so we could avoid the back-to-back 0's and do a bit > of self-documentation. I had LSM_FLAG_NONE initially, but removed it when I saw the amount of code churn it introduced. I'm happy to put it back. ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 1/3] LSM: add a flags field to the LSM hook definitions 2026-04-24 15:24 ` Casey Schaufler @ 2026-04-24 20:29 ` Paul Moore 0 siblings, 0 replies; 11+ messages in thread From: Paul Moore @ 2026-04-24 20:29 UTC (permalink / raw) To: Casey Schaufler Cc: linux-security-module, jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux On Fri, Apr 24, 2026 at 11:24 AM Casey Schaufler <casey@schaufler-ca.com> wrote: > On 4/23/2026 6:19 PM, Paul Moore wrote: > > On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: > >> Add a field for flags to the definition of LSM hooks. This allows > >> for hooks to be identified at system initialization for special > >> processing. > >> > >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> > >> --- > >> include/linux/bpf_lsm.h | 2 +- > >> include/linux/lsm_hook_defs.h | 614 ++++++++++++++++++---------------- > >> include/linux/lsm_hooks.h | 4 +- > >> kernel/bpf/bpf_lsm.c | 10 +- > >> security/bpf/hooks.c | 2 +- > >> security/security.c | 6 +- > >> 6 files changed, 331 insertions(+), 307 deletions(-) > >> > >> diff --git a/include/linux/bpf_lsm.h b/include/linux/bpf_lsm.h > >> index 643809cc78c3..d71ba8c87e79 100644 > >> --- a/include/linux/bpf_lsm.h > >> +++ b/include/linux/bpf_lsm.h > >> @@ -14,7 +14,7 @@ > >> > >> #ifdef CONFIG_BPF_LSM > >> > >> -#define LSM_HOOK(RET, DEFAULT, NAME, ...) \ > >> +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ > >> RET bpf_lsm_##NAME(__VA_ARGS__); > >> #include <linux/lsm_hook_defs.h> > >> #undef LSM_HOOK > >> diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h > >> index 8c42b4bde09c..acda3a02da97 100644 > >> --- a/include/linux/lsm_hook_defs.h > >> +++ b/include/linux/lsm_hook_defs.h > >> @@ -18,451 +18,475 @@ > >> * The macro LSM_HOOK is used to define the data structures required by > >> * the LSM framework using the pattern: > >> * > >> - * LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...) > >> + * LSM_HOOK(<return_type>, <default_value>, <flags>, <single>, > >> + * <hook_name>, args...) > >> * > >> * struct security_hook_heads { > >> - * #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME; > >> + * #define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) struct hlist_head NAME; > >> * #include <linux/lsm_hook_defs.h> > >> * #undef LSM_HOOK > >> * }; > >> */ > >> -LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr) > >> -LSM_HOOK(int, 0, binder_transaction, const struct cred *from, > >> +LSM_HOOK(int, 0, 0, binder_set_context_mgr, const struct cred *mgr) > >> +LSM_HOOK(int, 0, 0, binder_transaction, const struct cred *from, > >> const struct cred *to) > > I think adding a flag field to the LSM_HOOK() macro/definitions is a good > > and useful addition, but I'd prefer if we created a LSM_FLAG_NONE #define > > and used it here just so we could avoid the back-to-back 0's and do a bit > > of self-documentation. > > I had LSM_FLAG_NONE initially, but removed it when I saw the amount of code > churn it introduced. I'm happy to put it back. You're already touching every LSM_HOOK() definition to add a another parameter, changing that parameter from 0 to LSM_FLAG_NONE shouldn't make it that much worse. -- paul-moore.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 2/3] LSM: Enforce exclusive hooks 2026-02-25 19:21 ` [RFC PATCH 0/3] LSM: Hook registration exculsivity Casey Schaufler 2026-02-25 19:21 ` [RFC PATCH 1/3] LSM: add a flags field to the LSM hook definitions Casey Schaufler @ 2026-02-25 19:21 ` Casey Schaufler 2026-04-24 1:19 ` [PATCH RFC " Paul Moore 2026-02-25 19:21 ` [RFC PATCH 3/3] LSM: Reserve use of secmarks Casey Schaufler 2 siblings, 1 reply; 11+ messages in thread From: Casey Schaufler @ 2026-02-25 19:21 UTC (permalink / raw) To: casey, paul, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux If an LSM hook is marked as exclusive via LSM_FLAG_EXCLUSIVE in lsm_hook_defs.h it will not be added to the set of hooks to be executed if an different LSM has already registered an exclusive hook. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/security.h | 2 ++ security/lsm_init.c | 66 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/include/linux/security.h b/include/linux/security.h index 83a646d72f6f..e3c137a1b30a 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -2404,4 +2404,6 @@ static inline void security_initramfs_populated(void) } #endif /* CONFIG_SECURITY */ +extern u64 lsm_exclusive_hooks; + #endif /* ! __LINUX_SECURITY_H */ diff --git a/security/lsm_init.c b/security/lsm_init.c index 05bd52e6b1f2..dc3c84387a7e 100644 --- a/security/lsm_init.c +++ b/security/lsm_init.c @@ -356,6 +356,70 @@ static int __init lsm_static_call_init(struct security_hook_list *hl) return -ENOSPC; } +/* + * Hooks that are restricted to use by a single security module. + * + * Secmark hooks have not been converted from secids to lsm_props + * due to space limitations in packet headers. + * + * Conversions from a secid to a secctx are restricted to the + * single security module. All cases where there may be multiple + * modules providing the input data have been converted to use + * a lsm_prop instead of a secid. + */ +struct lsm_exclusive { + struct lsm_static_call *name; + char *namestr; + u32 flags; +}; + +static __initdata struct lsm_exclusive lsm_exclusive_set[] = { +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ + { .name = static_calls_table.NAME, .flags = FLAGS, .namestr = "" #NAME "" , }, +#include <linux/lsm_hook_defs.h> +#undef LSM_HOOK +}; +u64 lsm_exclusive_hooks; +EXPORT_SYMBOL(lsm_exclusive_hooks); + +/** + * lsm_exclusive_hook_denial - Check if exclusive hook is in use + * @hook: the hook to check + * + * Check if the hook in question is restricted to a single using LSM, + * and if the LSM providing single LSM hooks is defined. + * + * Returns true if the hook is exclusive and they are already provided, + * false otherwise. + */ +static bool __init lsm_exclusive_hook_denial(struct security_hook_list *hook) +{ + int i; + + if (lsm_exclusive_hooks == hook->lsmid->id) + return false; + + for (i = 0; i < ARRAY_SIZE(lsm_exclusive_set); i++) { + if (!(lsm_exclusive_set[i].flags & LSM_FLAG_EXCLUSIVE)) + continue; + if (hook->scalls == lsm_exclusive_set[i].name) { + if (lsm_exclusive_hooks) { + if (lsm_debug) + lsm_pr("%s denied for %s.\n", + lsm_exclusive_set[i].namestr, + hook->lsmid->name); + return true; + } + if (lsm_debug) + lsm_pr("Exclusive hooks limited to %s.\n", + hook->lsmid->name); + lsm_exclusive_hooks = hook->lsmid->id; + break; + } + } + return false; +} + /** * security_add_hooks - Add a LSM's hooks to the LSM framework's hook lists * @hooks: LSM hooks to add @@ -371,6 +435,8 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, for (i = 0; i < count; i++) { hooks[i].lsmid = lsmid; + if (lsm_exclusive_hook_denial(&hooks[i])) + continue; if (lsm_static_call_init(&hooks[i])) panic("exhausted LSM callback slots with LSM %s\n", lsmid->name); -- 2.52.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 2/3] LSM: Enforce exclusive hooks 2026-02-25 19:21 ` [RFC PATCH 2/3] LSM: Enforce exclusive hooks Casey Schaufler @ 2026-04-24 1:19 ` Paul Moore 2026-04-25 0:39 ` Casey Schaufler 0 siblings, 1 reply; 11+ messages in thread From: Paul Moore @ 2026-04-24 1:19 UTC (permalink / raw) To: Casey Schaufler, casey, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: > > If an LSM hook is marked as exclusive via LSM_FLAG_EXCLUSIVE > in lsm_hook_defs.h it will not be added to the set of hooks to > be executed if an different LSM has already registered an > exclusive hook. > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> > --- > include/linux/security.h | 2 ++ > security/lsm_init.c | 66 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 68 insertions(+) > > diff --git a/include/linux/security.h b/include/linux/security.h > index 83a646d72f6f..e3c137a1b30a 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -2404,4 +2404,6 @@ static inline void security_initramfs_populated(void) > } > #endif /* CONFIG_SECURITY */ > > +extern u64 lsm_exclusive_hooks; We already have the 'lsm_exclusive' variable in lsm_init.c, don't create another variable that does the same thing. If the scope of the existing variable isn't what you need, change that. Although to be honest, I'm not in love with what you're doing with the variable anyway, more on that later in the review. > #endif /* ! __LINUX_SECURITY_H */ > diff --git a/security/lsm_init.c b/security/lsm_init.c > index 05bd52e6b1f2..dc3c84387a7e 100644 > --- a/security/lsm_init.c > +++ b/security/lsm_init.c > @@ -356,6 +356,70 @@ static int __init lsm_static_call_init(struct security_hook_list *hl) > return -ENOSPC; > } > > +/* > + * Hooks that are restricted to use by a single security module. > + * > + * Secmark hooks have not been converted from secids to lsm_props > + * due to space limitations in packet headers. If this is a general purpose mechanism for all types of LSM hooks, please don't put commentary in here about a single class of hook. If this only reason for doing all of this is for secmark, just fix secmark instead of going through all of this trouble. > + * Conversions from a secid to a secctx are restricted to the > + * single security module. All cases where there may be multiple > + * modules providing the input data have been converted to use > + * a lsm_prop instead of a secid. Okay, yes, the paragraph above is true, I'm just not sure why it is important here? > + */ > +struct lsm_exclusive { > + struct lsm_static_call *name; > + char *namestr; > + u32 flags; > +}; > + > +static __initdata struct lsm_exclusive lsm_exclusive_set[] = { > +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ > + { .name = static_calls_table.NAME, .flags = FLAGS, .namestr = "" #NAME "" , }, > +#include <linux/lsm_hook_defs.h> > +#undef LSM_HOOK > +}; > +u64 lsm_exclusive_hooks; > +EXPORT_SYMBOL(lsm_exclusive_hooks); Unless I missed something, we really shouldn't need to export this, why did you need EXPORT_SYMBOL() here? > +/** > + * lsm_exclusive_hook_denial - Check if exclusive hook is in use > + * @hook: the hook to check > + * > + * Check if the hook in question is restricted to a single using LSM, > + * and if the LSM providing single LSM hooks is defined. > + * > + * Returns true if the hook is exclusive and they are already provided, > + * false otherwise. > + */ > +static bool __init lsm_exclusive_hook_denial(struct security_hook_list *hook) > +{ > + int i; > + > + if (lsm_exclusive_hooks == hook->lsmid->id) > + return false; > + > + for (i = 0; i < ARRAY_SIZE(lsm_exclusive_set); i++) { > + if (!(lsm_exclusive_set[i].flags & LSM_FLAG_EXCLUSIVE)) > + continue; The logic on this looks a bit odd. What is wrong with something like the pseduo code below? for (i = 0; ARRAY_SIZE(lsm_hooks); i++) { if (lsm_hooks[i] == hook) { if (lsm_hooks[i].flags & LSM_FLAG_EXCLUSIVE) return true; else return false; } } > + if (hook->scalls == lsm_exclusive_set[i].name) { > + if (lsm_exclusive_hooks) { > + if (lsm_debug) > + lsm_pr("%s denied for %s.\n", > + lsm_exclusive_set[i].namestr, > + hook->lsmid->name); The lsm_pr_dbg() macro exists for this very reason. > + return true; > + } > + if (lsm_debug) > + lsm_pr("Exclusive hooks limited to %s.\n", > + hook->lsmid->name); Same as above. > + lsm_exclusive_hooks = hook->lsmid->id; > + break; > + } > + } > + return false; > +} > > /** > * security_add_hooks - Add a LSM's hooks to the LSM framework's hook lists > * @hooks: LSM hooks to add > @@ -371,6 +435,8 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, > > for (i = 0; i < count; i++) { > hooks[i].lsmid = lsmid; > + if (lsm_exclusive_hook_denial(&hooks[i])) > + continue; > if (lsm_static_call_init(&hooks[i])) > panic("exhausted LSM callback slots with LSM %s\n", > lsmid->name); I don't think we'd want to simply skip over a hook registration if the LSM doesn't have access to an exclusive hook. At the very least it risks unexpected behavior in the LSM and at the worst it prevents the LSM from properly enforcing it's security policy. There is a reason we have the panic() call in the existing code if we are not able to register a hook. The simpliest solution here would be to panic, like we do today. However, if you want to get fancy and enable LSMs to optionally adjust their behavior to cope with the loss of a hook callback (I'm looking at your patch 3/3 now), come up with a mechanism to report back to the LSM that one or more of the callbacks were not registered. One quick thought would be to return a non-zero error code and add an indicator/bool/flag to the security_hook_list that would be set by security_add_hooks(). -- paul-moore.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 2/3] LSM: Enforce exclusive hooks 2026-04-24 1:19 ` [PATCH RFC " Paul Moore @ 2026-04-25 0:39 ` Casey Schaufler 0 siblings, 0 replies; 11+ messages in thread From: Casey Schaufler @ 2026-04-25 0:39 UTC (permalink / raw) To: Paul Moore, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux, Casey Schaufler On 4/23/2026 6:19 PM, Paul Moore wrote: > On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: >> If an LSM hook is marked as exclusive via LSM_FLAG_EXCLUSIVE >> in lsm_hook_defs.h it will not be added to the set of hooks to >> be executed if an different LSM has already registered an >> exclusive hook. >> >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> >> --- >> include/linux/security.h | 2 ++ >> security/lsm_init.c | 66 ++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 68 insertions(+) >> >> diff --git a/include/linux/security.h b/include/linux/security.h >> index 83a646d72f6f..e3c137a1b30a 100644 >> --- a/include/linux/security.h >> +++ b/include/linux/security.h >> @@ -2404,4 +2404,6 @@ static inline void security_initramfs_populated(void) >> } >> #endif /* CONFIG_SECURITY */ >> >> +extern u64 lsm_exclusive_hooks; > We already have the 'lsm_exclusive' variable in lsm_init.c, don't create > another variable that does the same thing. If the scope of the existing > variable isn't what you need, change that. Reusing lsm_exclusive is probably doable. For the RFC it made more sense to make them separate. > Although to be honest, I'm not in love with what you're doing with the > variable anyway, more on that later in the review. > >> #endif /* ! __LINUX_SECURITY_H */ >> diff --git a/security/lsm_init.c b/security/lsm_init.c >> index 05bd52e6b1f2..dc3c84387a7e 100644 >> --- a/security/lsm_init.c >> +++ b/security/lsm_init.c >> @@ -356,6 +356,70 @@ static int __init lsm_static_call_init(struct security_hook_list *hl) >> return -ENOSPC; >> } >> >> +/* >> + * Hooks that are restricted to use by a single security module. >> + * >> + * Secmark hooks have not been converted from secids to lsm_props >> + * due to space limitations in packet headers. > If this is a general purpose mechanism for all types of LSM hooks, please > don't put commentary in here about a single class of hook. OKey Dokey. > If this only reason for doing all of this is for secmark, just fix > secmark instead of going through all of this trouble. Secmark is the bellwether for using the mechanism. >> + * Conversions from a secid to a secctx are restricted to the >> + * single security module. All cases where there may be multiple >> + * modules providing the input data have been converted to use >> + * a lsm_prop instead of a secid. > Okay, yes, the paragraph above is true, I'm just not sure why it is > important here? It's important because it addresses the objection that the secmark issue might be addressed by converting the secmark to a lsm_prop pointer. I can certainly make that clearer. >> + */ >> +struct lsm_exclusive { >> + struct lsm_static_call *name; >> + char *namestr; >> + u32 flags; >> +}; >> + >> +static __initdata struct lsm_exclusive lsm_exclusive_set[] = { >> +#define LSM_HOOK(RET, DEFAULT, FLAGS, NAME, ...) \ >> + { .name = static_calls_table.NAME, .flags = FLAGS, .namestr = "" #NAME "" , }, >> +#include <linux/lsm_hook_defs.h> >> +#undef LSM_HOOK >> +}; >> +u64 lsm_exclusive_hooks; >> +EXPORT_SYMBOL(lsm_exclusive_hooks); > Unless I missed something, we really shouldn't need to export this, why > did you need EXPORT_SYMBOL() here? No, you didn't miss anything. It's a carryover from an early experiment. >> +/** >> + * lsm_exclusive_hook_denial - Check if exclusive hook is in use >> + * @hook: the hook to check >> + * >> + * Check if the hook in question is restricted to a single using LSM, >> + * and if the LSM providing single LSM hooks is defined. >> + * >> + * Returns true if the hook is exclusive and they are already provided, >> + * false otherwise. >> + */ >> +static bool __init lsm_exclusive_hook_denial(struct security_hook_list *hook) >> +{ >> + int i; >> + >> + if (lsm_exclusive_hooks == hook->lsmid->id) >> + return false; >> + >> + for (i = 0; i < ARRAY_SIZE(lsm_exclusive_set); i++) { >> + if (!(lsm_exclusive_set[i].flags & LSM_FLAG_EXCLUSIVE)) >> + continue; > The logic on this looks a bit odd. What is wrong with something like the > pseduo code below? This code isn't just looking to see if the hook is exclusive, it's looking to see if the hook is exclusive and if the LSM requesting it has been given the privilege to register exclusive hooks. This may not be the cleanest way to go about it, so I will reconsider how best to do that. > for (i = 0; ARRAY_SIZE(lsm_hooks); i++) { > if (lsm_hooks[i] == hook) { > if (lsm_hooks[i].flags & LSM_FLAG_EXCLUSIVE) > return true; > else > return false; > } > } > >> + if (hook->scalls == lsm_exclusive_set[i].name) { >> + if (lsm_exclusive_hooks) { >> + if (lsm_debug) >> + lsm_pr("%s denied for %s.\n", >> + lsm_exclusive_set[i].namestr, >> + hook->lsmid->name); > The lsm_pr_dbg() macro exists for this very reason. Indeed. I missed it here. Will correct. >> + return true; >> + } >> + if (lsm_debug) >> + lsm_pr("Exclusive hooks limited to %s.\n", >> + hook->lsmid->name); > Same as above. Same as above. >> + lsm_exclusive_hooks = hook->lsmid->id; >> + break; >> + } >> + } >> + return false; >> +} >> >> /** >> * security_add_hooks - Add a LSM's hooks to the LSM framework's hook lists >> * @hooks: LSM hooks to add >> @@ -371,6 +435,8 @@ void __init security_add_hooks(struct security_hook_list *hooks, int count, >> >> for (i = 0; i < count; i++) { >> hooks[i].lsmid = lsmid; >> + if (lsm_exclusive_hook_denial(&hooks[i])) >> + continue; >> if (lsm_static_call_init(&hooks[i])) >> panic("exhausted LSM callback slots with LSM %s\n", >> lsmid->name); > I don't think we'd want to simply skip over a hook registration if the > LSM doesn't have access to an exclusive hook. At the very least it risks > unexpected behavior in the LSM and at the worst it prevents the LSM from > properly enforcing it's security policy. There is a reason we have the > panic() call in the existing code if we are not able to register a hook. > > The simpliest solution here would be to panic, like we do today. > > However, if you want to get fancy and enable LSMs to optionally adjust > their behavior to cope with the loss of a hook callback (I'm looking at > your patch 3/3 now), come up with a mechanism to report back to the LSM > that one or more of the callbacks were not registered. One quick thought > would be to return a non-zero error code and add an indicator/bool/flag > to the security_hook_list that would be set by security_add_hooks(). An LSM can easily check to see if it doesn't get exclusive hooks by looking at lsm_exclusive_hooks after registration. if (lsm_exclusive_hooks != LSM_ID_ME) ... do something (in)appropriate ^ permalink raw reply [flat|nested] 11+ messages in thread
* [RFC PATCH 3/3] LSM: Reserve use of secmarks 2026-02-25 19:21 ` [RFC PATCH 0/3] LSM: Hook registration exculsivity Casey Schaufler 2026-02-25 19:21 ` [RFC PATCH 1/3] LSM: add a flags field to the LSM hook definitions Casey Schaufler 2026-02-25 19:21 ` [RFC PATCH 2/3] LSM: Enforce exclusive hooks Casey Schaufler @ 2026-02-25 19:21 ` Casey Schaufler 2026-04-24 1:19 ` [PATCH RFC " Paul Moore 2 siblings, 1 reply; 11+ messages in thread From: Casey Schaufler @ 2026-02-25 19:21 UTC (permalink / raw) To: casey, paul, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux Use of "exclusive" LSM hooks are limited to the first LSM registering them. These hooks include those use to process network secmarks. The hooks required to process secmarks are flagged with LSM_FLAG_EXCLUSIVE in their definitions. This includes secid_to_secctx and secctx_to_secid, which are used by netfilter. The various LSMs that use secmarks are updated to detect whether they are providing exclusive hooks, and to eschew the use of secmarks if they are not. SELinux has a peculiar behavior in that it may decide that it must have network controls, but only after policy is loaded. This patch includes a warning should policy capability alwaysnetwork be set when another LSM holds the exclusive hooks. It has been suggested that SELinux would consider this a fatal condition, in which case a panic might be a favored, if draconian, option. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> --- include/linux/lsm_hook_defs.h | 12 +++++------ include/linux/security.h | 1 + security/apparmor/lsm.c | 24 ++++++++++++++++------ security/security.c | 15 ++++++++++++++ security/selinux/hooks.c | 35 ++++++++++++++++++++++++-------- security/selinux/ss/services.c | 3 +++ security/smack/smack_lsm.c | 6 ++++-- security/smack/smack_netfilter.c | 6 ++++++ 8 files changed, 80 insertions(+), 22 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index acda3a02da97..e6d4d9c80ac6 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -309,12 +309,12 @@ LSM_HOOK(int, -EINVAL, 0, getprocattr, struct task_struct *p, const char *name, LSM_HOOK(int, -EINVAL, 0, setprocattr, const char *name, void *value, size_t size) LSM_HOOK(int, 0, 0, ismaclabel, const char *name) -LSM_HOOK(int, -EOPNOTSUPP, 0, secid_to_secctx, u32 secid, +LSM_HOOK(int, -EOPNOTSUPP, LSM_FLAG_EXCLUSIVE, secid_to_secctx, u32 secid, struct lsm_context *cp) LSM_HOOK(int, -EOPNOTSUPP, 0, lsmprop_to_secctx, struct lsm_prop *prop, struct lsm_context *cp) -LSM_HOOK(int, 0, 0, secctx_to_secid, const char *secdata, u32 seclen, - u32 *secid) +LSM_HOOK(int, 0, LSM_FLAG_EXCLUSIVE, secctx_to_secid, const char *secdata, + u32 seclen, u32 *secid) LSM_HOOK(void, LSM_RET_VOID, 0, release_secctx, struct lsm_context *cp) LSM_HOOK(void, LSM_RET_VOID, 0, inode_invalidate_secctx, struct inode *inode) LSM_HOOK(int, 0, 0, inode_notifysecctx, struct inode *inode, void *ctx, @@ -379,9 +379,9 @@ LSM_HOOK(void, LSM_RET_VOID, 0, inet_csk_clone, struct sock *newsk, const struct request_sock *req) LSM_HOOK(void, LSM_RET_VOID, 0, inet_conn_established, struct sock *sk, struct sk_buff *skb) -LSM_HOOK(int, 0, 0, secmark_relabel_packet, u32 secid) -LSM_HOOK(void, LSM_RET_VOID, 0, secmark_refcount_inc, void) -LSM_HOOK(void, LSM_RET_VOID, 0, secmark_refcount_dec, void) +LSM_HOOK(int, 0, LSM_FLAG_EXCLUSIVE, secmark_relabel_packet, u32 secid) +LSM_HOOK(void, LSM_RET_VOID, LSM_FLAG_EXCLUSIVE, secmark_refcount_inc, void) +LSM_HOOK(void, LSM_RET_VOID, LSM_FLAG_EXCLUSIVE, secmark_refcount_dec, void) LSM_HOOK(void, LSM_RET_VOID, 0, req_classify_flow, const struct request_sock *req, struct flowi_common *flic) LSM_HOOK(int, 0, 0, tun_dev_alloc_security, void *security) diff --git a/include/linux/security.h b/include/linux/security.h index e3c137a1b30a..638436b9b748 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -326,6 +326,7 @@ int unregister_blocking_lsm_notifier(struct notifier_block *nb); extern int security_init(void); extern int early_security_init(void); extern u64 lsm_name_to_attr(const char *name); +extern u32 lsm_secmark_from_skb(struct sk_buff *skb, const u64 lsmid); /* Security operations */ int security_binder_set_context_mgr(const struct cred *mgr); diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index a87cd60ed206..2ce0d9a73973 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c @@ -1511,9 +1511,11 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { struct aa_sk_ctx *ctx = aa_sock(sk); + u32 secmark; int error; - if (!skb->secmark) + secmark = lsm_secmark_from_skb(skb, LSM_ID_APPARMOR); + if (!secmark) return 0; /* @@ -1525,7 +1527,7 @@ static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) rcu_read_lock(); error = apparmor_secmark_check(rcu_dereference(ctx->label), OP_RECVMSG, - AA_MAY_RECEIVE, skb->secmark, sk); + AA_MAY_RECEIVE, secmark, sk); rcu_read_unlock(); return error; @@ -1640,14 +1642,16 @@ static int apparmor_inet_conn_request(const struct sock *sk, struct sk_buff *skb struct request_sock *req) { struct aa_sk_ctx *ctx = aa_sock(sk); + u32 secmark; int error; - if (!skb->secmark) + secmark = lsm_secmark_from_skb(skb, LSM_ID_APPARMOR); + if (!secmark) return 0; rcu_read_lock(); error = apparmor_secmark_check(rcu_dereference(ctx->label), OP_CONNECT, - AA_MAY_CONNECT, skb->secmark, sk); + AA_MAY_CONNECT, secmark, sk); rcu_read_unlock(); return error; @@ -2359,9 +2363,11 @@ static unsigned int apparmor_ip_postroute(void *priv, { struct aa_sk_ctx *ctx; struct sock *sk; + u32 secmark; int error; - if (!skb->secmark) + secmark = lsm_secmark_from_skb(skb, LSM_ID_APPARMOR); + if (!secmark) return NF_ACCEPT; sk = skb_to_full_sk(skb); @@ -2371,7 +2377,7 @@ static unsigned int apparmor_ip_postroute(void *priv, ctx = aa_sock(sk); rcu_read_lock(); error = apparmor_secmark_check(rcu_dereference(ctx->label), OP_SENDMSG, - AA_MAY_SEND, skb->secmark, sk); + AA_MAY_SEND, secmark, sk); rcu_read_unlock(); if (!error) return NF_ACCEPT; @@ -2399,12 +2405,18 @@ static const struct nf_hook_ops apparmor_nf_ops[] = { static int __net_init apparmor_nf_register(struct net *net) { + if (lsm_exclusive_hooks != LSM_ID_APPARMOR) + return 0; + return nf_register_net_hooks(net, apparmor_nf_ops, ARRAY_SIZE(apparmor_nf_ops)); } static void __net_exit apparmor_nf_unregister(struct net *net) { + if (lsm_exclusive_hooks != LSM_ID_APPARMOR) + return; + nf_unregister_net_hooks(net, apparmor_nf_ops, ARRAY_SIZE(apparmor_nf_ops)); } diff --git a/security/security.c b/security/security.c index 25e7cfc96f20..754b16004677 100644 --- a/security/security.c +++ b/security/security.c @@ -4509,6 +4509,21 @@ void security_inet_conn_established(struct sock *sk, } EXPORT_SYMBOL(security_inet_conn_established); +/** + * lsm_secmark_from_skb - secid for the specified LSM from the packet + * @skb: the packet + * @lsm: which LSM is asking + * + * If the specified LSM has use of the secmark, return its value. + * Otherwise, return the invalid secid 0. + */ +u32 lsm_secmark_from_skb(struct sk_buff *skb, const u64 lsmid) +{ + if (lsmid == lsm_exclusive_hooks) + return skb->secmark; + return 0; +} + /** * security_secmark_relabel_packet() - Check if setting a secmark is allowed * @secid: new secmark value diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d053ce562370..1dff2121a834 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5269,6 +5269,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, int err = 0; struct sk_security_struct *sksec = selinux_sock(sk); u32 sk_sid = sksec->sid; + u32 secmark; struct common_audit_data ad; struct lsm_network_audit net; char *addrp; @@ -5279,7 +5280,8 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, return err; if (selinux_secmark_enabled()) { - err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + secmark = lsm_secmark_from_skb(skb, LSM_ID_SELINUX); + err = avc_has_perm(sk_sid, secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) return err; @@ -5299,6 +5301,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) struct sk_security_struct *sksec = selinux_sock(sk); u16 family = sk->sk_family; u32 sk_sid = sksec->sid; + u32 secmark; struct common_audit_data ad; struct lsm_network_audit net; char *addrp; @@ -5348,7 +5351,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) } if (secmark_active) { - err = avc_has_perm(sk_sid, skb->secmark, SECCLASS_PACKET, + secmark = lsm_secmark_from_skb(skb, LSM_ID_SELINUX); + err = avc_has_perm(sk_sid, secmark, SECCLASS_PACKET, PACKET__RECV, &ad); if (err) return err; @@ -5850,6 +5854,7 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, int ifindex; u16 family; char *addrp; + u32 secmark; u32 peer_sid; struct common_audit_data ad; struct lsm_network_audit net; @@ -5883,10 +5888,12 @@ static unsigned int selinux_ip_forward(void *priv, struct sk_buff *skb, } } - if (secmark_active) - if (avc_has_perm(peer_sid, skb->secmark, + if (secmark_active) { + secmark = lsm_secmark_from_skb(skb, LSM_ID_SELINUX); + if (avc_has_perm(peer_sid, secmark, SECCLASS_PACKET, PACKET__FORWARD_IN, &ad)) return NF_DROP; + } if (netlbl_enabled()) /* we do this in the FORWARD path and not the POST_ROUTING @@ -5950,6 +5957,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, struct common_audit_data ad; struct lsm_network_audit net; u8 proto = 0; + u32 secmark; sk = skb_to_full_sk(skb); if (sk == NULL) @@ -5960,10 +5968,12 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb, if (selinux_parse_skb(skb, &ad, NULL, 0, &proto)) return NF_DROP; - if (selinux_secmark_enabled()) - if (avc_has_perm(sksec->sid, skb->secmark, + if (selinux_secmark_enabled()) { + secmark = lsm_secmark_from_skb(skb, LSM_ID_SELINUX); + if (avc_has_perm(sksec->sid, secmark, SECCLASS_PACKET, PACKET__SEND, &ad)) return NF_DROP_ERR(-ECONNREFUSED); + } if (selinux_xfrm_postroute_last(sksec->sid, skb, &ad, proto)) return NF_DROP_ERR(-ECONNREFUSED); @@ -5978,6 +5988,7 @@ static unsigned int selinux_ip_postroute(void *priv, u16 family; u32 secmark_perm; u32 peer_sid; + u32 secmark; int ifindex; struct sock *sk; struct common_audit_data ad; @@ -6082,10 +6093,12 @@ static unsigned int selinux_ip_postroute(void *priv, if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL)) return NF_DROP; - if (secmark_active) - if (avc_has_perm(peer_sid, skb->secmark, + if (secmark_active) { + secmark = lsm_secmark_from_skb(skb, LSM_ID_SELINUX); + if (avc_has_perm(peer_sid, secmark, SECCLASS_PACKET, secmark_perm, &ad)) return NF_DROP_ERR(-ECONNREFUSED); + } if (peerlbl_active) { u32 if_sid; @@ -7718,12 +7731,18 @@ static const struct nf_hook_ops selinux_nf_ops[] = { static int __net_init selinux_nf_register(struct net *net) { + if (lsm_exclusive_hooks != LSM_ID_SELINUX) + return 0; + return nf_register_net_hooks(net, selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); } static void __net_exit selinux_nf_unregister(struct net *net) { + if (lsm_exclusive_hooks != LSM_ID_SELINUX) + return; + nf_unregister_net_hooks(net, selinux_nf_ops, ARRAY_SIZE(selinux_nf_ops)); } diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 13fc712d5923..269ad09f8dca 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -2189,6 +2189,9 @@ static void security_load_policycaps(struct selinux_policy *policy) pr_info("SELinux: unknown policy capability %u\n", i); } + if (selinux_state.policycap[POLICYDB_CAP_ALWAYSNETWORK] && + lsm_exclusive_hooks != LSM_ID_SELINUX) + pr_warn("SELinux: policy capability alwaysnetwork is set, but secmark is used by another LSM.\n"); } static int security_preserve_bools(struct selinux_policy *oldpolicy, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index a0bd4919a9d9..7a98dcc4c67d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -4195,10 +4195,12 @@ static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr_in6 *sip) #ifdef CONFIG_NETWORK_SECMARK static struct smack_known *smack_from_skb(struct sk_buff *skb) { - if (skb == NULL || skb->secmark == 0) + u32 secmark = lsm_secmark_from_skb(skb, LSM_ID_SMACK); + + if (skb == NULL || secmark == 0) return NULL; - return smack_from_secid(skb->secmark); + return smack_from_secid(secmark); } #else static inline struct smack_known *smack_from_skb(struct sk_buff *skb) diff --git a/security/smack/smack_netfilter.c b/security/smack/smack_netfilter.c index 17ba578b1308..47426973843b 100644 --- a/security/smack/smack_netfilter.c +++ b/security/smack/smack_netfilter.c @@ -54,12 +54,18 @@ static const struct nf_hook_ops smack_nf_ops[] = { static int __net_init smack_nf_register(struct net *net) { + if (lsm_exclusive_hooks != LSM_ID_SMACK) + return 0; + return nf_register_net_hooks(net, smack_nf_ops, ARRAY_SIZE(smack_nf_ops)); } static void __net_exit smack_nf_unregister(struct net *net) { + if (lsm_exclusive_hooks != LSM_ID_SMACK) + return; + nf_unregister_net_hooks(net, smack_nf_ops, ARRAY_SIZE(smack_nf_ops)); } -- 2.52.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 3/3] LSM: Reserve use of secmarks 2026-02-25 19:21 ` [RFC PATCH 3/3] LSM: Reserve use of secmarks Casey Schaufler @ 2026-04-24 1:19 ` Paul Moore 2026-04-25 19:03 ` Casey Schaufler 0 siblings, 1 reply; 11+ messages in thread From: Paul Moore @ 2026-04-24 1:19 UTC (permalink / raw) To: Casey Schaufler, casey, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: > > Use of "exclusive" LSM hooks are limited to the first LSM registering > them. These hooks include those use to process network secmarks. > The hooks required to process secmarks are flagged with LSM_FLAG_EXCLUSIVE > in their definitions. This includes secid_to_secctx and secctx_to_secid, > which are used by netfilter. > > The various LSMs that use secmarks are updated to detect whether > they are providing exclusive hooks, and to eschew the use of secmarks > if they are not. > > SELinux has a peculiar behavior in that it may decide that it > must have network controls, but only after policy is loaded. > This patch includes a warning should policy capability alwaysnetwork > be set when another LSM holds the exclusive hooks. It has been > suggested that SELinux would consider this a fatal condition, in > which case a panic might be a favored, if draconian, option. > > Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> > --- > include/linux/lsm_hook_defs.h | 12 +++++------ > include/linux/security.h | 1 + > security/apparmor/lsm.c | 24 ++++++++++++++++------ > security/security.c | 15 ++++++++++++++ > security/selinux/hooks.c | 35 ++++++++++++++++++++++++-------- > security/selinux/ss/services.c | 3 +++ > security/smack/smack_lsm.c | 6 ++++-- > security/smack/smack_netfilter.c | 6 ++++++ > 8 files changed, 80 insertions(+), 22 deletions(-) ... > diff --git a/include/linux/security.h b/include/linux/security.h > index e3c137a1b30a..638436b9b748 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -326,6 +326,7 @@ int unregister_blocking_lsm_notifier(struct notifier_block *nb); > extern int security_init(void); > extern int early_security_init(void); > extern u64 lsm_name_to_attr(const char *name); > +extern u32 lsm_secmark_from_skb(struct sk_buff *skb, const u64 lsmid); > > /* Security operations */ > int security_binder_set_context_mgr(const struct cred *mgr); > diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c > index a87cd60ed206..2ce0d9a73973 100644 > --- a/security/apparmor/lsm.c > +++ b/security/apparmor/lsm.c > @@ -1511,9 +1511,11 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) > static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) > { > struct aa_sk_ctx *ctx = aa_sock(sk); > + u32 secmark; > int error; > > - if (!skb->secmark) > + secmark = lsm_secmark_from_skb(skb, LSM_ID_APPARMOR); > + if (!secmark) > return 0; > > /* ... > diff --git a/security/security.c b/security/security.c > index 25e7cfc96f20..754b16004677 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -4509,6 +4509,21 @@ void security_inet_conn_established(struct sock *sk, > } > EXPORT_SYMBOL(security_inet_conn_established); > > +/** > + * lsm_secmark_from_skb - secid for the specified LSM from the packet > + * @skb: the packet > + * @lsm: which LSM is asking > + * > + * If the specified LSM has use of the secmark, return its value. > + * Otherwise, return the invalid secid 0. > + */ > +u32 lsm_secmark_from_skb(struct sk_buff *skb, const u64 lsmid) > +{ > + if (lsmid == lsm_exclusive_hooks) > + return skb->secmark; > + return 0; > +} Ooof. Not a fan. A better way to handle this would be to like I mentioned in my comments on patch 2/3: have the LSM detect that it lost the LSM_FLAG_EXCLUSIVE battle at callback registration time and do whatever adjustments are necessary at init time. In a number of cases I believe that simply not registering the callback will be sufficient. If the only way to solve this is via runtime checks like this, unfortunately my answer is going to be "no". ... and of course the proper way to solve this for secmark is to just do the idr/xarray conversion for secmarks so every LSM can have their own secmark. Yes, it does require some work, but to be honest I think you've spent more time avoiding that work then it would be to just do it. I'm growing increasing inclined to simply state that this is the only solution I'm going to accept. -- paul-moore.com ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH RFC 3/3] LSM: Reserve use of secmarks 2026-04-24 1:19 ` [PATCH RFC " Paul Moore @ 2026-04-25 19:03 ` Casey Schaufler 0 siblings, 0 replies; 11+ messages in thread From: Casey Schaufler @ 2026-04-25 19:03 UTC (permalink / raw) To: Paul Moore, linux-security-module Cc: jmorris, serge, keescook, john.johansen, penguin-kernel, stephen.smalley.work, selinux, Casey Schaufler On 4/23/2026 6:19 PM, Paul Moore wrote: > On Feb 25, 2026 Casey Schaufler <casey@schaufler-ca.com> wrote: >> Use of "exclusive" LSM hooks are limited to the first LSM registering >> them. These hooks include those use to process network secmarks. >> The hooks required to process secmarks are flagged with LSM_FLAG_EXCLUSIVE >> in their definitions. This includes secid_to_secctx and secctx_to_secid, >> which are used by netfilter. >> >> The various LSMs that use secmarks are updated to detect whether >> they are providing exclusive hooks, and to eschew the use of secmarks >> if they are not. >> >> SELinux has a peculiar behavior in that it may decide that it >> must have network controls, but only after policy is loaded. >> This patch includes a warning should policy capability alwaysnetwork >> be set when another LSM holds the exclusive hooks. It has been >> suggested that SELinux would consider this a fatal condition, in >> which case a panic might be a favored, if draconian, option. >> >> Signed-off-by: Casey Schaufler <casey@schaufler-ca.com> >> --- >> include/linux/lsm_hook_defs.h | 12 +++++------ >> include/linux/security.h | 1 + >> security/apparmor/lsm.c | 24 ++++++++++++++++------ >> security/security.c | 15 ++++++++++++++ >> security/selinux/hooks.c | 35 ++++++++++++++++++++++++-------- >> security/selinux/ss/services.c | 3 +++ >> security/smack/smack_lsm.c | 6 ++++-- >> security/smack/smack_netfilter.c | 6 ++++++ >> 8 files changed, 80 insertions(+), 22 deletions(-) > .. > >> diff --git a/include/linux/security.h b/include/linux/security.h >> index e3c137a1b30a..638436b9b748 100644 >> --- a/include/linux/security.h >> +++ b/include/linux/security.h >> @@ -326,6 +326,7 @@ int unregister_blocking_lsm_notifier(struct notifier_block *nb); >> extern int security_init(void); >> extern int early_security_init(void); >> extern u64 lsm_name_to_attr(const char *name); >> +extern u32 lsm_secmark_from_skb(struct sk_buff *skb, const u64 lsmid); >> >> /* Security operations */ >> int security_binder_set_context_mgr(const struct cred *mgr); >> diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c >> index a87cd60ed206..2ce0d9a73973 100644 >> --- a/security/apparmor/lsm.c >> +++ b/security/apparmor/lsm.c >> @@ -1511,9 +1511,11 @@ static int apparmor_socket_shutdown(struct socket *sock, int how) >> static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) >> { >> struct aa_sk_ctx *ctx = aa_sock(sk); >> + u32 secmark; >> int error; >> >> - if (!skb->secmark) >> + secmark = lsm_secmark_from_skb(skb, LSM_ID_APPARMOR); >> + if (!secmark) >> return 0; >> >> /* > .. > >> diff --git a/security/security.c b/security/security.c >> index 25e7cfc96f20..754b16004677 100644 >> --- a/security/security.c >> +++ b/security/security.c >> @@ -4509,6 +4509,21 @@ void security_inet_conn_established(struct sock *sk, >> } >> EXPORT_SYMBOL(security_inet_conn_established); >> >> +/** >> + * lsm_secmark_from_skb - secid for the specified LSM from the packet >> + * @skb: the packet >> + * @lsm: which LSM is asking >> + * >> + * If the specified LSM has use of the secmark, return its value. >> + * Otherwise, return the invalid secid 0. >> + */ >> +u32 lsm_secmark_from_skb(struct sk_buff *skb, const u64 lsmid) >> +{ >> + if (lsmid == lsm_exclusive_hooks) >> + return skb->secmark; >> + return 0; >> +} > Ooof. Not a fan. A better way to handle this would be to like I > mentioned in my comments on patch 2/3: have the LSM detect that it lost > the LSM_FLAG_EXCLUSIVE battle at callback registration time and do > whatever adjustments are necessary at init time. In a number of cases I > believe that simply not registering the callback will be sufficient. In no case (AppArmor, Smack, SELinux) will that be sufficient. All access skb->secmark directly. The hooks that use the secmark also use other mechanisms (e.g. netlabel) to obtain security attributes. > If the only way to solve this is via runtime checks like this, > unfortunately my answer is going to be "no". OK. I hear you. > .. and of course the proper way to solve this for secmark is to just > do the idr/xarray conversion for secmarks so every LSM can have their > own secmark. Yes, it does require some work, but to be honest I think > you've spent more time avoiding that work then it would be to just do > it. I'm growing increasing inclined to simply state that this is the > only solution I'm going to accept. Thank you for the clarity. If you happen to have a preferred example of how idr/xarray is used I expect that we can reduce the review cycle of such an implementation. ... Or, if there's someone out there who's itching to get involved and eager to tackle a moderately complicated integration effort, I'd happily outline the pain points. > > -- > paul-moore.com With that I think this RFC has been useful in that the LSM define flag scheme might be useful in the future, but doesn't address the task at hand. ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-04-25 19:13 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20260225192143.14448-1-casey.ref@schaufler-ca.com>
2026-02-25 19:21 ` [RFC PATCH 0/3] LSM: Hook registration exculsivity Casey Schaufler
2026-02-25 19:21 ` [RFC PATCH 1/3] LSM: add a flags field to the LSM hook definitions Casey Schaufler
2026-04-24 1:19 ` [PATCH RFC " Paul Moore
2026-04-24 15:24 ` Casey Schaufler
2026-04-24 20:29 ` Paul Moore
2026-02-25 19:21 ` [RFC PATCH 2/3] LSM: Enforce exclusive hooks Casey Schaufler
2026-04-24 1:19 ` [PATCH RFC " Paul Moore
2026-04-25 0:39 ` Casey Schaufler
2026-02-25 19:21 ` [RFC PATCH 3/3] LSM: Reserve use of secmarks Casey Schaufler
2026-04-24 1:19 ` [PATCH RFC " Paul Moore
2026-04-25 19:03 ` Casey Schaufler
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox