2020-03-29 00:43:50 +00: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-17 23:36:40 +00:00
|
|
|
* The macro LSM_HOOK is used to define the data structures required by
|
2020-03-29 00:43:50 +00: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-12 16:56:13 +00: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,
|
2023-08-12 15:31:08 +00:00
|
|
|
const struct cred *to, const struct file *file)
|
2020-03-29 00:43:50 +00: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)
|
2023-08-07 06:59:29 +00:00
|
|
|
LSM_HOOK(int, 0, capget, const struct task_struct *target, kernel_cap_t *effective,
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2023-08-23 06:44:41 +00:00
|
|
|
LSM_HOOK(int, 0, quotactl, int cmds, int type, int id, const struct super_block *sb)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2024-07-24 02:06:58 +00:00
|
|
|
LSM_HOOK(int, 0, vm_enough_memory, struct mm_struct *mm, long pages)
|
2020-03-22 20:46:24 +00:00
|
|
|
LSM_HOOK(int, 0, bprm_creds_for_exec, struct linux_binprm *bprm)
|
2023-08-23 07:17:29 +00:00
|
|
|
LSM_HOOK(int, 0, bprm_creds_from_file, struct linux_binprm *bprm, const struct file *file)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, bprm_check_security, struct linux_binprm *bprm)
|
2023-08-23 07:47:56 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bprm_committing_creds, const struct linux_binprm *bprm)
|
2023-08-23 08:16:40 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bprm_committed_creds, const struct linux_binprm *bprm)
|
vfs, security: Fix automount superblock LSM init problem, preventing NFS sb sharing
When NFS superblocks are created by automounting, their LSM parameters
aren't set in the fs_context struct prior to sget_fc() being called,
leading to failure to match existing superblocks.
This bug leads to messages like the following appearing in dmesg when
fscache is enabled:
NFS: Cache volume key already in use (nfs,4.2,2,108,106a8c0,1,,,,100000,100000,2ee,3a98,1d4c,3a98,1)
Fix this by adding a new LSM hook to load fc->security for submount
creation.
Signed-off-by: David Howells <dhowells@redhat.com>
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://lore.kernel.org/r/165962680944.3334508.6610023900349142034.stgit@warthog.procyon.org.uk/ # v1
Link: https://lore.kernel.org/r/165962729225.3357250.14350728846471527137.stgit@warthog.procyon.org.uk/ # v2
Link: https://lore.kernel.org/r/165970659095.2812394.6868894171102318796.stgit@warthog.procyon.org.uk/ # v3
Link: https://lore.kernel.org/r/166133579016.3678898.6283195019480567275.stgit@warthog.procyon.org.uk/ # v4
Link: https://lore.kernel.org/r/217595.1662033775@warthog.procyon.org.uk/ # v5
Fixes: 9bc61ab18b1d ("vfs: Introduce fs_context, switch vfs_kern_mount() to it.")
Fixes: 779df6a5480f ("NFS: Ensure security label is set for root inode")
Tested-by: Jeff Layton <jlayton@kernel.org>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Acked-by: "Christian Brauner (Microsoft)" <brauner@kernel.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Message-Id: <20230808-master-v9-1-e0ecde888221@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>
2023-08-08 11:34:20 +00:00
|
|
|
LSM_HOOK(int, 0, fs_context_submount, struct fs_context *fc, struct super_block *reference)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, fs_context_dup, struct fs_context *fc,
|
|
|
|
struct fs_context *src_sc)
|
2020-04-30 15:52:40 +00:00
|
|
|
LSM_HOOK(int, -ENOPARAM, fs_context_parse_param, struct fs_context *fc,
|
2020-03-29 00:43:50 +00:00
|
|
|
struct fs_parameter *param)
|
|
|
|
LSM_HOOK(int, 0, sb_alloc_security, struct super_block *sb)
|
2021-04-22 15:41:16 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sb_delete, struct super_block *sb)
|
2020-03-29 00:43:50 +00: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 03:37:55 +00:00
|
|
|
LSM_HOOK(int, 0, sb_mnt_opts_compat, struct super_block *sb, void *mnt_opts)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, sb_remount, struct super_block *sb, void *mnt_opts)
|
2023-08-23 09:01:28 +00:00
|
|
|
LSM_HOOK(int, 0, sb_kern_mount, const struct super_block *sb)
|
2020-03-29 00:43:50 +00:00
|
|
|
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-26 20:35:14 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, dentry_init_security, struct dentry *dentry,
|
2021-10-12 13:23:07 +00:00
|
|
|
int mode, const struct qstr *name, const char **xattr_name,
|
2024-10-23 21:21:57 +00:00
|
|
|
struct lsm_context *cp)
|
2020-03-29 00:43:50 +00: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)
|
2024-02-15 10:31:02 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, path_post_mknod, struct mnt_idmap *idmap,
|
|
|
|
struct dentry *dentry)
|
2020-03-29 00:43:50 +00:00
|
|
|
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,
|
2022-05-06 16:10:56 +00:00
|
|
|
struct dentry *new_dentry, unsigned int flags)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2024-07-09 23:43:06 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_free_security_rcu, void *inode_security)
|
security: Allow all LSMs to provide xattrs for inode_init_security hook
Currently, the LSM infrastructure supports only one LSM providing an xattr
and EVM calculating the HMAC on that xattr, plus other inode metadata.
Allow all LSMs to provide one or multiple xattrs, by extending the security
blob reservation mechanism. Introduce the new lbs_xattr_count field of the
lsm_blob_sizes structure, so that each LSM can specify how many xattrs it
needs, and the LSM infrastructure knows how many xattr slots it should
allocate.
Modify the inode_init_security hook definition, by passing the full
xattr array allocated in security_inode_init_security(), and the current
number of xattr slots in that array filled by LSMs. The first parameter
would allow EVM to access and calculate the HMAC on xattrs supplied by
other LSMs, the second to not leave gaps in the xattr array, when an LSM
requested but did not provide xattrs (e.g. if it is not initialized).
Introduce lsm_get_xattr_slot(), which LSMs can call as many times as the
number specified in the lbs_xattr_count field of the lsm_blob_sizes
structure. During each call, lsm_get_xattr_slot() increments the number of
filled xattrs, so that at the next invocation it returns the next xattr
slot to fill.
Cleanup security_inode_init_security(). Unify the !initxattrs and
initxattrs case by simply not allocating the new_xattrs array in the
former. Update the documentation to reflect the changes, and fix the
description of the xattr name, as it is not allocated anymore.
Adapt both SELinux and Smack to use the new definition of the
inode_init_security hook, and to call lsm_get_xattr_slot() to obtain and
fill the reserved slots in the xattr array.
Move the xattr->name assignment after the xattr->value one, so that it is
done only in case of successful memory allocation.
Finally, change the default return value of the inode_init_security hook
from zero to -EOPNOTSUPP, so that BPF LSM correctly follows the hook
conventions.
Reported-by: Nicolas Bouchinet <nicolas.bouchinet@clip-os.org>
Link: https://lore.kernel.org/linux-integrity/Y1FTSIo+1x+4X0LS@archlinux/
Signed-off-by: Roberto Sassu <roberto.sassu@huawei.com>
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
[PM: minor comment and variable tweaks, approved by RS]
Signed-off-by: Paul Moore <paul@paul-moore.com>
2023-06-10 07:57:35 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, inode_init_security, struct inode *inode,
|
|
|
|
struct inode *dir, const struct qstr *qstr, struct xattr *xattrs,
|
|
|
|
int *xattr_count)
|
2021-01-08 22:22:20 +00:00
|
|
|
LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
|
|
|
|
const struct qstr *name, const struct inode *context_inode)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
|
|
|
|
umode_t mode)
|
2024-02-15 10:31:03 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_post_create_tmpfile, struct mnt_idmap *idmap,
|
|
|
|
struct inode *inode)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2024-02-15 10:30:57 +00:00
|
|
|
LSM_HOOK(int, 0, inode_setattr, struct mnt_idmap *idmap, struct dentry *dentry,
|
|
|
|
struct iattr *attr)
|
2024-02-15 10:30:58 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_post_setattr, struct mnt_idmap *idmap,
|
|
|
|
struct dentry *dentry, int ia_valid)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, inode_getattr, const struct path *path)
|
lsm: fixup the inode xattr capability handling
The current security_inode_setxattr() and security_inode_removexattr()
hooks rely on individual LSMs to either call into the associated
capability hooks (cap_inode_setxattr() or cap_inode_removexattr()), or
return a magic value of 1 to indicate that the LSM layer itself should
perform the capability checks. Unfortunately, with the default return
value for these LSM hooks being 0, an individual LSM hook returning a
1 will cause the LSM hook processing to exit early, potentially
skipping a LSM. Thankfully, with the exception of the BPF LSM, none
of the LSMs which currently register inode xattr hooks should end up
returning a value of 1, and in the BPF LSM case, with the BPF LSM hooks
executing last there should be no real harm in stopping processing of
the LSM hooks. However, the reliance on the individual LSMs to either
call the capability hooks themselves, or signal the LSM with a return
value of 1, is fragile and relies on a specific set of LSMs being
enabled. This patch is an effort to resolve, or minimize, these
issues.
Before we discuss the solution, there are a few observations and
considerations that we need to take into account:
* BPF LSM registers an implementation for every LSM hook, and that
implementation simply returns the hook's default return value, a
0 in this case. We want to ensure that the default BPF LSM behavior
results in the capability checks being called.
* SELinux and Smack do not expect the traditional capability checks
to be applied to the xattrs that they "own".
* SELinux and Smack are currently written in such a way that the
xattr capability checks happen before any additional LSM specific
access control checks. SELinux does apply SELinux specific access
controls to all xattrs, even those not "owned" by SELinux.
* IMA and EVM also register xattr hooks but assume that the LSM layer
and specific LSMs have already authorized the basic xattr operation.
In order to ensure we perform the capability based access controls
before the individual LSM access controls, perform only one capability
access control check for each operation, and clarify the logic around
applying the capability controls, we need a mechanism to determine if
any of the enabled LSMs "own" a particular xattr and want to take
responsibility for controlling access to that xattr. The solution in
this patch is to create a new LSM hook, 'inode_xattr_skipcap', that is
not exported to the rest of the kernel via a security_XXX() function,
but is used by the LSM layer to determine if a LSM wants to control
access to a given xattr and avoid the traditional capability controls.
Registering an inode_xattr_skipcap hook is optional, if a LSM declines
to register an implementation, or uses an implementation that simply
returns the default value (0), there is no effect as the LSM continues
to enforce the capability based controls (unless another LSM takes
ownership of the xattr). If none of the LSMs signal that the
capability checks should be skipped, the capability check is performed
and if access is granted the individual LSM xattr access control hooks
are executed, keeping with the DAC-before-LSM convention.
Cc: stable@vger.kernel.org
Acked-by: Casey Schaufler <casey@schaufler-ca.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
2024-05-02 21:57:51 +00:00
|
|
|
LSM_HOOK(int, 0, inode_xattr_skipcap, const char *name)
|
2023-01-13 11:49:23 +00:00
|
|
|
LSM_HOOK(int, 0, inode_setxattr, struct mnt_idmap *idmap,
|
2021-01-21 13:19:29 +00:00
|
|
|
struct dentry *dentry, const char *name, const void *value,
|
|
|
|
size_t size, int flags)
|
2020-03-29 00:43:50 +00: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)
|
2023-01-13 11:49:23 +00:00
|
|
|
LSM_HOOK(int, 0, inode_removexattr, struct mnt_idmap *idmap,
|
2021-01-21 13:19:29 +00:00
|
|
|
struct dentry *dentry, const char *name)
|
2024-02-15 10:30:59 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_post_removexattr, struct dentry *dentry,
|
|
|
|
const char *name)
|
2023-01-13 11:49:24 +00:00
|
|
|
LSM_HOOK(int, 0, inode_set_acl, struct mnt_idmap *idmap,
|
2022-09-22 15:17:07 +00:00
|
|
|
struct dentry *dentry, const char *acl_name, struct posix_acl *kacl)
|
2024-02-15 10:31:04 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_post_set_acl, struct dentry *dentry,
|
|
|
|
const char *acl_name, struct posix_acl *kacl)
|
2023-01-13 11:49:24 +00:00
|
|
|
LSM_HOOK(int, 0, inode_get_acl, struct mnt_idmap *idmap,
|
2022-09-22 15:17:07 +00:00
|
|
|
struct dentry *dentry, const char *acl_name)
|
2023-01-13 11:49:24 +00:00
|
|
|
LSM_HOOK(int, 0, inode_remove_acl, struct mnt_idmap *idmap,
|
2022-09-22 15:17:07 +00:00
|
|
|
struct dentry *dentry, const char *acl_name)
|
2024-02-15 10:31:05 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_post_remove_acl, struct mnt_idmap *idmap,
|
|
|
|
struct dentry *dentry, const char *acl_name)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, inode_need_killpriv, struct dentry *dentry)
|
2023-01-13 11:49:23 +00:00
|
|
|
LSM_HOOK(int, 0, inode_killpriv, struct mnt_idmap *idmap,
|
2021-01-21 13:19:29 +00:00
|
|
|
struct dentry *dentry)
|
2023-01-13 11:49:22 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecurity, struct mnt_idmap *idmap,
|
2021-01-21 13:19:29 +00:00
|
|
|
struct inode *inode, const char *name, void **buffer, bool alloc)
|
2020-03-29 00:43:50 +00: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)
|
2024-10-09 17:32:16 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, inode_getlsmprop, struct inode *inode,
|
|
|
|
struct lsm_prop *prop)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, inode_copy_up, struct dentry *src, struct cred **new)
|
2024-02-23 17:25:05 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, inode_copy_up_xattr, struct dentry *src,
|
|
|
|
const char *name)
|
2024-08-03 06:08:28 +00:00
|
|
|
LSM_HOOK(int, 0, inode_setintegrity, const struct inode *inode,
|
|
|
|
enum lsm_integrity_type type, const void *value, size_t size)
|
2020-03-29 00:43:50 +00: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)
|
2024-02-15 10:31:01 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file)
|
2020-03-29 00:43:50 +00:00
|
|
|
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: new security_file_ioctl_compat() hook
Some ioctl commands do not require ioctl permission, but are routed to
other permissions such as FILE_GETATTR or FILE_SETATTR. This routing is
done by comparing the ioctl cmd to a set of 64-bit flags (FS_IOC_*).
However, if a 32-bit process is running on a 64-bit kernel, it emits
32-bit flags (FS_IOC32_*) for certain ioctl operations. These flags are
being checked erroneously, which leads to these ioctl operations being
routed to the ioctl permission, rather than the correct file
permissions.
This was also noted in a RED-PEN finding from a while back -
"/* RED-PEN how should LSM module know it's handling 32bit? */".
This patch introduces a new hook, security_file_ioctl_compat(), that is
called from the compat ioctl syscall. All current LSMs have been changed
to support this hook.
Reviewing the three places where we are currently using
security_file_ioctl(), it appears that only SELinux needs a dedicated
compat change; TOMOYO and SMACK appear to be functional without any
change.
Cc: stable@vger.kernel.org
Fixes: 0b24dcb7f2f7 ("Revert "selinux: simplify ioctl checking"")
Signed-off-by: Alfred Piccioni <alpic@google.com>
Reviewed-by: Stephen Smalley <stephen.smalley.work@gmail.com>
[PM: subject tweak, line length fixes, and alignment corrections]
Signed-off-by: Paul Moore <paul@paul-moore.com>
2023-12-19 09:09:09 +00:00
|
|
|
LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd,
|
|
|
|
unsigned long arg)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2024-02-15 10:31:00 +00:00
|
|
|
LSM_HOOK(int, 0, file_post_open, struct file *file, int mask)
|
2022-10-18 18:22:06 +00:00
|
|
|
LSM_HOOK(int, 0, file_truncate, struct file *file)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2024-10-09 17:32:18 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, cred_getlsmprop, const struct cred *c,
|
|
|
|
struct lsm_prop *prop)
|
2020-03-29 00:43:50 +00:00
|
|
|
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-02 17:38:20 +00: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-06 20:11:15 +00:00
|
|
|
enum kernel_load_data_id id, char *description)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, kernel_read_file, struct file *file,
|
2020-10-02 17:38:23 +00:00
|
|
|
enum kernel_read_file_id id, bool contents)
|
2020-03-29 00:43:50 +00: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-09 17:22:13 +00:00
|
|
|
LSM_HOOK(int, 0, task_fix_setgid, struct cred *new, const struct cred * old,
|
|
|
|
int flags)
|
2022-06-08 20:57:11 +00:00
|
|
|
LSM_HOOK(int, 0, task_fix_setgroups, struct cred *new, const struct cred * old)
|
2020-03-29 00:43:50 +00: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)
|
2024-10-09 17:32:15 +00:00
|
|
|
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)
|
2020-03-29 00:43:50 +00: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)
|
security, lsm: Introduce security_create_user_ns()
User namespaces are an effective tool to allow programs to run with
permission without requiring the need for a program to run as root. User
namespaces may also be used as a sandboxing technique. However, attackers
sometimes leverage user namespaces as an initial attack vector to perform
some exploit. [1,2,3]
While it is not the unprivileged user namespace functionality, which
causes the kernel to be exploitable, users/administrators might want to
more granularly limit or at least monitor how various processes use this
functionality, while vulnerable kernel subsystems are being patched.
Preventing user namespace already creation comes in a few of forms in
order of granularity:
1. /proc/sys/user/max_user_namespaces sysctl
2. Distro specific patch(es)
3. CONFIG_USER_NS
To block a task based on its attributes, the LSM hook cred_prepare is a
decent candidate for use because it provides more granular control, and
it is called before create_user_ns():
cred = prepare_creds()
security_prepare_creds()
call_int_hook(cred_prepare, ...
if (cred)
create_user_ns(cred)
Since security_prepare_creds() is meant for LSMs to copy and prepare
credentials, access control is an unintended use of the hook. [4]
Further, security_prepare_creds() will always return a ENOMEM if the
hook returns any non-zero error code.
This hook also does not handle the clone3 case which requires us to
access a user space pointer to know if we're in the CLONE_NEW_USER
call path which may be subject to a TOCTTOU attack.
Lastly, cred_prepare is called in many call paths, and a targeted hook
further limits the frequency of calls which is a beneficial outcome.
Therefore introduce a new function security_create_user_ns() with an
accompanying userns_create LSM hook.
With the new userns_create hook, users will have more control over the
observability and access control over user namespace creation. Users
should expect that normal operation of user namespaces will behave as
usual, and only be impacted when controls are implemented by users or
administrators.
This hook takes the prepared creds for LSM authors to write policy
against. On success, the new namespace is applied to credentials,
otherwise an error is returned.
Links:
1. https://nvd.nist.gov/vuln/detail/CVE-2022-0492
2. https://nvd.nist.gov/vuln/detail/CVE-2022-25636
3. https://nvd.nist.gov/vuln/detail/CVE-2022-34918
4. https://lore.kernel.org/all/1c4b1c0d-12f6-6e9e-a6a3-cdce7418110c@schaufler-ca.com/
Reviewed-by: Christian Brauner (Microsoft) <brauner@kernel.org>
Reviewed-by: KP Singh <kpsingh@kernel.org>
Signed-off-by: Frederick Lawler <fred@cloudflare.com>
Signed-off-by: Paul Moore <paul@paul-moore.com>
2022-08-15 16:20:25 +00:00
|
|
|
LSM_HOOK(int, 0, userns_create, const struct cred *cred)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, ipc_permission, struct kern_ipc_perm *ipcp, short flag)
|
2024-10-09 17:32:13 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, ipc_getlsmprop, struct kern_ipc_perm *ipcp,
|
|
|
|
struct lsm_prop *prop)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2023-09-12 20:56:49 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, getselfattr, unsigned int attr,
|
2024-03-14 15:31:26 +00:00
|
|
|
struct lsm_ctx __user *ctx, u32 *size, u32 flags)
|
2023-09-12 20:56:49 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, setselfattr, unsigned int attr,
|
2024-03-14 15:31:26 +00:00
|
|
|
struct lsm_ctx *ctx, u32 size, u32 flags)
|
2022-01-31 00:57:52 +00:00
|
|
|
LSM_HOOK(int, -EINVAL, getprocattr, struct task_struct *p, const char *name,
|
2020-03-29 00:43:50 +00:00
|
|
|
char **value)
|
|
|
|
LSM_HOOK(int, -EINVAL, setprocattr, const char *name, void *value, size_t size)
|
|
|
|
LSM_HOOK(int, 0, ismaclabel, const char *name)
|
2024-10-23 21:21:55 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, secid_to_secctx, u32 secid, struct lsm_context *cp)
|
2024-10-09 17:32:11 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, lsmprop_to_secctx, struct lsm_prop *prop,
|
2024-10-23 21:21:55 +00:00
|
|
|
struct lsm_context *cp)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, secctx_to_secid, const char *secdata, u32 seclen, u32 *secid)
|
2024-10-23 21:21:54 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, release_secctx, struct lsm_context *cp)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2024-10-23 21:21:56 +00:00
|
|
|
LSM_HOOK(int, -EOPNOTSUPP, inode_getsecctx, struct inode *inode,
|
|
|
|
struct lsm_context *cp)
|
2020-03-29 00:43:50 +00:00
|
|
|
|
2020-02-12 13:58:35 +00: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 13:58:35 +00: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 13:58:35 +00:00
|
|
|
#endif /* CONFIG_SECURITY && CONFIG_KEY_NOTIFICATIONS */
|
|
|
|
|
2020-03-29 00:43:50 +00: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)
|
2024-01-26 18:45:31 +00:00
|
|
|
LSM_HOOK(int, -ENOPROTOOPT, socket_getpeersec_stream, struct socket *sock,
|
2022-10-10 16:31:21 +00:00
|
|
|
sockptr_t optval, sockptr_t optlen, unsigned int len)
|
2024-01-26 18:45:31 +00:00
|
|
|
LSM_HOOK(int, -ENOPROTOOPT, socket_getpeersec_dgram, struct socket *sock,
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
2023-07-11 13:06:08 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sk_getsecid, const struct sock *sk, u32 *secid)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sock_graft, struct sock *sk, struct socket *parent)
|
2020-11-30 15:36:29 +00:00
|
|
|
LSM_HOOK(int, 0, inet_conn_request, const struct sock *sk, struct sk_buff *skb,
|
2020-03-29 00:43:50 +00: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 02:38:26 +00:00
|
|
|
struct flowi_common *flic)
|
2024-07-10 21:32:28 +00:00
|
|
|
LSM_HOOK(int, 0, tun_dev_alloc_security, void *security)
|
2020-03-29 00:43:50 +00:00
|
|
|
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 12:02:47 +00:00
|
|
|
LSM_HOOK(int, 0, sctp_assoc_request, struct sctp_association *asoc,
|
2020-03-29 00:43:50 +00: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 12:02:47 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, sctp_sk_clone, struct sctp_association *asoc,
|
2020-03-29 00:43:50 +00:00
|
|
|
struct sock *sk, struct sock *newsk)
|
2022-02-12 17:59:21 +00:00
|
|
|
LSM_HOOK(int, 0, sctp_assoc_established, struct sctp_association *asoc,
|
|
|
|
struct sk_buff *skb)
|
2023-04-20 17:17:13 +00:00
|
|
|
LSM_HOOK(int, 0, mptcp_add_subflow, struct sock *sk, struct sock *ssk)
|
2020-03-29 00:43:50 +00: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)
|
2024-07-10 21:32:29 +00:00
|
|
|
LSM_HOOK(int, 0, ib_alloc_security, void *sec)
|
2020-03-29 00:43:50 +00:00
|
|
|
#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 05:48:41 +00:00
|
|
|
LSM_HOOK(int, 0, xfrm_policy_lookup, struct xfrm_sec_ctx *ctx, u32 fl_secid)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 1, xfrm_state_pol_flow_match, struct xfrm_state *x,
|
2020-09-28 02:38:26 +00:00
|
|
|
struct xfrm_policy *xp, const struct flowi_common *flic)
|
2020-03-29 00:43:50 +00: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(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred,
|
2020-06-15 18:12:32 +00:00
|
|
|
enum key_need_perm need_perm)
|
2023-03-08 18:28:18 +00:00
|
|
|
LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer)
|
2024-02-15 10:31:06 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, key_post_create_or_update, struct key *keyring,
|
|
|
|
struct key *key, const void *payload, size_t payload_len,
|
|
|
|
unsigned long flags, bool create)
|
2020-03-29 00:43:50 +00:00
|
|
|
#endif /* CONFIG_KEYS */
|
|
|
|
|
|
|
|
#ifdef CONFIG_AUDIT
|
|
|
|
LSM_HOOK(int, 0, audit_rule_init, u32 field, u32 op, char *rulestr,
|
2024-05-07 01:25:41 +00:00
|
|
|
void **lsmrule, gfp_t gfp)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, audit_rule_known, struct audit_krule *krule)
|
2024-10-09 17:32:10 +00:00
|
|
|
LSM_HOOK(int, 0, audit_rule_match, struct lsm_prop *prop, u32 field, u32 op,
|
|
|
|
void *lsmrule)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, audit_rule_free, void *lsmrule)
|
|
|
|
#endif /* CONFIG_AUDIT */
|
|
|
|
|
|
|
|
#ifdef CONFIG_BPF_SYSCALL
|
2025-03-10 22:17:11 +00:00
|
|
|
LSM_HOOK(int, 0, bpf, int cmd, union bpf_attr *attr, unsigned int size, bool kernel)
|
2020-03-29 00:43:50 +00:00
|
|
|
LSM_HOOK(int, 0, bpf_map, struct bpf_map *map, fmode_t fmode)
|
|
|
|
LSM_HOOK(int, 0, bpf_prog, struct bpf_prog *prog)
|
bpf,lsm: Refactor bpf_map_alloc/bpf_map_free LSM hooks
Similarly to bpf_prog_alloc LSM hook, rename and extend bpf_map_alloc
hook into bpf_map_create, taking not just struct bpf_map, but also
bpf_attr and bpf_token, to give a fuller context to LSMs.
Unlike bpf_prog_alloc, there is no need to move the hook around, as it
currently is firing right before allocating BPF map ID and FD, which
seems to be a sweet spot.
But like bpf_prog_alloc/bpf_prog_free combo, make sure that bpf_map_free
LSM hook is called even if bpf_map_create hook returned error, as if few
LSMs are combined together it could be that one LSM successfully
allocated security blob for its needs, while subsequent LSM rejected BPF
map creation. The former LSM would still need to free up LSM blob, so we
need to ensure security_bpf_map_free() is called regardless of the
outcome.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Link: https://lore.kernel.org/bpf/20240124022127.2379740-11-andrii@kernel.org
2024-01-24 02:21:07 +00:00
|
|
|
LSM_HOOK(int, 0, bpf_map_create, struct bpf_map *map, union bpf_attr *attr,
|
2025-03-10 22:17:11 +00:00
|
|
|
struct bpf_token *token, bool kernel)
|
bpf,lsm: Refactor bpf_map_alloc/bpf_map_free LSM hooks
Similarly to bpf_prog_alloc LSM hook, rename and extend bpf_map_alloc
hook into bpf_map_create, taking not just struct bpf_map, but also
bpf_attr and bpf_token, to give a fuller context to LSMs.
Unlike bpf_prog_alloc, there is no need to move the hook around, as it
currently is firing right before allocating BPF map ID and FD, which
seems to be a sweet spot.
But like bpf_prog_alloc/bpf_prog_free combo, make sure that bpf_map_free
LSM hook is called even if bpf_map_create hook returned error, as if few
LSMs are combined together it could be that one LSM successfully
allocated security blob for its needs, while subsequent LSM rejected BPF
map creation. The former LSM would still need to free up LSM blob, so we
need to ensure security_bpf_map_free() is called regardless of the
outcome.
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Link: https://lore.kernel.org/bpf/20240124022127.2379740-11-andrii@kernel.org
2024-01-24 02:21:07 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bpf_map_free, struct bpf_map *map)
|
bpf,lsm: Refactor bpf_prog_alloc/bpf_prog_free LSM hooks
Based on upstream discussion ([0]), rework existing
bpf_prog_alloc_security LSM hook. Rename it to bpf_prog_load and instead
of passing bpf_prog_aux, pass proper bpf_prog pointer for a full BPF
program struct. Also, we pass bpf_attr union with all the user-provided
arguments for BPF_PROG_LOAD command. This will give LSMs as much
information as we can basically provide.
The hook is also BPF token-aware now, and optional bpf_token struct is
passed as a third argument. bpf_prog_load LSM hook is called after
a bunch of sanity checks were performed, bpf_prog and bpf_prog_aux were
allocated and filled out, but right before performing full-fledged BPF
verification step.
bpf_prog_free LSM hook is now accepting struct bpf_prog argument, for
consistency. SELinux code is adjusted to all new names, types, and
signatures.
Note, given that bpf_prog_load (previously bpf_prog_alloc) hook can be
used by some LSMs to allocate extra security blob, but also by other
LSMs to reject BPF program loading, we need to make sure that
bpf_prog_free LSM hook is called after bpf_prog_load/bpf_prog_alloc one
*even* if the hook itself returned error. If we don't do that, we run
the risk of leaking memory. This seems to be possible today when
combining SELinux and BPF LSM, as one example, depending on their
relative ordering.
Also, for BPF LSM setup, add bpf_prog_load and bpf_prog_free to
sleepable LSM hooks list, as they are both executed in sleepable
context. Also drop bpf_prog_load hook from untrusted, as there is no
issue with refcount or anything else anymore, that originally forced us
to add it to untrusted list in c0c852dd1876 ("bpf: Do not mark certain LSM
hook arguments as trusted"). We now trigger this hook much later and it
should not be an issue anymore.
[0] https://lore.kernel.org/bpf/9fe88aef7deabbe87d3fc38c4aea3c69.paul@paul-moore.com/
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Link: https://lore.kernel.org/bpf/20240124022127.2379740-10-andrii@kernel.org
2024-01-24 02:21:06 +00:00
|
|
|
LSM_HOOK(int, 0, bpf_prog_load, struct bpf_prog *prog, union bpf_attr *attr,
|
2025-03-10 22:17:11 +00:00
|
|
|
struct bpf_token *token, bool kernel)
|
bpf,lsm: Refactor bpf_prog_alloc/bpf_prog_free LSM hooks
Based on upstream discussion ([0]), rework existing
bpf_prog_alloc_security LSM hook. Rename it to bpf_prog_load and instead
of passing bpf_prog_aux, pass proper bpf_prog pointer for a full BPF
program struct. Also, we pass bpf_attr union with all the user-provided
arguments for BPF_PROG_LOAD command. This will give LSMs as much
information as we can basically provide.
The hook is also BPF token-aware now, and optional bpf_token struct is
passed as a third argument. bpf_prog_load LSM hook is called after
a bunch of sanity checks were performed, bpf_prog and bpf_prog_aux were
allocated and filled out, but right before performing full-fledged BPF
verification step.
bpf_prog_free LSM hook is now accepting struct bpf_prog argument, for
consistency. SELinux code is adjusted to all new names, types, and
signatures.
Note, given that bpf_prog_load (previously bpf_prog_alloc) hook can be
used by some LSMs to allocate extra security blob, but also by other
LSMs to reject BPF program loading, we need to make sure that
bpf_prog_free LSM hook is called after bpf_prog_load/bpf_prog_alloc one
*even* if the hook itself returned error. If we don't do that, we run
the risk of leaking memory. This seems to be possible today when
combining SELinux and BPF LSM, as one example, depending on their
relative ordering.
Also, for BPF LSM setup, add bpf_prog_load and bpf_prog_free to
sleepable LSM hooks list, as they are both executed in sleepable
context. Also drop bpf_prog_load hook from untrusted, as there is no
issue with refcount or anything else anymore, that originally forced us
to add it to untrusted list in c0c852dd1876 ("bpf: Do not mark certain LSM
hook arguments as trusted"). We now trigger this hook much later and it
should not be an issue anymore.
[0] https://lore.kernel.org/bpf/9fe88aef7deabbe87d3fc38c4aea3c69.paul@paul-moore.com/
Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Acked-by: Paul Moore <paul@paul-moore.com>
Link: https://lore.kernel.org/bpf/20240124022127.2379740-10-andrii@kernel.org
2024-01-24 02:21:06 +00:00
|
|
|
LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free, struct bpf_prog *prog)
|
2024-01-24 02:21:08 +00:00
|
|
|
LSM_HOOK(int, 0, bpf_token_create, struct bpf_token *token, union bpf_attr *attr,
|
2024-08-06 22:38:12 +00:00
|
|
|
const struct path *path)
|
2024-01-24 02:21:08 +00:00
|
|
|
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)
|
2020-03-29 00:43:50 +00:00
|
|
|
#endif /* CONFIG_BPF_SYSCALL */
|
|
|
|
|
|
|
|
LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
|
|
|
|
|
|
|
|
#ifdef CONFIG_PERF_EVENTS
|
2024-12-23 07:06:49 +00:00
|
|
|
LSM_HOOK(int, 0, perf_event_open, int type)
|
2020-03-29 00:43:50 +00:00
|
|
|
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)
|
|
|
|
#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 00:56:49 +00:00
|
|
|
|
|
|
|
#ifdef CONFIG_IO_URING
|
|
|
|
LSM_HOOK(int, 0, uring_override_creds, const struct cred *new)
|
|
|
|
LSM_HOOK(int, 0, uring_sqpoll, void)
|
2022-07-15 19:16:22 +00:00
|
|
|
LSM_HOOK(int, 0, uring_cmd, struct io_uring_cmd *ioucmd)
|
2025-01-27 15:57:18 +00:00
|
|
|
LSM_HOOK(int, 0, uring_allowed, void)
|
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 00:56:49 +00:00
|
|
|
#endif /* CONFIG_IO_URING */
|
2024-08-03 06:08:19 +00:00
|
|
|
|
|
|
|
LSM_HOOK(void, LSM_RET_VOID, initramfs_populated, void)
|
block,lsm: add LSM blob and new LSM hooks for block devices
This patch introduces a new LSM blob to the block_device structure,
enabling the security subsystem to store security-sensitive data related
to block devices. Currently, for a device mapper's mapped device containing
a dm-verity target, critical security information such as the roothash and
its signing state are not readily accessible. Specifically, while the
dm-verity volume creation process passes the dm-verity roothash and its
signature from userspace to the kernel, the roothash is stored privately
within the dm-verity target, and its signature is discarded
post-verification. This makes it extremely hard for the security subsystem
to utilize these data.
With the addition of the LSM blob to the block_device structure, the
security subsystem can now retain and manage important security metadata
such as the roothash and the signing state of a dm-verity by storing them
inside the blob. Access decisions can then be based on these stored data.
The implementation follows the same approach used for security blobs in
other structures like struct file, struct inode, and struct superblock.
The initialization of the security blob occurs after the creation of the
struct block_device, performed by the security subsystem. Similarly, the
security blob is freed by the security subsystem before the struct
block_device is deallocated or freed.
This patch also introduces a new hook security_bdev_setintegrity() to save
block device's integrity data to the new LSM blob. For example, for
dm-verity, it can use this hook to expose its roothash and signing state
to LSMs, then LSMs can save these data into the LSM blob.
Please note that the new hook should be invoked every time the security
information is updated to keep these data current. For example, in
dm-verity, if the mapping table is reloaded and configured to use a
different dm-verity target with a new roothash and signing information,
the previously stored data in the LSM blob will become obsolete. It is
crucial to re-invoke the hook to refresh these data and ensure they are up
to date. This necessity arises from the design of device-mapper, where a
device-mapper device is first created, and then targets are subsequently
loaded into it. These targets can be modified multiple times during the
device's lifetime. Therefore, while the LSM blob is allocated during the
creation of the block device, its actual contents are not initialized at
this stage and can change substantially over time. This includes
alterations from data that the LSM 'trusts' to those it does not, making
it essential to handle these changes correctly. Failure to address this
dynamic aspect could potentially allow for bypassing LSM checks.
Signed-off-by: Deven Bowers <deven.desai@linux.microsoft.com>
Signed-off-by: Fan Wu <wufan@linux.microsoft.com>
[PM: merge fuzz, subject line tweaks]
Signed-off-by: Paul Moore <paul@paul-moore.com>
2024-08-03 06:08:25 +00:00
|
|
|
|
|
|
|
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,
|
|
|
|
enum lsm_integrity_type type, const void *value, size_t size)
|