5718 lines · 166.6 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* * Security plug functions * * Copyright (C) 2001 WireX Communications, Inc <chris@wirex.com> * Copyright (C) 2001-2002 Greg Kroah-Hartman <greg@kroah.com> * Copyright (C) 2001 Networks Associates Technology, Inc <ssmalley@nai.com> * Copyright (C) 2016 Mellanox Technologies * Copyright (C) 2023 Microsoft Corporation <paul@paul-moore.com> */ #define pr_fmt(fmt) "LSM: " fmt #include <linux/bpf.h>#include <linux/capability.h>#include <linux/dcache.h>#include <linux/export.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/kernel_read_file.h>#include <linux/lsm_hooks.h>#include <linux/mman.h>#include <linux/mount.h>#include <linux/personality.h>#include <linux/backing-dev.h>#include <linux/string.h>#include <linux/xattr.h>#include <linux/msg.h>#include <linux/overflow.h>#include <linux/perf_event.h>#include <linux/fs.h>#include <net/flow.h>#include <net/sock.h> #include "lsm.h" /* * These are descriptions of the reasons that can be passed to the * security_locked_down() LSM hook. Placing this array here allows * all security modules to use the same descriptions for auditing * purposes. */const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX + 1] = {	[LOCKDOWN_NONE] = "none",	[LOCKDOWN_MODULE_SIGNATURE] = "unsigned module loading",	[LOCKDOWN_DEV_MEM] = "/dev/mem,kmem,port",	[LOCKDOWN_EFI_TEST] = "/dev/efi_test access",	[LOCKDOWN_KEXEC] = "kexec of unsigned images",	[LOCKDOWN_HIBERNATION] = "hibernation",	[LOCKDOWN_PCI_ACCESS] = "direct PCI access",	[LOCKDOWN_IOPORT] = "raw io port access",	[LOCKDOWN_MSR] = "raw MSR access",	[LOCKDOWN_ACPI_TABLES] = "modifying ACPI tables",	[LOCKDOWN_DEVICE_TREE] = "modifying device tree contents",	[LOCKDOWN_PCMCIA_CIS] = "direct PCMCIA CIS storage",	[LOCKDOWN_TIOCSSERIAL] = "reconfiguration of serial port IO",	[LOCKDOWN_MODULE_PARAMETERS] = "unsafe module parameters",	[LOCKDOWN_MMIOTRACE] = "unsafe mmio",	[LOCKDOWN_DEBUGFS] = "debugfs access",	[LOCKDOWN_XMON_WR] = "xmon write access",	[LOCKDOWN_BPF_WRITE_USER] = "use of bpf to write user RAM",	[LOCKDOWN_DBG_WRITE_KERNEL] = "use of kgdb/kdb to write kernel RAM",	[LOCKDOWN_RTAS_ERROR_INJECTION] = "RTAS error injection",	[LOCKDOWN_XEN_USER_ACTIONS] = "Xen guest user action",	[LOCKDOWN_INTEGRITY_MAX] = "integrity",	[LOCKDOWN_KCORE] = "/proc/kcore access",	[LOCKDOWN_KPROBES] = "use of kprobes",	[LOCKDOWN_BPF_READ_KERNEL] = "use of bpf to read kernel RAM",	[LOCKDOWN_DBG_READ_KERNEL] = "use of kgdb/kdb to read kernel RAM",	[LOCKDOWN_PERF] = "unsafe use of perf",	[LOCKDOWN_TRACEFS] = "use of tracefs",	[LOCKDOWN_XMON_RW] = "xmon read and write access",	[LOCKDOWN_XFRM_SECRET] = "xfrm SA secret",	[LOCKDOWN_CONFIDENTIALITY_MAX] = "confidentiality",}; bool lsm_debug __ro_after_init; unsigned int lsm_active_cnt __ro_after_init;const struct lsm_id *lsm_idlist[MAX_LSM_COUNT]; struct lsm_blob_sizes blob_sizes; struct kmem_cache *lsm_file_cache;struct kmem_cache *lsm_backing_file_cache;struct kmem_cache *lsm_inode_cache; #define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX /* * Identifier for the LSM static calls. * HOOK is an LSM hook as defined in linux/lsm_hookdefs.h * IDX is the index of the static call. 0 <= NUM < MAX_LSM_COUNT */#define LSM_STATIC_CALL(HOOK, IDX) lsm_static_call_##HOOK##_##IDX /* * Call the macro M for each LSM hook MAX_LSM_COUNT times. */#define LSM_LOOP_UNROLL(M, ...) 		\do {						\	UNROLL(MAX_LSM_COUNT, M, __VA_ARGS__)	\} while (0) #define LSM_DEFINE_UNROLL(M, ...) UNROLL(MAX_LSM_COUNT, M, __VA_ARGS__) #ifdef CONFIG_HAVE_STATIC_CALL#define LSM_HOOK_TRAMP(NAME, NUM) \	&STATIC_CALL_TRAMP(LSM_STATIC_CALL(NAME, NUM))#else#define LSM_HOOK_TRAMP(NAME, NUM) NULL#endif /* * Define static calls and static keys for each LSM hook. */#define DEFINE_LSM_STATIC_CALL(NUM, NAME, RET, ...)			\	DEFINE_STATIC_CALL_NULL(LSM_STATIC_CALL(NAME, NUM),		\				*((RET(*)(__VA_ARGS__))NULL));		\	static DEFINE_STATIC_KEY_FALSE(SECURITY_HOOK_ACTIVE_KEY(NAME, NUM)); #define LSM_HOOK(RET, DEFAULT, NAME, ...)				\	LSM_DEFINE_UNROLL(DEFINE_LSM_STATIC_CALL, NAME, RET, __VA_ARGS__)#include <linux/lsm_hook_defs.h>#undef LSM_HOOK#undef DEFINE_LSM_STATIC_CALL /* * Initialise a table of static calls for each LSM hook. * DEFINE_STATIC_CALL_NULL invocation above generates a key (STATIC_CALL_KEY) * and a trampoline (STATIC_CALL_TRAMP) which are used to call * __static_call_update when updating the static call. * * The static calls table is used by early LSMs, some architectures can fault on * unaligned accesses and the fault handling code may not be ready by then. * Thus, the static calls table should be aligned to avoid any unhandled faults * in early init. */struct lsm_static_calls_table	static_calls_table __ro_after_init __aligned(sizeof(u64)) = {#define INIT_LSM_STATIC_CALL(NUM, NAME)					\	(struct lsm_static_call) {					\		.key = &STATIC_CALL_KEY(LSM_STATIC_CALL(NAME, NUM)),	\		.trampoline = LSM_HOOK_TRAMP(NAME, NUM),		\		.active = &SECURITY_HOOK_ACTIVE_KEY(NAME, NUM),		\	},#define LSM_HOOK(RET, DEFAULT, NAME, ...)				\	.NAME = {							\		LSM_DEFINE_UNROLL(INIT_LSM_STATIC_CALL, NAME)		\	},#include <linux/lsm_hook_defs.h>#undef LSM_HOOK#undef INIT_LSM_STATIC_CALL	}; /** * lsm_file_alloc - allocate a composite file blob * @file: the file that needs a blob * * Allocate the file blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_file_alloc(struct file *file){	if (!lsm_file_cache) {		file->f_security = NULL;		return 0;	} 	file->f_security = kmem_cache_zalloc(lsm_file_cache, GFP_KERNEL);	if (file->f_security == NULL)		return -ENOMEM;	return 0;} /** * lsm_backing_file_alloc - allocate a composite backing file blob * @backing_file: the backing file * * Allocate the backing file blob for all the modules. * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_backing_file_alloc(struct file *backing_file){	void *blob; 	if (!lsm_backing_file_cache) {		backing_file_set_security(backing_file, NULL);		return 0;	} 	blob = kmem_cache_zalloc(lsm_backing_file_cache, GFP_KERNEL);	backing_file_set_security(backing_file, blob);	if (!blob)		return -ENOMEM;	return 0;} /** * lsm_blob_alloc - allocate a composite blob * @dest: the destination for the blob * @size: the size of the blob * @gfp: allocation type * * Allocate a blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_blob_alloc(void **dest, size_t size, gfp_t gfp){	if (size == 0) {		*dest = NULL;		return 0;	} 	*dest = kzalloc(size, gfp);	if (*dest == NULL)		return -ENOMEM;	return 0;} /** * lsm_cred_alloc - allocate a composite cred blob * @cred: the cred that needs a blob * @gfp: allocation type * * Allocate the cred blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */int lsm_cred_alloc(struct cred *cred, gfp_t gfp){	return lsm_blob_alloc(&cred->security, blob_sizes.lbs_cred, gfp);} /** * lsm_inode_alloc - allocate a composite inode blob * @inode: the inode that needs a blob * @gfp: allocation flags * * Allocate the inode blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_inode_alloc(struct inode *inode, gfp_t gfp){	if (!lsm_inode_cache) {		inode->i_security = NULL;		return 0;	} 	inode->i_security = kmem_cache_zalloc(lsm_inode_cache, gfp);	if (inode->i_security == NULL)		return -ENOMEM;	return 0;} /** * lsm_task_alloc - allocate a composite task blob * @task: the task that needs a blob * * Allocate the task blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */int lsm_task_alloc(struct task_struct *task){	return lsm_blob_alloc(&task->security, blob_sizes.lbs_task, GFP_KERNEL);} /** * lsm_ipc_alloc - allocate a composite ipc blob * @kip: the ipc that needs a blob * * Allocate the ipc blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_ipc_alloc(struct kern_ipc_perm *kip){	return lsm_blob_alloc(&kip->security, blob_sizes.lbs_ipc, GFP_KERNEL);} #ifdef CONFIG_KEYS/** * lsm_key_alloc - allocate a composite key blob * @key: the key that needs a blob * * Allocate the key blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_key_alloc(struct key *key){	return lsm_blob_alloc(&key->security, blob_sizes.lbs_key, GFP_KERNEL);}#endif /* CONFIG_KEYS */ /** * lsm_msg_msg_alloc - allocate a composite msg_msg blob * @mp: the msg_msg that needs a blob * * Allocate the ipc blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_msg_msg_alloc(struct msg_msg *mp){	return lsm_blob_alloc(&mp->security, blob_sizes.lbs_msg_msg,			      GFP_KERNEL);} /** * lsm_bdev_alloc - allocate a composite block_device blob * @bdev: the block_device that needs a blob * * Allocate the block_device blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_bdev_alloc(struct block_device *bdev){	return lsm_blob_alloc(&bdev->bd_security, blob_sizes.lbs_bdev,			      GFP_KERNEL);} #ifdef CONFIG_BPF_SYSCALL/** * lsm_bpf_map_alloc - allocate a composite bpf_map blob * @map: the bpf_map that needs a blob * * Allocate the bpf_map blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_bpf_map_alloc(struct bpf_map *map){	return lsm_blob_alloc(&map->security, blob_sizes.lbs_bpf_map, GFP_KERNEL);} /** * lsm_bpf_prog_alloc - allocate a composite bpf_prog blob * @prog: the bpf_prog that needs a blob * * Allocate the bpf_prog blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_bpf_prog_alloc(struct bpf_prog *prog){	return lsm_blob_alloc(&prog->aux->security, blob_sizes.lbs_bpf_prog, GFP_KERNEL);} /** * lsm_bpf_token_alloc - allocate a composite bpf_token blob * @token: the bpf_token that needs a blob * * Allocate the bpf_token blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_bpf_token_alloc(struct bpf_token *token){	return lsm_blob_alloc(&token->security, blob_sizes.lbs_bpf_token, GFP_KERNEL);}#endif /* CONFIG_BPF_SYSCALL */ /** * lsm_superblock_alloc - allocate a composite superblock blob * @sb: the superblock that needs a blob * * Allocate the superblock blob for all the modules * * Returns 0, or -ENOMEM if memory can't be allocated. */static int lsm_superblock_alloc(struct super_block *sb){	return lsm_blob_alloc(&sb->s_security, blob_sizes.lbs_superblock,			      GFP_KERNEL);} /** * lsm_fill_user_ctx - Fill a user space lsm_ctx structure * @uctx: a userspace LSM context to be filled * @uctx_len: available uctx size (input), used uctx size (output) * @val: the new LSM context value * @val_len: the size of the new LSM context value * @id: LSM id * @flags: LSM defined flags * * Fill all of the fields in a userspace lsm_ctx structure.  If @uctx is NULL * simply calculate the required size to output via @utc_len and return * success. * * Returns 0 on success, -E2BIG if userspace buffer is not large enough, * -EFAULT on a copyout error, -ENOMEM if memory can't be allocated. */int lsm_fill_user_ctx(struct lsm_ctx __user *uctx, u32 *uctx_len,		      void *val, size_t val_len,		      u64 id, u64 flags){	struct lsm_ctx *nctx = NULL;	size_t nctx_len;	int rc = 0; 	nctx_len = ALIGN(struct_size(nctx, ctx, val_len), sizeof(void *));	if (nctx_len > *uctx_len) {		rc = -E2BIG;		goto out;	} 	/* no buffer - return success/0 and set @uctx_len to the req size */	if (!uctx)		goto out; 	nctx = kzalloc(nctx_len, GFP_KERNEL);	if (nctx == NULL) {		rc = -ENOMEM;		goto out;	}	nctx->id = id;	nctx->flags = flags;	nctx->len = nctx_len;	nctx->ctx_len = val_len;	memcpy(nctx->ctx, val, val_len); 	if (copy_to_user(uctx, nctx, nctx_len))		rc = -EFAULT; out:	kfree(nctx);	*uctx_len = nctx_len;	return rc;} /* * The default value of the LSM hook is defined in linux/lsm_hook_defs.h and * can be accessed with: * *	LSM_RET_DEFAULT(<hook_name>) * * The macros below define static constants for the default value of each * LSM hook. */#define LSM_RET_DEFAULT(NAME) (NAME##_default)#define DECLARE_LSM_RET_DEFAULT_void(DEFAULT, NAME)#define DECLARE_LSM_RET_DEFAULT_int(DEFAULT, NAME) \	static const int __maybe_unused LSM_RET_DEFAULT(NAME) = (DEFAULT);#define LSM_HOOK(RET, DEFAULT, NAME, ...) \	DECLARE_LSM_RET_DEFAULT_##RET(DEFAULT, NAME) #include <linux/lsm_hook_defs.h>#undef LSM_HOOK /* * Hook list operation macros. * * call_void_hook: *	This is a hook that does not return a value. * * call_int_hook: *	This is a hook that returns a value. */#define __CALL_STATIC_VOID(NUM, HOOK, ...)				     \do {									     \	if (static_branch_unlikely(&SECURITY_HOOK_ACTIVE_KEY(HOOK, NUM))) {    \		static_call(LSM_STATIC_CALL(HOOK, NUM))(__VA_ARGS__);	     \	}								     \} while (0); #define call_void_hook(HOOK, ...)                                 \	do {                                                      \		LSM_LOOP_UNROLL(__CALL_STATIC_VOID, HOOK, __VA_ARGS__); \	} while (0)  #define __CALL_STATIC_INT(NUM, R, HOOK, LABEL, ...)			     \do {									     \	if (static_branch_unlikely(&SECURITY_HOOK_ACTIVE_KEY(HOOK, NUM))) {  \		R = static_call(LSM_STATIC_CALL(HOOK, NUM))(__VA_ARGS__);    \		if (R != LSM_RET_DEFAULT(HOOK))				     \			goto LABEL;					     \	}								     \} while (0); #define call_int_hook(HOOK, ...)					\({									\	__label__ OUT;							\	int RC = LSM_RET_DEFAULT(HOOK);					\									\	LSM_LOOP_UNROLL(__CALL_STATIC_INT, RC, HOOK, OUT, __VA_ARGS__);	\OUT:									\	RC;								\}) #define lsm_for_each_hook(scall, NAME)					\	for (scall = static_calls_table.NAME;				\	     scall - static_calls_table.NAME < MAX_LSM_COUNT; scall++)  \

Lines 1–500 of 5718.