2020-03-29 08:43:50 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Linux Security Module Hook declarations.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com>
|
|
|
|
* Copyright (C) 2001 Greg Kroah-Hartman <greg@kroah.com>
|
|
|
|
* Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com>
|
|
|
|
* Copyright (C) 2001 James Morris <jmorris@intercode.com.au>
|
|
|
|
* Copyright (C) 2001 Silicon Graphics, Inc. (Trust Technology Group)
|
|
|
|
* Copyright (C) 2015 Intel Corporation.
|
|
|
|
* Copyright (C) 2015 Casey Schaufler <casey@schaufler-ca.com>
|
|
|
|
* Copyright (C) 2016 Mellanox Techonologies
|
|
|
|
* Copyright (C) 2020 Google LLC.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
2020-07-18 07:36:40 +08:00
|
|
|
* The macro LSM_HOOK is used to define the data structures required by
|
2020-03-29 08:43:50 +08:00
|
|
|
* the LSM framework using the pattern:
|
|
|
|
*
|
|
|
|
* LSM_HOOK(<return_type>, <default_value>, <hook_name>, args...)
|
|
|
|
*
|
|
|
|
* struct security_hook_heads {
|
|
|
|
* #define LSM_HOOK(RET, DEFAULT, NAME, ...) struct hlist_head NAME;
|
|
|
|
* #include <linux/lsm_hook_defs.h>
|
|
|
|
* #undef LSM_HOOK
|
|
|
|
* };
|
|
|
|
*/
|
2021-10-13 00:56:13 +08:00
|
|
|
LSM_HOOK(int, 0, binder_set_context_mgr, const struct cred *mgr)
|
|
|
|
LSM_HOOK(int, 0, binder_transaction, const struct cred *from,
|
|
|
|
const struct cred *to)
|
|
|
|
LSM_HOOK(int, 0, binder_transfer_binder, const struct cred *from,
|
|
|
|
const struct cred *to)
|
|
|
|
LSM_HOOK(int, 0, binder_transfer_file, const struct cred *from,
|
|
|
|
const struct cred *to, struct file *file)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 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, 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,
|
|
|
|
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, 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,
|
|
|
|
const struct timezone *tz)
|
|
|
|
LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages)
|
2020-03-23 04:46:24 +08:00
|
|
|
LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm)
|
2020-05-30 11:00:54 +08:00
|
|
|
LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, struct file *file)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, struct linux_binprm *bprm)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, struct linux_binprm *bprm)
|
|
|
|
LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc,
|
|
|
|
struct fs_context *src_sc)
|
2020-04-30 23:52:40 +08:00
|
|
|
LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc,
|
2020-03-29 08:43:50 +08:00
|
|
|
struct fs_parameter *param)
|
|
|
|
LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb)
|
2021-04-22 23:41:16 +08:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sb_delete, struct super_block *sb)
|
2020-03-29 08:43:50 +08:00
|
|
|
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)
|
2021-02-27 11:37:55 +08:00
|
|
|
LSM_HOOK(int, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts)
|
|
|
|
LSM_HOOK(int, 0, sb_kern_mount, 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,
|
|
|
|
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,
|
|
|
|
const struct path *new_path)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
struct super_block *newsb, unsigned long kern_flags,
|
|
|
|
unsigned long *set_kern_flags)
|
|
|
|
LSM_HOOK(int, 0, move_mount, const struct path *from_path,
|
|
|
|
const struct path *to_path)
|
security, lsm: dentry_init_security() Handle multi LSM registration
A ceph user has reported that ceph is crashing with kernel NULL pointer
dereference. Following is the backtrace.
/proc/version: Linux version 5.16.2-arch1-1 (linux@archlinux) (gcc (GCC)
11.1.0, GNU ld (GNU Binutils) 2.36.1) #1 SMP PREEMPT Thu, 20 Jan 2022
16:18:29 +0000
distro / arch: Arch Linux / x86_64
SELinux is not enabled
ceph cluster version: 16.2.7 (dd0603118f56ab514f133c8d2e3adfc983942503)
relevant dmesg output:
[ 30.947129] BUG: kernel NULL pointer dereference, address:
0000000000000000
[ 30.947206] #PF: supervisor read access in kernel mode
[ 30.947258] #PF: error_code(0x0000) - not-present page
[ 30.947310] PGD 0 P4D 0
[ 30.947342] Oops: 0000 [#1] PREEMPT SMP PTI
[ 30.947388] CPU: 5 PID: 778 Comm: touch Not tainted 5.16.2-arch1-1 #1
86fbf2c313cc37a553d65deb81d98e9dcc2a3659
[ 30.947486] Hardware name: Gigabyte Technology Co., Ltd. B365M
DS3H/B365M DS3H, BIOS F5 08/13/2019
[ 30.947569] RIP: 0010:strlen+0x0/0x20
[ 30.947616] Code: b6 07 38 d0 74 16 48 83 c7 01 84 c0 74 05 48 39 f7 75
ec 31 c0 31 d2 89 d6 89 d7 c3 48 89 f8 31 d2 89 d6 89 d7 c3 0
f 1f 40 00 <80> 3f 00 74 12 48 89 f8 48 83 c0 01 80 38 00 75 f7 48 29 f8 31
ff
[ 30.947782] RSP: 0018:ffffa4ed80ffbbb8 EFLAGS: 00010246
[ 30.947836] RAX: 0000000000000000 RBX: ffffa4ed80ffbc60 RCX:
0000000000000000
[ 30.947904] RDX: 0000000000000000 RSI: 0000000000000000 RDI:
0000000000000000
[ 30.947971] RBP: ffff94b0d15c0ae0 R08: 0000000000000000 R09:
0000000000000000
[ 30.948040] R10: 0000000000000000 R11: 0000000000000000 R12:
0000000000000000
[ 30.948106] R13: 0000000000000001 R14: ffffa4ed80ffbc60 R15:
0000000000000000
[ 30.948174] FS: 00007fc7520f0740(0000) GS:ffff94b7ced40000(0000)
knlGS:0000000000000000
[ 30.948252] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 30.948308] CR2: 0000000000000000 CR3: 0000000104a40001 CR4:
00000000003706e0
[ 30.948376] Call Trace:
[ 30.948404] <TASK>
[ 30.948431] ceph_security_init_secctx+0x7b/0x240 [ceph
49f9c4b9bf5be8760f19f1747e26da33920bce4b]
[ 30.948582] ceph_atomic_open+0x51e/0x8a0 [ceph
49f9c4b9bf5be8760f19f1747e26da33920bce4b]
[ 30.948708] ? get_cached_acl+0x4d/0xa0
[ 30.948759] path_openat+0x60d/0x1030
[ 30.948809] do_filp_open+0xa5/0x150
[ 30.948859] do_sys_openat2+0xc4/0x190
[ 30.948904] __x64_sys_openat+0x53/0xa0
[ 30.948948] do_syscall_64+0x5c/0x90
[ 30.948989] ? exc_page_fault+0x72/0x180
[ 30.949034] entry_SYSCALL_64_after_hwframe+0x44/0xae
[ 30.949091] RIP: 0033:0x7fc7521e25bb
[ 30.950849] Code: 25 00 00 41 00 3d 00 00 41 00 74 4b 64 8b 04 25 18 00
00 00 85 c0 75 67 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 0
0 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 91 00 00 00 48 8b 54 24 28 64 48 2b 14
25
Core of the problem is that ceph checks for return code from
security_dentry_init_security() and if return code is 0, it assumes
everything is fine and continues to call strlen(name), which crashes.
Typically SELinux LSM returns 0 and sets name to "security.selinux" and
it is not a problem. Or if selinux is not compiled in or disabled, it
returns -EOPNOTSUP and ceph deals with it.
But somehow in this configuration, 0 is being returned and "name" is
not being initialized and that's creating the problem.
Our suspicion is that BPF LSM is registering a hook for
dentry_init_security() and returns hook default of 0.
LSM_HOOK(int, 0, dentry_init_security, struct dentry *dentry,...)
I have not been able to reproduce it just by doing CONFIG_BPF_LSM=y.
Stephen has tested the patch though and confirms it solves the problem
for him.
dentry_init_security() is written in such a way that it expects only one
LSM to register the hook. Atleast that's the expectation with current code.
If another LSM returns a hook and returns default, it will simply return
0 as of now and that will break ceph.
Hence, suggestion is that change semantics of this hook a bit. If there
are no LSMs or no LSM is taking ownership and initializing security context,
then return -EOPNOTSUP. Also allow at max one LSM to initialize security
context. This hook can't deal with multiple LSMs trying to init security
context. This patch implements this new behavior.
Reported-by: Stephen Muth <smuth4@gmail.com>
Tested-by: Stephen Muth <smuth4@gmail.com>
Suggested-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Reviewed-by: Serge Hallyn <serge@hallyn.com>
Cc: Jeff Layton <jlayton@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Paul Moore <paul@paul-moore.com>
Cc: <stable@vger.kernel.org> # 5.16.0
Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Acked-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: James Morris <jmorris@namei.org>
2022-01-27 04:35:14 +08:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
|
2021-10-12 21:23:07 +08:00
|
|
|
int mode, const struct qstr *name, const char **xattr_name,
|
|
|
|
void **ctx, u32 *ctxlen)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, dentry_create_files_as, struct dentry *dentry, int mode,
|
|
|
|
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,
|
|
|
|
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,
|
|
|
|
umode_t mode, unsigned int dev)
|
|
|
|
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,
|
|
|
|
const struct path *new_dir, struct dentry *new_dentry)
|
|
|
|
LSM_HOOK(int, 0, path_rename, const struct path *old_dir,
|
|
|
|
struct dentry *old_dentry, const struct path *new_dir,
|
|
|
|
struct dentry *new_dentry)
|
|
|
|
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)
|
|
|
|
#endif /* CONFIG_SECURITY_PATH */
|
|
|
|
|
|
|
|
/* Needed for inode based security check */
|
|
|
|
LSM_HOOK(int, 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(int, 0, inode_init_security, struct inode *inode,
|
|
|
|
struct inode *dir, const struct qstr *qstr, const char **name,
|
|
|
|
void **value, size_t *len)
|
2021-01-09 06:22:20 +08:00
|
|
|
LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
|
|
|
|
const struct qstr *name, const struct inode *context_inode)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
|
|
|
|
umode_t mode)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
const char *old_name)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
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 dentry *dentry, struct iattr *attr)
|
|
|
|
LSM_HOOK(int, 0, inode_getattr, const struct path *path)
|
2021-01-21 21:19:29 +08:00
|
|
|
LSM_HOOK(int, 0, inode_setxattr, struct user_namespace *mnt_userns,
|
|
|
|
struct dentry *dentry, const char *name, const void *value,
|
|
|
|
size_t size, int flags)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, 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)
|
2021-01-21 21:19:29 +08:00
|
|
|
LSM_HOOK(int, 0, inode_removexattr, struct user_namespace *mnt_userns,
|
|
|
|
struct dentry *dentry, const char *name)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry)
|
2021-01-21 21:19:29 +08:00
|
|
|
LSM_HOOK(int, 0, inode_killpriv, struct user_namespace *mnt_userns,
|
|
|
|
struct dentry *dentry)
|
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct user_namespace *mnt_userns,
|
|
|
|
struct inode *inode, const char *name, void **buffer, bool alloc)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, 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,
|
|
|
|
size_t buffer_size)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_getsecid, struct inode *inode, u32 *secid)
|
|
|
|
LSM_HOOK(int, 0, inode_copy_up, struct dentry *src, struct cred **new)
|
2020-06-22 06:21:35 +08:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, inode_copy_up_xattr, const char *name)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 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_free_security, struct file *file)
|
|
|
|
LSM_HOOK(int, 0, file_ioctl, 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,
|
|
|
|
unsigned long prot, unsigned long flags)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
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,
|
|
|
|
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, task_alloc, struct task_struct *task,
|
|
|
|
unsigned long 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,
|
|
|
|
gfp_t gfp)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, 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(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)
|
2020-10-03 01:38:20 +08:00
|
|
|
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,
|
2020-10-07 04:11:15 +08:00
|
|
|
enum kernel_load_data_id id, char *description)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, kernel_read_file, struct file *file,
|
2020-10-03 01:38:23 +08:00
|
|
|
enum kernel_read_file_id id, bool contents)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
int flags)
|
2020-06-10 01:22:13 +08:00
|
|
|
LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old,
|
|
|
|
int flags)
|
2020-03-29 08:43:50 +08:00
|
|
|
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)
|
2021-09-29 23:01:21 +08:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, current_getsecid_subj, u32 *secid)
|
2021-02-20 03:26:21 +08:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, task_getsecid_obj,
|
|
|
|
struct task_struct *p, u32 *secid)
|
2020-03-29 08:43:50 +08:00
|
|
|
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,
|
|
|
|
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,
|
|
|
|
unsigned long arg3, unsigned long arg4, unsigned long arg5)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, task_to_inode, struct task_struct *p,
|
|
|
|
struct inode *inode)
|
|
|
|
LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, ipc_getsecid, struct kern_ipc_perm *ipcp,
|
|
|
|
u32 *secid)
|
|
|
|
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,
|
|
|
|
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,
|
|
|
|
struct msg_msg *msg, int msqflg)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
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,
|
|
|
|
struct inode *inode)
|
|
|
|
LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, 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)
|
2020-05-13 01:46:07 +08:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, char **secdata,
|
2020-03-29 08:43:50 +08:00
|
|
|
u32 *seclen)
|
|
|
|
LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, release_secctx, char *secdata, u32 seclen)
|
|
|
|
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, 0, inode_getsecctx, struct inode *inode, void **ctx,
|
|
|
|
u32 *ctxlen)
|
|
|
|
|
2020-02-12 21:58:35 +08:00
|
|
|
#if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
|
|
|
|
LSM_HOOK(int, 0, post_notification, const struct cred *w_cred,
|
|
|
|
const struct cred *cred, struct watch_notification *n)
|
2020-02-12 21:58:35 +08:00
|
|
|
#endif /* CONFIG_SECURITY && CONFIG_WATCH_QUEUE */
|
|
|
|
|
|
|
|
#if defined(CONFIG_SECURITY) && defined(CONFIG_KEY_NOTIFICATIONS)
|
|
|
|
LSM_HOOK(int, 0, watch_key, struct key *key)
|
2020-02-12 21:58:35 +08:00
|
|
|
#endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */
|
|
|
|
|
2020-03-29 08:43:50 +08:00
|
|
|
#ifdef CONFIG_SECURITY_NETWORK
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
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,
|
|
|
|
int size)
|
|
|
|
LSM_HOOK(int, 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, 0, socket_getpeersec_stream, struct socket *sock,
|
|
|
|
char __user *optval, int __user *optlen, unsigned len)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
struct sock *newsk)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, struct sock *sk, u32 *secid)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sock_graft, struct sock *sk, struct socket *parent)
|
2020-11-30 23:36:29 +08:00
|
|
|
LSM_HOOK(int, 0, inet_conn_request, const struct sock *sk, struct sk_buff *skb,
|
2020-03-29 08:43:50 +08:00
|
|
|
struct request_sock *req)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inet_csk_clone, struct sock *newsk,
|
|
|
|
const struct request_sock *req)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, 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,
|
2020-09-28 10:38:26 +08:00
|
|
|
struct flowi_common *flic)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, tun_dev_alloc_security, void **security)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, tun_dev_free_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)
|
2021-11-02 20:02:47 +08:00
|
|
|
LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_association *asoc,
|
2020-03-29 08:43:50 +08:00
|
|
|
struct sk_buff *skb)
|
|
|
|
LSM_HOOK(int, 0, sctp_bind_connect, struct sock *sk, int optname,
|
|
|
|
struct sockaddr *address, int addrlen)
|
2021-11-02 20:02:47 +08:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc,
|
2020-03-29 08:43:50 +08:00
|
|
|
struct sock *sk, struct sock *newsk)
|
2022-02-13 01:59:21 +08:00
|
|
|
LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc,
|
|
|
|
struct sk_buff *skb)
|
2020-03-29 08:43:50 +08:00
|
|
|
#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,
|
|
|
|
u8 port_num)
|
|
|
|
LSM_HOOK(int, 0, ib_alloc_security, void **sec)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, ib_free_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,
|
|
|
|
struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp)
|
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
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,
|
|
|
|
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)
|
2021-04-09 13:48:41 +08:00
|
|
|
LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x,
|
2020-09-28 10:38:26 +08:00
|
|
|
struct xfrm_policy *xp, const struct flowi_common *flic)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 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,
|
|
|
|
unsigned long flags)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key)
|
|
|
|
LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred,
|
2020-06-16 02:12:32 +08:00
|
|
|
enum key_need_perm need_perm)
|
2020-03-29 08:43:50 +08:00
|
|
|
LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **_buffer)
|
|
|
|
#endif /* CONFIG_KEYS */
|
|
|
|
|
|
|
|
#ifdef CONFIG_AUDIT
|
|
|
|
LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr,
|
|
|
|
void **lsmrule)
|
|
|
|
LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule)
|
|
|
|
LSM_HOOK(int, 0, audit_rule_match, u32 secid, u32 field, u32 op, void *lsmrule)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, 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)
|
|
|
|
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_alloc_security, struct bpf_map *map)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bpf_map_free_security, struct bpf_map *map)
|
|
|
|
LSM_HOOK(int, 0, bpf_prog_alloc_security, struct bpf_prog_aux *aux)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free_security, struct bpf_prog_aux *aux)
|
|
|
|
#endif /* CONFIG_BPF_SYSCALL */
|
|
|
|
|
|
|
|
LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
|
|
|
|
|
|
|
|
#ifdef CONFIG_PERF_EVENTS
|
|
|
|
LSM_HOOK(int, 0, perf_event_open, struct perf_event_attr *attr, int type)
|
|
|
|
LSM_HOOK(int, 0, perf_event_alloc, struct perf_event *event)
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, perf_event_free, 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)
|
|
|
|
#endif /* CONFIG_PERF_EVENTS */
|
lsm,io_uring: add LSM hooks to io_uring
A full expalantion of io_uring is beyond the scope of this commit
description, but in summary it is an asynchronous I/O mechanism
which allows for I/O requests and the resulting data to be queued
in memory mapped "rings" which are shared between the kernel and
userspace. Optionally, io_uring offers the ability for applications
to spawn kernel threads to dequeue I/O requests from the ring and
submit the requests in the kernel, helping to minimize the syscall
overhead. Rings are accessed in userspace by memory mapping a file
descriptor provided by the io_uring_setup(2), and can be shared
between applications as one might do with any open file descriptor.
Finally, process credentials can be registered with a given ring
and any process with access to that ring can submit I/O requests
using any of the registered credentials.
While the io_uring functionality is widely recognized as offering a
vastly improved, and high performing asynchronous I/O mechanism, its
ability to allow processes to submit I/O requests with credentials
other than its own presents a challenge to LSMs. When a process
creates a new io_uring ring the ring's credentials are inhertied
from the calling process; if this ring is shared with another
process operating with different credentials there is the potential
to bypass the LSMs security policy. Similarly, registering
credentials with a given ring allows any process with access to that
ring to submit I/O requests with those credentials.
In an effort to allow LSMs to apply security policy to io_uring I/O
operations, this patch adds two new LSM hooks. These hooks, in
conjunction with the LSM anonymous inode support previously
submitted, allow an LSM to apply access control policy to the
sharing of io_uring rings as well as any io_uring credential changes
requested by a process.
The new LSM hooks are described below:
* int security_uring_override_creds(cred)
Controls if the current task, executing an io_uring operation,
is allowed to override it's credentials with @cred. In cases
where the current task is a user application, the current
credentials will be those of the user application. In cases
where the current task is a kernel thread servicing io_uring
requests the current credentials will be those of the io_uring
ring (inherited from the process that created the ring).
* int security_uring_sqpoll(void)
Controls if the current task is allowed to create an io_uring
polling thread (IORING_SETUP_SQPOLL). Without a SQPOLL thread
in the kernel processes must submit I/O requests via
io_uring_enter(2) which allows us to compare any requested
credential changes against the application making the request.
With a SQPOLL thread, we can no longer compare requested
credential changes against the application making the request,
the comparison is made against the ring's credentials.
Signed-off-by: Paul Moore <paul@paul-moore.com>
2021-02-02 08:56:49 +08:00
|
|
|
|
|
|
|
#ifdef CONFIG_IO_URING
|
|
|
|
LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
|
|
|
|
LSM_HOOK(int, 0, uring_sqpoll, void)
|
|
|
|
#endif /* CONFIG_IO_URING */
|