From dd3a7ee91e0ce0b03d22e974a79e8247cc99959b Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Sat, 28 Sep 2024 11:13:13 -0700 Subject: hardening: Adjust dependencies in selection of MODVERSIONS MODVERSIONS recently grew a dependency on !COMPILE_TEST so that Rust could be more easily tested. However, this introduces a Kconfig warning when building allmodconfig with a clang version that supports RANDSTRUCT natively because RANDSTRUCT_FULL and RANDSTRUCT_PERFORMANCE select MODVERSIONS when MODULES is enabled, bypassing the !COMPILE_TEST dependency: WARNING: unmet direct dependencies detected for MODVERSIONS Depends on [n]: MODULES [=y] && !COMPILE_TEST [=y] Selected by [y]: - RANDSTRUCT_FULL [=y] && (CC_HAS_RANDSTRUCT [=y] || GCC_PLUGINS [=n]) && MODULES [=y] Add the !COMPILE_TEST dependency to the selections to clear up the warning. Fixes: 1f9c4a996756 ("Kbuild: make MODVERSIONS support depend on not being a compile test build") Signed-off-by: Nathan Chancellor Link: https://lore.kernel.org/r/20240928-fix-randstruct-modversions-kconfig-warning-v1-1-27d3edc8571e@kernel.org Signed-off-by: Kees Cook --- security/Kconfig.hardening | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 2cff851ebfd7..c9d5ca3d8d08 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -340,7 +340,7 @@ choice config RANDSTRUCT_FULL bool "Fully randomize structure layout" depends on CC_HAS_RANDSTRUCT || GCC_PLUGINS - select MODVERSIONS if MODULES + select MODVERSIONS if MODULES && !COMPILE_TEST help Fully randomize the member layout of sensitive structures as much as possible, which may have both a @@ -356,7 +356,7 @@ choice config RANDSTRUCT_PERFORMANCE bool "Limit randomization of structure layout to cache-lines" depends on GCC_PLUGINS - select MODVERSIONS if MODULES + select MODVERSIONS if MODULES && !COMPILE_TEST help Randomization of sensitive kernel structures will make a best effort at restricting randomization to cacheline-sized -- cgit v1.2.3 From c5e3cdbf2afedef77b64229fd0aed693abf0a0c4 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 3 Oct 2024 16:43:39 -0400 Subject: tomoyo: revert CONFIG_SECURITY_TOMOYO_LKM support This patch reverts two TOMOYO patches that were merged into Linus' tree during the v6.12 merge window: 8b985bbfabbe ("tomoyo: allow building as a loadable LSM module") 268225a1de1a ("tomoyo: preparation step for building as a loadable LSM module") Together these two patches introduced the CONFIG_SECURITY_TOMOYO_LKM Kconfig build option which enabled a TOMOYO specific dynamic LSM loading mechanism (see the original commits for more details). Unfortunately, this approach was widely rejected by the LSM community as well as some members of the general kernel community. Objections included concerns over setting a bad precedent regarding individual LSMs managing their LSM callback registrations as well as general kernel symbol exporting practices. With little to no support for the CONFIG_SECURITY_TOMOYO_LKM approach outside of Tetsuo, and multiple objections, we need to revert these changes. Link: https://lore.kernel.org/all/0c4b443a-9c72-4800-97e8-a3816b6a9ae2@I-love.SAKURA.ne.jp Link: https://lore.kernel.org/all/CAHC9VhR=QjdoHG3wJgHFJkKYBg7vkQH2MpffgVzQ0tAByo_wRg@mail.gmail.com Acked-by: John Johansen Signed-off-by: Paul Moore --- security/tomoyo/Kconfig | 15 - security/tomoyo/Makefile | 8 +- security/tomoyo/common.c | 14 +- security/tomoyo/common.h | 72 ----- security/tomoyo/gc.c | 3 - security/tomoyo/hooks.h | 515 --------------------------------- security/tomoyo/init.c | 366 ----------------------- security/tomoyo/load_policy.c | 12 - security/tomoyo/proxy.c | 82 ------ security/tomoyo/securityfs_if.c | 10 +- security/tomoyo/tomoyo.c | 623 ++++++++++++++++++++++++++++++++++++++++ security/tomoyo/util.c | 3 + 12 files changed, 632 insertions(+), 1091 deletions(-) delete mode 100644 security/tomoyo/hooks.h delete mode 100644 security/tomoyo/init.c delete mode 100644 security/tomoyo/proxy.c create mode 100644 security/tomoyo/tomoyo.c (limited to 'security') diff --git a/security/tomoyo/Kconfig b/security/tomoyo/Kconfig index 90eccc6cd464..1e0dd1a6d0b0 100644 --- a/security/tomoyo/Kconfig +++ b/security/tomoyo/Kconfig @@ -13,21 +13,6 @@ config SECURITY_TOMOYO found at . If you are unsure how to answer this question, answer N. -config SECURITY_TOMOYO_LKM - bool "Cut out most of TOMOYO's code to a loadable kernel module" - default n - depends on SECURITY_TOMOYO - depends on MODULES - help - Say Y here if you want to include TOMOYO without bloating - vmlinux file. If you say Y, most of TOMOYO code is cut out to - a loadable kernel module named tomoyo.ko . This option will be - useful for kernels built by Linux distributors where TOMOYO is - included but TOMOYO is not enabled by default. Please be sure - to explicitly load tomoyo.ko if you want to activate TOMOYO - without calling userspace policy loader, for tomoyo.ko is - loaded immediately before calling userspace policy loader. - config SECURITY_TOMOYO_MAX_ACCEPT_ENTRY int "Default maximal count for learning mode" default 2048 diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 287a7d16fa15..55c67b9846a9 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile @@ -1,11 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 -tomoyo-objs := audit.o common.o condition.o domain.o environ.o file.o gc.o group.o memory.o mount.o network.o proxy.o realpath.o securityfs_if.o util.o -obj-y += init.o load_policy.o -ifdef CONFIG_SECURITY_TOMOYO_LKM -obj-m += tomoyo.o -else -obj-y += tomoyo.o -endif +obj-y = audit.o common.o condition.o domain.o environ.o file.o gc.o group.o load_policy.o memory.o mount.o network.o realpath.o securityfs_if.o tomoyo.o util.o targets += builtin-policy.h diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index c0ef014f8009..5c7b059a332a 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -998,13 +998,8 @@ static bool tomoyo_select_domain(struct tomoyo_io_buffer *head, p = find_task_by_pid_ns(pid, &init_pid_ns); else p = find_task_by_vpid(pid); - if (p) { + if (p) domain = tomoyo_task(p)->domain_info; -#ifdef CONFIG_SECURITY_TOMOYO_LKM - if (!domain) - domain = &tomoyo_kernel_domain; -#endif - } rcu_read_unlock(); } else if (!strncmp(data, "domain=", 7)) { if (tomoyo_domain_def(data + 7)) @@ -1715,13 +1710,8 @@ static void tomoyo_read_pid(struct tomoyo_io_buffer *head) p = find_task_by_pid_ns(pid, &init_pid_ns); else p = find_task_by_vpid(pid); - if (p) { + if (p) domain = tomoyo_task(p)->domain_info; -#ifdef CONFIG_SECURITY_TOMOYO_LKM - if (!domain) - domain = &tomoyo_kernel_domain; -#endif - } rcu_read_unlock(); if (!domain) return; diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 4f6c52a9f478..0e8e2e959aef 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -978,7 +978,6 @@ int tomoyo_get_mode(const struct tomoyo_policy_namespace *ns, const u8 profile, int tomoyo_init_request_info(struct tomoyo_request_info *r, struct tomoyo_domain_info *domain, const u8 index); -int __init tomoyo_interface_init(void); int tomoyo_mkdev_perm(const u8 operation, const struct path *path, const unsigned int mode, unsigned int dev); int tomoyo_mount_permission(const char *dev_name, const struct path *path, @@ -1215,14 +1214,10 @@ static inline void tomoyo_put_group(struct tomoyo_group *group) * * Returns pointer to "struct tomoyo_task" for specified thread. */ -#ifdef CONFIG_SECURITY_TOMOYO_LKM -extern struct tomoyo_task *tomoyo_task(struct task_struct *task); -#else static inline struct tomoyo_task *tomoyo_task(struct task_struct *task) { return task->security + tomoyo_blob_sizes.lbs_task; } -#endif /** * tomoyo_same_name_union - Check for duplicated "struct tomoyo_name_union" entry. @@ -1289,71 +1284,4 @@ static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void) pos = srcu_dereference((head)->next, &tomoyo_ss); \ for ( ; pos != (head); pos = srcu_dereference(pos->next, &tomoyo_ss)) -#ifdef CONFIG_SECURITY_TOMOYO_LKM - -#define LSM_HOOK(RET, DEFAULT, NAME, ...) typedef RET (NAME##_t)(__VA_ARGS__); -#include -#undef LSM_HOOK - -struct tomoyo_hooks { - cred_prepare_t *cred_prepare; - bprm_committed_creds_t *bprm_committed_creds; - task_alloc_t *task_alloc; - task_free_t *task_free; - bprm_check_security_t *bprm_check_security; - file_fcntl_t *file_fcntl; - file_open_t *file_open; - file_truncate_t *file_truncate; - path_truncate_t *path_truncate; - path_unlink_t *path_unlink; - path_mkdir_t *path_mkdir; - path_rmdir_t *path_rmdir; - path_symlink_t *path_symlink; - path_mknod_t *path_mknod; - path_link_t *path_link; - path_rename_t *path_rename; - inode_getattr_t *inode_getattr; - file_ioctl_t *file_ioctl; - file_ioctl_compat_t *file_ioctl_compat; - path_chmod_t *path_chmod; - path_chown_t *path_chown; - path_chroot_t *path_chroot; - sb_mount_t *sb_mount; - sb_umount_t *sb_umount; - sb_pivotroot_t *sb_pivotroot; - socket_bind_t *socket_bind; - socket_connect_t *socket_connect; - socket_listen_t *socket_listen; - socket_sendmsg_t *socket_sendmsg; -}; - -extern void tomoyo_register_hooks(const struct tomoyo_hooks *tomoyo_hooks); - -struct tomoyo_operations { - void (*check_profile)(void); - int enabled; -}; - -extern struct tomoyo_operations tomoyo_ops; - -/* - * Temporary hack: functions needed by tomoyo.ko . This will be removed - * after all functions are marked as EXPORT_STMBOL_GPL(). - */ -struct tomoyo_tmp_exports { - struct task_struct * (*find_task_by_vpid)(pid_t nr); - struct task_struct * (*find_task_by_pid_ns)(pid_t nr, struct pid_namespace *ns); - void (*put_filesystem)(struct file_system_type *fs); - struct file * (*get_mm_exe_file)(struct mm_struct *mm); - char * (*d_absolute_path)(const struct path *path, char *buf, int buflen); -}; -extern const struct tomoyo_tmp_exports tomoyo_tmp_exports; -#define find_task_by_vpid tomoyo_tmp_exports.find_task_by_vpid -#define find_task_by_pid_ns tomoyo_tmp_exports.find_task_by_pid_ns -#define put_filesystem tomoyo_tmp_exports.put_filesystem -#define get_mm_exe_file tomoyo_tmp_exports.get_mm_exe_file -#define d_absolute_path tomoyo_tmp_exports.d_absolute_path - -#endif /* defined(CONFIG_SECURITY_TOMOYO_LKM) */ - #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c index 6eccca150839..026e29ea3796 100644 --- a/security/tomoyo/gc.c +++ b/security/tomoyo/gc.c @@ -9,9 +9,6 @@ #include #include -/* Lock for GC. */ -DEFINE_SRCU(tomoyo_ss); - /** * tomoyo_memory_free - Free memory for elements. * diff --git a/security/tomoyo/hooks.h b/security/tomoyo/hooks.h deleted file mode 100644 index 58929bb71477..000000000000 --- a/security/tomoyo/hooks.h +++ /dev/null @@ -1,515 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * security/tomoyo/hooks.h - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include "common.h" - -/** - * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. - * - * Returns pointer to "struct tomoyo_domain_info" for current thread. - */ -struct tomoyo_domain_info *tomoyo_domain(void) -{ - struct tomoyo_task *s = tomoyo_task(current); - - return s->domain_info; -} - -/** - * tomoyo_cred_prepare - Target for security_prepare_creds(). - * - * @new: Pointer to "struct cred". - * @old: Pointer to "struct cred". - * @gfp: Memory allocation flags. - * - * Returns 0. - */ -static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, - gfp_t gfp) -{ - /* Restore old_domain_info saved by previous execve() request. */ - struct tomoyo_task *s = tomoyo_task(current); - - if (s->old_domain_info && !current->in_execve) { - atomic_dec(&s->domain_info->users); - s->domain_info = s->old_domain_info; - s->old_domain_info = NULL; - } - return 0; -} - -/** - * tomoyo_bprm_committed_creds - Target for security_bprm_committed_creds(). - * - * @bprm: Pointer to "struct linux_binprm". - */ -static void tomoyo_bprm_committed_creds(const struct linux_binprm *bprm) -{ - /* Clear old_domain_info saved by execve() request. */ - struct tomoyo_task *s = tomoyo_task(current); - - atomic_dec(&s->old_domain_info->users); - s->old_domain_info = NULL; -} - -/** - * tomoyo_bprm_check_security - Target for security_bprm_check(). - * - * @bprm: Pointer to "struct linux_binprm". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_bprm_check_security(struct linux_binprm *bprm) -{ - struct tomoyo_task *s = tomoyo_task(current); - - /* - * Execute permission is checked against pathname passed to execve() - * using current domain. - */ - if (!s->old_domain_info) { - const int idx = tomoyo_read_lock(); - const int err = tomoyo_find_next_domain(bprm); - - tomoyo_read_unlock(idx); - return err; - } - /* - * Read permission is checked against interpreters using next domain. - */ - return tomoyo_check_open_permission(s->domain_info, - &bprm->file->f_path, O_RDONLY); -} - -/** - * tomoyo_inode_getattr - Target for security_inode_getattr(). - * - * @path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_inode_getattr(const struct path *path) -{ - return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL); -} - -/** - * tomoyo_path_truncate - Target for security_path_truncate(). - * - * @path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_truncate(const struct path *path) -{ - return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); -} - -/** - * tomoyo_file_truncate - Target for security_file_truncate(). - * - * @file: Pointer to "struct file". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_file_truncate(struct file *file) -{ - return tomoyo_path_truncate(&file->f_path); -} - -/** - * tomoyo_path_unlink - Target for security_path_unlink(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) -{ - struct path path = { .mnt = parent->mnt, .dentry = dentry }; - - return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); -} - -/** - * tomoyo_path_mkdir - Target for security_path_mkdir(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * @mode: DAC permission mode. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, - umode_t mode) -{ - struct path path = { .mnt = parent->mnt, .dentry = dentry }; - - return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, - mode & S_IALLUGO); -} - -/** - * tomoyo_path_rmdir - Target for security_path_rmdir(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) -{ - struct path path = { .mnt = parent->mnt, .dentry = dentry }; - - return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); -} - -/** - * tomoyo_path_symlink - Target for security_path_symlink(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * @old_name: Symlink's content. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, - const char *old_name) -{ - struct path path = { .mnt = parent->mnt, .dentry = dentry }; - - return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); -} - -/** - * tomoyo_path_mknod - Target for security_path_mknod(). - * - * @parent: Pointer to "struct path". - * @dentry: Pointer to "struct dentry". - * @mode: DAC permission mode. - * @dev: Device attributes. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, - umode_t mode, unsigned int dev) -{ - struct path path = { .mnt = parent->mnt, .dentry = dentry }; - int type = TOMOYO_TYPE_CREATE; - const unsigned int perm = mode & S_IALLUGO; - - switch (mode & S_IFMT) { - case S_IFCHR: - type = TOMOYO_TYPE_MKCHAR; - break; - case S_IFBLK: - type = TOMOYO_TYPE_MKBLOCK; - break; - default: - goto no_dev; - } - return tomoyo_mkdev_perm(type, &path, perm, dev); - no_dev: - switch (mode & S_IFMT) { - case S_IFIFO: - type = TOMOYO_TYPE_MKFIFO; - break; - case S_IFSOCK: - type = TOMOYO_TYPE_MKSOCK; - break; - } - return tomoyo_path_number_perm(type, &path, perm); -} - -/** - * tomoyo_path_link - Target for security_path_link(). - * - * @old_dentry: Pointer to "struct dentry". - * @new_dir: Pointer to "struct path". - * @new_dentry: Pointer to "struct dentry". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry) -{ - struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; - struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; - - return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); -} - -/** - * tomoyo_path_rename - Target for security_path_rename(). - * - * @old_parent: Pointer to "struct path". - * @old_dentry: Pointer to "struct dentry". - * @new_parent: Pointer to "struct path". - * @new_dentry: Pointer to "struct dentry". - * @flags: Rename options. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_rename(const struct path *old_parent, - struct dentry *old_dentry, - const struct path *new_parent, - struct dentry *new_dentry, - const unsigned int flags) -{ - struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; - struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; - - if (flags & RENAME_EXCHANGE) { - const int err = tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path2, - &path1); - - if (err) - return err; - } - return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); -} - -/** - * tomoyo_file_fcntl - Target for security_file_fcntl(). - * - * @file: Pointer to "struct file". - * @cmd: Command for fcntl(). - * @arg: Argument for @cmd. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) - return 0; - return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, - O_WRONLY | (arg & O_APPEND)); -} - -/** - * tomoyo_file_open - Target for security_file_open(). - * - * @f: Pointer to "struct file". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_file_open(struct file *f) -{ - /* Don't check read permission here if called from execve(). */ - /* Illogically, FMODE_EXEC is in f_flags, not f_mode. */ - if (f->f_flags & __FMODE_EXEC) - return 0; - return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, - f->f_flags); -} - -/** - * tomoyo_file_ioctl - Target for security_file_ioctl(). - * - * @file: Pointer to "struct file". - * @cmd: Command for ioctl(). - * @arg: Argument for @cmd. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) -{ - return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); -} - -/** - * tomoyo_path_chmod - Target for security_path_chmod(). - * - * @path: Pointer to "struct path". - * @mode: DAC permission mode. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_chmod(const struct path *path, umode_t mode) -{ - return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path, - mode & S_IALLUGO); -} - -/** - * tomoyo_path_chown - Target for security_path_chown(). - * - * @path: Pointer to "struct path". - * @uid: Owner ID. - * @gid: Group ID. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) -{ - int error = 0; - - if (uid_valid(uid)) - error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, - from_kuid(&init_user_ns, uid)); - if (!error && gid_valid(gid)) - error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, - from_kgid(&init_user_ns, gid)); - return error; -} - -/** - * tomoyo_path_chroot - Target for security_path_chroot(). - * - * @path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_path_chroot(const struct path *path) -{ - return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); -} - -/** - * tomoyo_sb_mount - Target for security_sb_mount(). - * - * @dev_name: Name of device file. Maybe NULL. - * @path: Pointer to "struct path". - * @type: Name of filesystem type. Maybe NULL. - * @flags: Mount options. - * @data: Optional data. Maybe NULL. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_mount(const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data) -{ - return tomoyo_mount_permission(dev_name, path, type, flags, data); -} - -/** - * tomoyo_sb_umount - Target for security_sb_umount(). - * - * @mnt: Pointer to "struct vfsmount". - * @flags: Unmount options. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) -{ - struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; - - return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); -} - -/** - * tomoyo_sb_pivotroot - Target for security_sb_pivotroot(). - * - * @old_path: Pointer to "struct path". - * @new_path: Pointer to "struct path". - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_sb_pivotroot(const struct path *old_path, const struct path *new_path) -{ - return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); -} - -/** - * tomoyo_socket_listen - Check permission for listen(). - * - * @sock: Pointer to "struct socket". - * @backlog: Backlog parameter. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_listen(struct socket *sock, int backlog) -{ - return tomoyo_socket_listen_permission(sock); -} - -/** - * tomoyo_socket_connect - Check permission for connect(). - * - * @sock: Pointer to "struct socket". - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, - int addr_len) -{ - return tomoyo_socket_connect_permission(sock, addr, addr_len); -} - -/** - * tomoyo_socket_bind - Check permission for bind(). - * - * @sock: Pointer to "struct socket". - * @addr: Pointer to "struct sockaddr". - * @addr_len: Size of @addr. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, - int addr_len) -{ - return tomoyo_socket_bind_permission(sock, addr, addr_len); -} - -/** - * tomoyo_socket_sendmsg - Check permission for sendmsg(). - * - * @sock: Pointer to "struct socket". - * @msg: Pointer to "struct msghdr". - * @size: Size of message. - * - * Returns 0 on success, negative value otherwise. - */ -static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, - int size) -{ - return tomoyo_socket_sendmsg_permission(sock, msg, size); -} - -/** - * tomoyo_task_alloc - Target for security_task_alloc(). - * - * @task: Pointer to "struct task_struct". - * @clone_flags: clone() flags. - * - * Returns 0. - */ -static int tomoyo_task_alloc(struct task_struct *task, - unsigned long clone_flags) -{ - struct tomoyo_task *old = tomoyo_task(current); - struct tomoyo_task *new = tomoyo_task(task); - - new->domain_info = old->domain_info; - atomic_inc(&new->domain_info->users); - new->old_domain_info = NULL; - return 0; -} - -/** - * tomoyo_task_free - Target for security_task_free(). - * - * @task: Pointer to "struct task_struct". - */ -static void tomoyo_task_free(struct task_struct *task) -{ - struct tomoyo_task *s = tomoyo_task(task); - - if (s->domain_info) { - atomic_dec(&s->domain_info->users); - s->domain_info = NULL; - } - if (s->old_domain_info) { - atomic_dec(&s->old_domain_info->users); - s->old_domain_info = NULL; - } -} diff --git a/security/tomoyo/init.c b/security/tomoyo/init.c deleted file mode 100644 index 034e7db22d4e..000000000000 --- a/security/tomoyo/init.c +++ /dev/null @@ -1,366 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * security/tomoyo/init.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include -#include -#include "common.h" - -#ifndef CONFIG_SECURITY_TOMOYO_LKM - -#include "hooks.h" - -#else - -#define DEFINE_STATIC_CALL_PROXY(NAME) \ - static NAME##_t tomoyo_##NAME; \ - DEFINE_STATIC_CALL_RET0(tomoyo_##NAME, tomoyo_##NAME); -DEFINE_STATIC_CALL_PROXY(cred_prepare) -DEFINE_STATIC_CALL_PROXY(bprm_committed_creds) -DEFINE_STATIC_CALL_PROXY(bprm_check_security) -DEFINE_STATIC_CALL_PROXY(inode_getattr) -DEFINE_STATIC_CALL_PROXY(path_truncate) -DEFINE_STATIC_CALL_PROXY(file_truncate) -DEFINE_STATIC_CALL_PROXY(path_unlink) -DEFINE_STATIC_CALL_PROXY(path_mkdir) -DEFINE_STATIC_CALL_PROXY(path_rmdir) -DEFINE_STATIC_CALL_PROXY(path_symlink) -DEFINE_STATIC_CALL_PROXY(path_mknod) -DEFINE_STATIC_CALL_PROXY(path_link) -DEFINE_STATIC_CALL_PROXY(path_rename) -DEFINE_STATIC_CALL_PROXY(file_fcntl) -DEFINE_STATIC_CALL_PROXY(file_open) -DEFINE_STATIC_CALL_PROXY(file_ioctl) -DEFINE_STATIC_CALL_PROXY(path_chmod) -DEFINE_STATIC_CALL_PROXY(path_chown) -DEFINE_STATIC_CALL_PROXY(path_chroot) -DEFINE_STATIC_CALL_PROXY(sb_mount) -DEFINE_STATIC_CALL_PROXY(sb_umount) -DEFINE_STATIC_CALL_PROXY(sb_pivotroot) -DEFINE_STATIC_CALL_PROXY(socket_listen) -DEFINE_STATIC_CALL_PROXY(socket_connect) -DEFINE_STATIC_CALL_PROXY(socket_bind) -DEFINE_STATIC_CALL_PROXY(socket_sendmsg) -DEFINE_STATIC_CALL_PROXY(task_alloc) -DEFINE_STATIC_CALL_PROXY(task_free) -#undef DEFINE_STATIC_CALL_PROXY - -static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, gfp_t gfp) -{ - return static_call(tomoyo_cred_prepare)(new, old, gfp); -} - -static void tomoyo_bprm_committed_creds(const struct linux_binprm *bprm) -{ - static_call(tomoyo_bprm_committed_creds)(bprm); -} - -static int tomoyo_bprm_check_security(struct linux_binprm *bprm) -{ - return static_call(tomoyo_bprm_check_security)(bprm); -} - -static int tomoyo_inode_getattr(const struct path *path) -{ - return static_call(tomoyo_inode_getattr)(path); -} - -static int tomoyo_path_truncate(const struct path *path) -{ - return static_call(tomoyo_path_truncate)(path); -} - -static int tomoyo_file_truncate(struct file *file) -{ - return static_call(tomoyo_file_truncate)(file); -} - -static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) -{ - return static_call(tomoyo_path_unlink)(parent, dentry); -} - -static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, umode_t mode) -{ - return static_call(tomoyo_path_mkdir)(parent, dentry, mode); -} - -static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) -{ - return static_call(tomoyo_path_rmdir)(parent, dentry); -} - -static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, - const char *old_name) -{ - return static_call(tomoyo_path_symlink)(parent, dentry, old_name); -} - -static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, - umode_t mode, unsigned int dev) -{ - return static_call(tomoyo_path_mknod)(parent, dentry, mode, dev); -} - -static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, - struct dentry *new_dentry) -{ - return static_call(tomoyo_path_link)(old_dentry, new_dir, new_dentry); -} - -static int tomoyo_path_rename(const struct path *old_parent, struct dentry *old_dentry, - const struct path *new_parent, struct dentry *new_dentry, - const unsigned int flags) -{ - return static_call(tomoyo_path_rename)(old_parent, old_dentry, new_parent, new_dentry, flags); -} - -static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return static_call(tomoyo_file_fcntl)(file, cmd, arg); -} - -static int tomoyo_file_open(struct file *f) -{ - return static_call(tomoyo_file_open)(f); -} - -static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - return static_call(tomoyo_file_ioctl)(file, cmd, arg); -} - -static int tomoyo_path_chmod(const struct path *path, umode_t mode) -{ - return static_call(tomoyo_path_chmod)(path, mode); -} - -static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) -{ - return static_call(tomoyo_path_chown)(path, uid, gid); -} - -static int tomoyo_path_chroot(const struct path *path) -{ - return static_call(tomoyo_path_chroot)(path); -} - -static int tomoyo_sb_mount(const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data) -{ - return static_call(tomoyo_sb_mount)(dev_name, path, type, flags, data); -} - -static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) -{ - return static_call(tomoyo_sb_umount)(mnt, flags); -} - -static int tomoyo_sb_pivotroot(const struct path *old_path, const struct path *new_path) -{ - return static_call(tomoyo_sb_pivotroot)(old_path, new_path); -} - -static int tomoyo_socket_listen(struct socket *sock, int backlog) -{ - return static_call(tomoyo_socket_listen)(sock, backlog); -} - -static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, int addr_len) -{ - return static_call(tomoyo_socket_connect)(sock, addr, addr_len); -} - -static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, int addr_len) -{ - return static_call(tomoyo_socket_bind)(sock, addr, addr_len); -} - -static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) -{ - return static_call(tomoyo_socket_sendmsg)(sock, msg, size); -} - -static int tomoyo_task_alloc(struct task_struct *task, unsigned long clone_flags) -{ - return static_call(tomoyo_task_alloc)(task, clone_flags); -} - -static void tomoyo_task_free(struct task_struct *task) -{ - static_call(tomoyo_task_free)(task); -} - -void tomoyo_register_hooks(const struct tomoyo_hooks *tomoyo_hooks) -{ - static void *registered; - - if (cmpxchg(®istered, NULL, ®istered)) - panic("%s was called twice!\n", __func__); - static_call_update(tomoyo_task_free, tomoyo_hooks->task_free); - static_call_update(tomoyo_task_alloc, tomoyo_hooks->task_alloc); - static_call_update(tomoyo_cred_prepare, tomoyo_hooks->cred_prepare); - static_call_update(tomoyo_bprm_committed_creds, tomoyo_hooks->bprm_committed_creds); - static_call_update(tomoyo_bprm_check_security, tomoyo_hooks->bprm_check_security); - static_call_update(tomoyo_inode_getattr, tomoyo_hooks->inode_getattr); - static_call_update(tomoyo_path_truncate, tomoyo_hooks->path_truncate); - static_call_update(tomoyo_file_truncate, tomoyo_hooks->file_truncate); - static_call_update(tomoyo_path_unlink, tomoyo_hooks->path_unlink); - static_call_update(tomoyo_path_mkdir, tomoyo_hooks->path_mkdir); - static_call_update(tomoyo_path_rmdir, tomoyo_hooks->path_rmdir); - static_call_update(tomoyo_path_symlink, tomoyo_hooks->path_symlink); - static_call_update(tomoyo_path_mknod, tomoyo_hooks->path_mknod); - static_call_update(tomoyo_path_link, tomoyo_hooks->path_link); - static_call_update(tomoyo_path_rename, tomoyo_hooks->path_rename); - static_call_update(tomoyo_file_fcntl, tomoyo_hooks->file_fcntl); - static_call_update(tomoyo_file_open, tomoyo_hooks->file_open); - static_call_update(tomoyo_file_ioctl, tomoyo_hooks->file_ioctl); - static_call_update(tomoyo_path_chmod, tomoyo_hooks->path_chmod); - static_call_update(tomoyo_path_chown, tomoyo_hooks->path_chown); - static_call_update(tomoyo_path_chroot, tomoyo_hooks->path_chroot); - static_call_update(tomoyo_sb_mount, tomoyo_hooks->sb_mount); - static_call_update(tomoyo_sb_umount, tomoyo_hooks->sb_umount); - static_call_update(tomoyo_sb_pivotroot, tomoyo_hooks->sb_pivotroot); - static_call_update(tomoyo_socket_listen, tomoyo_hooks->socket_listen); - static_call_update(tomoyo_socket_connect, tomoyo_hooks->socket_connect); - static_call_update(tomoyo_socket_bind, tomoyo_hooks->socket_bind); - static_call_update(tomoyo_socket_sendmsg, tomoyo_hooks->socket_sendmsg); -} -EXPORT_SYMBOL_GPL(tomoyo_register_hooks); - -/* - * Temporary hack: functions needed by tomoyo.ko . This hack will be removed - * after all functions are marked as EXPORT_STMBOL_GPL(). - */ -#undef find_task_by_vpid -#undef find_task_by_pid_ns -#undef put_filesystem -#undef get_mm_exe_file -#undef d_absolute_path -const struct tomoyo_tmp_exports tomoyo_tmp_exports = { - .find_task_by_vpid = find_task_by_vpid, - .find_task_by_pid_ns = find_task_by_pid_ns, - .put_filesystem = put_filesystem, - .get_mm_exe_file = get_mm_exe_file, - .d_absolute_path = d_absolute_path, -}; -EXPORT_SYMBOL_GPL(tomoyo_tmp_exports); - -#endif - -#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER -static int tomoyo_bprm_creds_for_exec(struct linux_binprm *bprm) -{ - /* - * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested - * for the first time. - */ - if (!tomoyo_policy_loaded) - tomoyo_load_policy(bprm->filename); - return 0; -} -#endif - -struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = { - .lbs_task = sizeof(struct tomoyo_task), -}; - -static const struct lsm_id tomoyo_lsmid = { - .name = "tomoyo", - .id = LSM_ID_TOMOYO, -}; - -/* tomoyo_hooks is used for registering TOMOYO. */ -static struct security_hook_list tomoyo_hooks[] __ro_after_init = { - LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), - LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds), - LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc), - LSM_HOOK_INIT(task_free, tomoyo_task_free), -#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER - LSM_HOOK_INIT(bprm_creds_for_exec, tomoyo_bprm_creds_for_exec), -#endif - LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), - LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), - LSM_HOOK_INIT(file_open, tomoyo_file_open), - LSM_HOOK_INIT(file_truncate, tomoyo_file_truncate), - LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate), - LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink), - LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir), - LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir), - LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink), - LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod), - LSM_HOOK_INIT(path_link, tomoyo_path_link), - LSM_HOOK_INIT(path_rename, tomoyo_path_rename), - LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr), - LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl), - LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl), - LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod), - LSM_HOOK_INIT(path_chown, tomoyo_path_chown), - LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot), - LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount), - LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount), - LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot), - LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind), - LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect), - LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen), - LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg), -}; - -int tomoyo_enabled __ro_after_init = 1; - -/* Has /sbin/init started? */ -bool tomoyo_policy_loaded; - -#ifdef CONFIG_SECURITY_TOMOYO_LKM -EXPORT_SYMBOL_GPL(tomoyo_blob_sizes); -EXPORT_SYMBOL_GPL(tomoyo_policy_loaded); - -struct tomoyo_operations tomoyo_ops; -EXPORT_SYMBOL_GPL(tomoyo_ops); - -/** - * tomoyo_init - Reserve hooks for TOMOYO Linux. - * - * Returns 0. - */ -static int __init tomoyo_init(void) -{ - /* register ourselves with the security framework */ - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), &tomoyo_lsmid); - tomoyo_ops.enabled = tomoyo_enabled; - pr_info("Hooks for initializing TOMOYO Linux are ready\n"); - return 0; -} -#else -/** - * tomoyo_init - Register TOMOYO Linux as a LSM module. - * - * Returns 0. - */ -static int __init tomoyo_init(void) -{ - struct tomoyo_task *s = tomoyo_task(current); - - /* register ourselves with the security framework */ - security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), - &tomoyo_lsmid); - pr_info("TOMOYO Linux initialized\n"); - s->domain_info = &tomoyo_kernel_domain; - atomic_inc(&tomoyo_kernel_domain.users); - s->old_domain_info = NULL; - tomoyo_mm_init(); - - return 0; -} -#endif - -DEFINE_LSM(tomoyo) = { - .name = "tomoyo", - .enabled = &tomoyo_enabled, - .flags = LSM_FLAG_LEGACY_MAJOR, - .blobs = &tomoyo_blob_sizes, - .init = tomoyo_init, -}; diff --git a/security/tomoyo/load_policy.c b/security/tomoyo/load_policy.c index 6a2a72354a64..363b65be87ab 100644 --- a/security/tomoyo/load_policy.c +++ b/security/tomoyo/load_policy.c @@ -97,14 +97,6 @@ void tomoyo_load_policy(const char *filename) if (!tomoyo_policy_loader_exists()) return; done = true; -#ifdef CONFIG_SECURITY_TOMOYO_LKM - /* Load tomoyo.ko if not yet loaded. */ - if (!tomoyo_ops.check_profile) - request_module("tomoyo"); - /* Check if tomoyo.ko was successfully loaded. */ - if (!tomoyo_ops.check_profile) - panic("Failed to load tomoyo module."); -#endif pr_info("Calling %s to load policy. Please wait.\n", tomoyo_loader); argv[0] = (char *) tomoyo_loader; argv[1] = NULL; @@ -112,11 +104,7 @@ void tomoyo_load_policy(const char *filename) envp[1] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin"; envp[2] = NULL; call_usermodehelper(argv[0], argv, envp, UMH_WAIT_PROC); -#ifdef CONFIG_SECURITY_TOMOYO_LKM - tomoyo_ops.check_profile(); -#else tomoyo_check_profile(); -#endif } #endif diff --git a/security/tomoyo/proxy.c b/security/tomoyo/proxy.c deleted file mode 100644 index 1618cc0f2af8..000000000000 --- a/security/tomoyo/proxy.c +++ /dev/null @@ -1,82 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * security/tomoyo/proxy.c - * - * Copyright (C) 2005-2011 NTT DATA CORPORATION - */ - -#include -#include "common.h" - -#ifdef CONFIG_SECURITY_TOMOYO_LKM - -struct tomoyo_task *tomoyo_task(struct task_struct *task) -{ - struct tomoyo_task *s = task->security + tomoyo_blob_sizes.lbs_task; - - if (unlikely(!s->domain_info)) { - if (likely(task == current)) { - s->domain_info = &tomoyo_kernel_domain; - atomic_inc(&tomoyo_kernel_domain.users); - } else { - /* Caller handles s->domain_info == NULL case. */ - } - } - return s; -} - -#include "hooks.h" - -/** - * tomoyo_runtime_init - Register TOMOYO Linux as a loadable LSM module. - * - * Returns 0 if TOMOYO is enabled, -EINVAL otherwise. - */ -static int __init tomoyo_runtime_init(void) -{ - const struct tomoyo_hooks tomoyo_hooks = { - .cred_prepare = tomoyo_cred_prepare, - .bprm_committed_creds = tomoyo_bprm_committed_creds, - .task_alloc = tomoyo_task_alloc, - .task_free = tomoyo_task_free, - .bprm_check_security = tomoyo_bprm_check_security, - .file_fcntl = tomoyo_file_fcntl, - .file_open = tomoyo_file_open, - .file_truncate = tomoyo_file_truncate, - .path_truncate = tomoyo_path_truncate, - .path_unlink = tomoyo_path_unlink, - .path_mkdir = tomoyo_path_mkdir, - .path_rmdir = tomoyo_path_rmdir, - .path_symlink = tomoyo_path_symlink, - .path_mknod = tomoyo_path_mknod, - .path_link = tomoyo_path_link, - .path_rename = tomoyo_path_rename, - .inode_getattr = tomoyo_inode_getattr, - .file_ioctl = tomoyo_file_ioctl, - .file_ioctl_compat = tomoyo_file_ioctl, - .path_chmod = tomoyo_path_chmod, - .path_chown = tomoyo_path_chown, - .path_chroot = tomoyo_path_chroot, - .sb_mount = tomoyo_sb_mount, - .sb_umount = tomoyo_sb_umount, - .sb_pivotroot = tomoyo_sb_pivotroot, - .socket_bind = tomoyo_socket_bind, - .socket_connect = tomoyo_socket_connect, - .socket_listen = tomoyo_socket_listen, - .socket_sendmsg = tomoyo_socket_sendmsg, - }; - - if (!tomoyo_ops.enabled) - return -EINVAL; - tomoyo_ops.check_profile = tomoyo_check_profile; - pr_info("TOMOYO Linux initialized\n"); - tomoyo_task(current); - tomoyo_mm_init(); - tomoyo_interface_init(); - tomoyo_register_hooks(&tomoyo_hooks); - return 0; -} -module_init(tomoyo_runtime_init); -MODULE_LICENSE("GPL"); - -#endif diff --git a/security/tomoyo/securityfs_if.c b/security/tomoyo/securityfs_if.c index a3b821b7f477..a2705798476f 100644 --- a/security/tomoyo/securityfs_if.c +++ b/security/tomoyo/securityfs_if.c @@ -229,19 +229,17 @@ static void __init tomoyo_create_entry(const char *name, const umode_t mode, } /** - * tomoyo_interface_init - Initialize /sys/kernel/security/tomoyo/ interface. + * tomoyo_initerface_init - Initialize /sys/kernel/security/tomoyo/ interface. * * Returns 0. */ -int __init tomoyo_interface_init(void) +static int __init tomoyo_initerface_init(void) { struct tomoyo_domain_info *domain; struct dentry *tomoyo_dir; -#ifndef CONFIG_SECURITY_TOMOYO_LKM if (!tomoyo_enabled) return 0; -#endif domain = tomoyo_domain(); /* Don't create securityfs entries unless registered. */ if (domain != &tomoyo_kernel_domain) @@ -272,6 +270,4 @@ int __init tomoyo_interface_init(void) return 0; } -#ifndef CONFIG_SECURITY_TOMOYO_LKM -fs_initcall(tomoyo_interface_init); -#endif +fs_initcall(tomoyo_initerface_init); diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c new file mode 100644 index 000000000000..04a92c3d65d4 --- /dev/null +++ b/security/tomoyo/tomoyo.c @@ -0,0 +1,623 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * security/tomoyo/tomoyo.c + * + * Copyright (C) 2005-2011 NTT DATA CORPORATION + */ + +#include +#include +#include "common.h" + +/** + * tomoyo_domain - Get "struct tomoyo_domain_info" for current thread. + * + * Returns pointer to "struct tomoyo_domain_info" for current thread. + */ +struct tomoyo_domain_info *tomoyo_domain(void) +{ + struct tomoyo_task *s = tomoyo_task(current); + + if (s->old_domain_info && !current->in_execve) { + atomic_dec(&s->old_domain_info->users); + s->old_domain_info = NULL; + } + return s->domain_info; +} + +/** + * tomoyo_cred_prepare - Target for security_prepare_creds(). + * + * @new: Pointer to "struct cred". + * @old: Pointer to "struct cred". + * @gfp: Memory allocation flags. + * + * Returns 0. + */ +static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, + gfp_t gfp) +{ + /* Restore old_domain_info saved by previous execve() request. */ + struct tomoyo_task *s = tomoyo_task(current); + + if (s->old_domain_info && !current->in_execve) { + atomic_dec(&s->domain_info->users); + s->domain_info = s->old_domain_info; + s->old_domain_info = NULL; + } + return 0; +} + +/** + * tomoyo_bprm_committed_creds - Target for security_bprm_committed_creds(). + * + * @bprm: Pointer to "struct linux_binprm". + */ +static void tomoyo_bprm_committed_creds(const struct linux_binprm *bprm) +{ + /* Clear old_domain_info saved by execve() request. */ + struct tomoyo_task *s = tomoyo_task(current); + + atomic_dec(&s->old_domain_info->users); + s->old_domain_info = NULL; +} + +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER +/** + * tomoyo_bprm_creds_for_exec - Target for security_bprm_creds_for_exec(). + * + * @bprm: Pointer to "struct linux_binprm". + * + * Returns 0. + */ +static int tomoyo_bprm_creds_for_exec(struct linux_binprm *bprm) +{ + /* + * Load policy if /sbin/tomoyo-init exists and /sbin/init is requested + * for the first time. + */ + if (!tomoyo_policy_loaded) + tomoyo_load_policy(bprm->filename); + return 0; +} +#endif + +/** + * tomoyo_bprm_check_security - Target for security_bprm_check(). + * + * @bprm: Pointer to "struct linux_binprm". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_bprm_check_security(struct linux_binprm *bprm) +{ + struct tomoyo_task *s = tomoyo_task(current); + + /* + * Execute permission is checked against pathname passed to execve() + * using current domain. + */ + if (!s->old_domain_info) { + const int idx = tomoyo_read_lock(); + const int err = tomoyo_find_next_domain(bprm); + + tomoyo_read_unlock(idx); + return err; + } + /* + * Read permission is checked against interpreters using next domain. + */ + return tomoyo_check_open_permission(s->domain_info, + &bprm->file->f_path, O_RDONLY); +} + +/** + * tomoyo_inode_getattr - Target for security_inode_getattr(). + * + * @path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_inode_getattr(const struct path *path) +{ + return tomoyo_path_perm(TOMOYO_TYPE_GETATTR, path, NULL); +} + +/** + * tomoyo_path_truncate - Target for security_path_truncate(). + * + * @path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_truncate(const struct path *path) +{ + return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path, NULL); +} + +/** + * tomoyo_file_truncate - Target for security_file_truncate(). + * + * @file: Pointer to "struct file". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_file_truncate(struct file *file) +{ + return tomoyo_path_truncate(&file->f_path); +} + +/** + * tomoyo_path_unlink - Target for security_path_unlink(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_unlink(const struct path *parent, struct dentry *dentry) +{ + struct path path = { .mnt = parent->mnt, .dentry = dentry }; + + return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path, NULL); +} + +/** + * tomoyo_path_mkdir - Target for security_path_mkdir(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * @mode: DAC permission mode. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_mkdir(const struct path *parent, struct dentry *dentry, + umode_t mode) +{ + struct path path = { .mnt = parent->mnt, .dentry = dentry }; + + return tomoyo_path_number_perm(TOMOYO_TYPE_MKDIR, &path, + mode & S_IALLUGO); +} + +/** + * tomoyo_path_rmdir - Target for security_path_rmdir(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_rmdir(const struct path *parent, struct dentry *dentry) +{ + struct path path = { .mnt = parent->mnt, .dentry = dentry }; + + return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path, NULL); +} + +/** + * tomoyo_path_symlink - Target for security_path_symlink(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * @old_name: Symlink's content. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_symlink(const struct path *parent, struct dentry *dentry, + const char *old_name) +{ + struct path path = { .mnt = parent->mnt, .dentry = dentry }; + + return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path, old_name); +} + +/** + * tomoyo_path_mknod - Target for security_path_mknod(). + * + * @parent: Pointer to "struct path". + * @dentry: Pointer to "struct dentry". + * @mode: DAC permission mode. + * @dev: Device attributes. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_mknod(const struct path *parent, struct dentry *dentry, + umode_t mode, unsigned int dev) +{ + struct path path = { .mnt = parent->mnt, .dentry = dentry }; + int type = TOMOYO_TYPE_CREATE; + const unsigned int perm = mode & S_IALLUGO; + + switch (mode & S_IFMT) { + case S_IFCHR: + type = TOMOYO_TYPE_MKCHAR; + break; + case S_IFBLK: + type = TOMOYO_TYPE_MKBLOCK; + break; + default: + goto no_dev; + } + return tomoyo_mkdev_perm(type, &path, perm, dev); + no_dev: + switch (mode & S_IFMT) { + case S_IFIFO: + type = TOMOYO_TYPE_MKFIFO; + break; + case S_IFSOCK: + type = TOMOYO_TYPE_MKSOCK; + break; + } + return tomoyo_path_number_perm(type, &path, perm); +} + +/** + * tomoyo_path_link - Target for security_path_link(). + * + * @old_dentry: Pointer to "struct dentry". + * @new_dir: Pointer to "struct path". + * @new_dentry: Pointer to "struct dentry". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_link(struct dentry *old_dentry, const struct path *new_dir, + struct dentry *new_dentry) +{ + struct path path1 = { .mnt = new_dir->mnt, .dentry = old_dentry }; + struct path path2 = { .mnt = new_dir->mnt, .dentry = new_dentry }; + + return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); +} + +/** + * tomoyo_path_rename - Target for security_path_rename(). + * + * @old_parent: Pointer to "struct path". + * @old_dentry: Pointer to "struct dentry". + * @new_parent: Pointer to "struct path". + * @new_dentry: Pointer to "struct dentry". + * @flags: Rename options. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_rename(const struct path *old_parent, + struct dentry *old_dentry, + const struct path *new_parent, + struct dentry *new_dentry, + const unsigned int flags) +{ + struct path path1 = { .mnt = old_parent->mnt, .dentry = old_dentry }; + struct path path2 = { .mnt = new_parent->mnt, .dentry = new_dentry }; + + if (flags & RENAME_EXCHANGE) { + const int err = tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path2, + &path1); + + if (err) + return err; + } + return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); +} + +/** + * tomoyo_file_fcntl - Target for security_file_fcntl(). + * + * @file: Pointer to "struct file". + * @cmd: Command for fcntl(). + * @arg: Argument for @cmd. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + if (!(cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND))) + return 0; + return tomoyo_check_open_permission(tomoyo_domain(), &file->f_path, + O_WRONLY | (arg & O_APPEND)); +} + +/** + * tomoyo_file_open - Target for security_file_open(). + * + * @f: Pointer to "struct file". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_file_open(struct file *f) +{ + /* Don't check read permission here if called from execve(). */ + /* Illogically, FMODE_EXEC is in f_flags, not f_mode. */ + if (f->f_flags & __FMODE_EXEC) + return 0; + return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, + f->f_flags); +} + +/** + * tomoyo_file_ioctl - Target for security_file_ioctl(). + * + * @file: Pointer to "struct file". + * @cmd: Command for ioctl(). + * @arg: Argument for @cmd. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, + unsigned long arg) +{ + return tomoyo_path_number_perm(TOMOYO_TYPE_IOCTL, &file->f_path, cmd); +} + +/** + * tomoyo_path_chmod - Target for security_path_chmod(). + * + * @path: Pointer to "struct path". + * @mode: DAC permission mode. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_chmod(const struct path *path, umode_t mode) +{ + return tomoyo_path_number_perm(TOMOYO_TYPE_CHMOD, path, + mode & S_IALLUGO); +} + +/** + * tomoyo_path_chown - Target for security_path_chown(). + * + * @path: Pointer to "struct path". + * @uid: Owner ID. + * @gid: Group ID. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_chown(const struct path *path, kuid_t uid, kgid_t gid) +{ + int error = 0; + + if (uid_valid(uid)) + error = tomoyo_path_number_perm(TOMOYO_TYPE_CHOWN, path, + from_kuid(&init_user_ns, uid)); + if (!error && gid_valid(gid)) + error = tomoyo_path_number_perm(TOMOYO_TYPE_CHGRP, path, + from_kgid(&init_user_ns, gid)); + return error; +} + +/** + * tomoyo_path_chroot - Target for security_path_chroot(). + * + * @path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_path_chroot(const struct path *path) +{ + return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path, NULL); +} + +/** + * tomoyo_sb_mount - Target for security_sb_mount(). + * + * @dev_name: Name of device file. Maybe NULL. + * @path: Pointer to "struct path". + * @type: Name of filesystem type. Maybe NULL. + * @flags: Mount options. + * @data: Optional data. Maybe NULL. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_sb_mount(const char *dev_name, const struct path *path, + const char *type, unsigned long flags, void *data) +{ + return tomoyo_mount_permission(dev_name, path, type, flags, data); +} + +/** + * tomoyo_sb_umount - Target for security_sb_umount(). + * + * @mnt: Pointer to "struct vfsmount". + * @flags: Unmount options. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) +{ + struct path path = { .mnt = mnt, .dentry = mnt->mnt_root }; + + return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path, NULL); +} + +/** + * tomoyo_sb_pivotroot - Target for security_sb_pivotroot(). + * + * @old_path: Pointer to "struct path". + * @new_path: Pointer to "struct path". + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_sb_pivotroot(const struct path *old_path, const struct path *new_path) +{ + return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); +} + +/** + * tomoyo_socket_listen - Check permission for listen(). + * + * @sock: Pointer to "struct socket". + * @backlog: Backlog parameter. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_listen(struct socket *sock, int backlog) +{ + return tomoyo_socket_listen_permission(sock); +} + +/** + * tomoyo_socket_connect - Check permission for connect(). + * + * @sock: Pointer to "struct socket". + * @addr: Pointer to "struct sockaddr". + * @addr_len: Size of @addr. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_connect(struct socket *sock, struct sockaddr *addr, + int addr_len) +{ + return tomoyo_socket_connect_permission(sock, addr, addr_len); +} + +/** + * tomoyo_socket_bind - Check permission for bind(). + * + * @sock: Pointer to "struct socket". + * @addr: Pointer to "struct sockaddr". + * @addr_len: Size of @addr. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_bind(struct socket *sock, struct sockaddr *addr, + int addr_len) +{ + return tomoyo_socket_bind_permission(sock, addr, addr_len); +} + +/** + * tomoyo_socket_sendmsg - Check permission for sendmsg(). + * + * @sock: Pointer to "struct socket". + * @msg: Pointer to "struct msghdr". + * @size: Size of message. + * + * Returns 0 on success, negative value otherwise. + */ +static int tomoyo_socket_sendmsg(struct socket *sock, struct msghdr *msg, + int size) +{ + return tomoyo_socket_sendmsg_permission(sock, msg, size); +} + +struct lsm_blob_sizes tomoyo_blob_sizes __ro_after_init = { + .lbs_task = sizeof(struct tomoyo_task), +}; + +/** + * tomoyo_task_alloc - Target for security_task_alloc(). + * + * @task: Pointer to "struct task_struct". + * @clone_flags: clone() flags. + * + * Returns 0. + */ +static int tomoyo_task_alloc(struct task_struct *task, + unsigned long clone_flags) +{ + struct tomoyo_task *old = tomoyo_task(current); + struct tomoyo_task *new = tomoyo_task(task); + + new->domain_info = old->domain_info; + atomic_inc(&new->domain_info->users); + new->old_domain_info = NULL; + return 0; +} + +/** + * tomoyo_task_free - Target for security_task_free(). + * + * @task: Pointer to "struct task_struct". + */ +static void tomoyo_task_free(struct task_struct *task) +{ + struct tomoyo_task *s = tomoyo_task(task); + + if (s->domain_info) { + atomic_dec(&s->domain_info->users); + s->domain_info = NULL; + } + if (s->old_domain_info) { + atomic_dec(&s->old_domain_info->users); + s->old_domain_info = NULL; + } +} + +static const struct lsm_id tomoyo_lsmid = { + .name = "tomoyo", + .id = LSM_ID_TOMOYO, +}; + +/* + * tomoyo_security_ops is a "struct security_operations" which is used for + * registering TOMOYO. + */ +static struct security_hook_list tomoyo_hooks[] __ro_after_init = { + LSM_HOOK_INIT(cred_prepare, tomoyo_cred_prepare), + LSM_HOOK_INIT(bprm_committed_creds, tomoyo_bprm_committed_creds), + LSM_HOOK_INIT(task_alloc, tomoyo_task_alloc), + LSM_HOOK_INIT(task_free, tomoyo_task_free), +#ifndef CONFIG_SECURITY_TOMOYO_OMIT_USERSPACE_LOADER + LSM_HOOK_INIT(bprm_creds_for_exec, tomoyo_bprm_creds_for_exec), +#endif + LSM_HOOK_INIT(bprm_check_security, tomoyo_bprm_check_security), + LSM_HOOK_INIT(file_fcntl, tomoyo_file_fcntl), + LSM_HOOK_INIT(file_open, tomoyo_file_open), + LSM_HOOK_INIT(file_truncate, tomoyo_file_truncate), + LSM_HOOK_INIT(path_truncate, tomoyo_path_truncate), + LSM_HOOK_INIT(path_unlink, tomoyo_path_unlink), + LSM_HOOK_INIT(path_mkdir, tomoyo_path_mkdir), + LSM_HOOK_INIT(path_rmdir, tomoyo_path_rmdir), + LSM_HOOK_INIT(path_symlink, tomoyo_path_symlink), + LSM_HOOK_INIT(path_mknod, tomoyo_path_mknod), + LSM_HOOK_INIT(path_link, tomoyo_path_link), + LSM_HOOK_INIT(path_rename, tomoyo_path_rename), + LSM_HOOK_INIT(inode_getattr, tomoyo_inode_getattr), + LSM_HOOK_INIT(file_ioctl, tomoyo_file_ioctl), + LSM_HOOK_INIT(file_ioctl_compat, tomoyo_file_ioctl), + LSM_HOOK_INIT(path_chmod, tomoyo_path_chmod), + LSM_HOOK_INIT(path_chown, tomoyo_path_chown), + LSM_HOOK_INIT(path_chroot, tomoyo_path_chroot), + LSM_HOOK_INIT(sb_mount, tomoyo_sb_mount), + LSM_HOOK_INIT(sb_umount, tomoyo_sb_umount), + LSM_HOOK_INIT(sb_pivotroot, tomoyo_sb_pivotroot), + LSM_HOOK_INIT(socket_bind, tomoyo_socket_bind), + LSM_HOOK_INIT(socket_connect, tomoyo_socket_connect), + LSM_HOOK_INIT(socket_listen, tomoyo_socket_listen), + LSM_HOOK_INIT(socket_sendmsg, tomoyo_socket_sendmsg), +}; + +/* Lock for GC. */ +DEFINE_SRCU(tomoyo_ss); + +int tomoyo_enabled __ro_after_init = 1; + +/** + * tomoyo_init - Register TOMOYO Linux as a LSM module. + * + * Returns 0. + */ +static int __init tomoyo_init(void) +{ + struct tomoyo_task *s = tomoyo_task(current); + + /* register ourselves with the security framework */ + security_add_hooks(tomoyo_hooks, ARRAY_SIZE(tomoyo_hooks), + &tomoyo_lsmid); + pr_info("TOMOYO Linux initialized\n"); + s->domain_info = &tomoyo_kernel_domain; + atomic_inc(&tomoyo_kernel_domain.users); + s->old_domain_info = NULL; + tomoyo_mm_init(); + + return 0; +} + +DEFINE_LSM(tomoyo) = { + .name = "tomoyo", + .enabled = &tomoyo_enabled, + .flags = LSM_FLAG_LEGACY_MAJOR, + .blobs = &tomoyo_blob_sizes, + .init = tomoyo_init, +}; diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index b851ff377382..6799b1122c9d 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c @@ -13,6 +13,9 @@ /* Lock for protecting policy. */ DEFINE_MUTEX(tomoyo_policy_lock); +/* Has /sbin/init started? */ +bool tomoyo_policy_loaded; + /* * Mapping table from "enum tomoyo_mac_index" to * "enum tomoyo_mac_category_index". -- cgit v1.2.3 From 9897713fe1077c90b4a86c9af0a878d56c8888a2 Mon Sep 17 00:00:00 2001 From: Michal Hocko Date: Thu, 26 Sep 2024 19:11:50 +0200 Subject: bcachefs: do not use PF_MEMALLOC_NORECLAIM Patch series "remove PF_MEMALLOC_NORECLAIM" v3. This patch (of 2): bch2_new_inode relies on PF_MEMALLOC_NORECLAIM to try to allocate a new inode to achieve GFP_NOWAIT semantic while holding locks. If this allocation fails it will drop locks and use GFP_NOFS allocation context. We would like to drop PF_MEMALLOC_NORECLAIM because it is really dangerous to use if the caller doesn't control the full call chain with this flag set. E.g. if any of the function down the chain needed GFP_NOFAIL request the PF_MEMALLOC_NORECLAIM would override this and cause unexpected failure. While this is not the case in this particular case using the scoped gfp semantic is not really needed bacause we can easily pus the allocation context down the chain without too much clutter. [akpm@linux-foundation.org: fix kerneldoc warnings] Link: https://lkml.kernel.org/r/20240926172940.167084-1-mhocko@kernel.org Link: https://lkml.kernel.org/r/20240926172940.167084-2-mhocko@kernel.org Signed-off-by: Michal Hocko Reviewed-by: Christoph Hellwig Reviewed-by: Dave Chinner Reviewed-by: Jan Kara # For vfs changes Cc: Al Viro Cc: Christian Brauner Cc: James Morris Cc: Kent Overstreet Cc: Paul Moore Cc: Serge E. Hallyn Cc: Yafang Shao Cc: Matthew Wilcox (Oracle) Cc: Vlastimil Babka Signed-off-by: Andrew Morton --- fs/bcachefs/fs.c | 14 ++++++-------- fs/inode.c | 10 ++++++---- include/linux/fs.h | 7 ++++++- include/linux/security.h | 4 ++-- security/security.c | 10 ++++++---- 5 files changed, 26 insertions(+), 19 deletions(-) (limited to 'security') diff --git a/fs/bcachefs/fs.c b/fs/bcachefs/fs.c index 5bfc26d58270..02969dff165d 100644 --- a/fs/bcachefs/fs.c +++ b/fs/bcachefs/fs.c @@ -300,10 +300,10 @@ static struct inode *bch2_alloc_inode(struct super_block *sb) BUG(); } -static struct bch_inode_info *__bch2_new_inode(struct bch_fs *c) +static struct bch_inode_info *__bch2_new_inode(struct bch_fs *c, gfp_t gfp) { struct bch_inode_info *inode = alloc_inode_sb(c->vfs_sb, - bch2_inode_cache, GFP_NOFS); + bch2_inode_cache, gfp); if (!inode) return NULL; @@ -315,7 +315,7 @@ static struct bch_inode_info *__bch2_new_inode(struct bch_fs *c) mutex_init(&inode->ei_quota_lock); memset(&inode->ei_devs_need_flush, 0, sizeof(inode->ei_devs_need_flush)); - if (unlikely(inode_init_always(c->vfs_sb, &inode->v))) { + if (unlikely(inode_init_always_gfp(c->vfs_sb, &inode->v, gfp))) { kmem_cache_free(bch2_inode_cache, inode); return NULL; } @@ -328,12 +328,10 @@ static struct bch_inode_info *__bch2_new_inode(struct bch_fs *c) */ static struct bch_inode_info *bch2_new_inode(struct btree_trans *trans) { - struct bch_inode_info *inode = - memalloc_flags_do(PF_MEMALLOC_NORECLAIM|PF_MEMALLOC_NOWARN, - __bch2_new_inode(trans->c)); + struct bch_inode_info *inode = __bch2_new_inode(trans->c, GFP_NOWAIT); if (unlikely(!inode)) { - int ret = drop_locks_do(trans, (inode = __bch2_new_inode(trans->c)) ? 0 : -ENOMEM); + int ret = drop_locks_do(trans, (inode = __bch2_new_inode(trans->c, GFP_NOFS)) ? 0 : -ENOMEM); if (ret && inode) { __destroy_inode(&inode->v); kmem_cache_free(bch2_inode_cache, inode); @@ -407,7 +405,7 @@ __bch2_create(struct mnt_idmap *idmap, if (ret) return ERR_PTR(ret); #endif - inode = __bch2_new_inode(c); + inode = __bch2_new_inode(c, GFP_NOFS); if (unlikely(!inode)) { inode = ERR_PTR(-ENOMEM); goto err; diff --git a/fs/inode.c b/fs/inode.c index 471ae4a31549..8dabb224f941 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -146,14 +146,16 @@ static int no_open(struct inode *inode, struct file *file) } /** - * inode_init_always - perform inode structure initialisation + * inode_init_always_gfp - perform inode structure initialisation * @sb: superblock inode belongs to * @inode: inode to initialise + * @gfp: allocation flags * * These are initializations that need to be done on every inode * allocation as the fields are not initialised by slab allocation. + * If there are additional allocations required @gfp is used. */ -int inode_init_always(struct super_block *sb, struct inode *inode) +int inode_init_always_gfp(struct super_block *sb, struct inode *inode, gfp_t gfp) { static const struct inode_operations empty_iops; static const struct file_operations no_open_fops = {.open = no_open}; @@ -230,14 +232,14 @@ int inode_init_always(struct super_block *sb, struct inode *inode) #endif inode->i_flctx = NULL; - if (unlikely(security_inode_alloc(inode))) + if (unlikely(security_inode_alloc(inode, gfp))) return -ENOMEM; this_cpu_inc(nr_inodes); return 0; } -EXPORT_SYMBOL(inode_init_always); +EXPORT_SYMBOL(inode_init_always_gfp); void free_inode_nonrcu(struct inode *inode) { diff --git a/include/linux/fs.h b/include/linux/fs.h index e3c603d01337..3559446279c1 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -3082,7 +3082,12 @@ extern loff_t default_llseek(struct file *file, loff_t offset, int whence); extern loff_t vfs_llseek(struct file *file, loff_t offset, int whence); -extern int inode_init_always(struct super_block *, struct inode *); +extern int inode_init_always_gfp(struct super_block *, struct inode *, gfp_t); +static inline int inode_init_always(struct super_block *sb, struct inode *inode) +{ + return inode_init_always_gfp(sb, inode, GFP_NOFS); +} + extern void inode_init_once(struct inode *); extern void address_space_init_once(struct address_space *mapping); extern struct inode * igrab(struct inode *); diff --git a/include/linux/security.h b/include/linux/security.h index b86ec2afc691..2ec8f3014757 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -348,7 +348,7 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, struct cred *new); int security_path_notify(const struct path *path, u64 mask, unsigned int obj_type); -int security_inode_alloc(struct inode *inode); +int security_inode_alloc(struct inode *inode, gfp_t gfp); void security_inode_free(struct inode *inode); int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, @@ -789,7 +789,7 @@ static inline int security_path_notify(const struct path *path, u64 mask, return 0; } -static inline int security_inode_alloc(struct inode *inode) +static inline int security_inode_alloc(struct inode *inode, gfp_t gfp) { return 0; } diff --git a/security/security.c b/security/security.c index 6875eb4a59fc..c5981e558bc2 100644 --- a/security/security.c +++ b/security/security.c @@ -740,19 +740,20 @@ static int lsm_file_alloc(struct file *file) /** * 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) +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_NOFS); + inode->i_security = kmem_cache_zalloc(lsm_inode_cache, gfp); if (inode->i_security == NULL) return -ENOMEM; return 0; @@ -1678,6 +1679,7 @@ int security_path_notify(const struct path *path, u64 mask, /** * security_inode_alloc() - Allocate an inode LSM blob * @inode: the inode + * @gfp: allocation flags * * Allocate and attach a security structure to @inode->i_security. The * i_security field is initialized to NULL when the inode structure is @@ -1685,9 +1687,9 @@ int security_path_notify(const struct path *path, u64 mask, * * Return: Return 0 if operation was successful. */ -int security_inode_alloc(struct inode *inode) +int security_inode_alloc(struct inode *inode, gfp_t gfp) { - int rc = lsm_inode_alloc(inode); + int rc = lsm_inode_alloc(inode, gfp); if (unlikely(rc)) return rc; -- cgit v1.2.3 From 579941899db4f972507df3bf783518e606bb095a Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 25 Sep 2024 23:01:33 +0200 Subject: ipe: return -ESTALE instead of -EINVAL on update when new policy has a lower version When loading policies in userspace we want a recognizable error when an update attempts to use an old policy, as that is an error that needs to be treated differently from an invalid policy. Use -ESTALE as it is clear enough for an update mechanism. Signed-off-by: Luca Boccassi Reviewed-by: Serge Hallyn Signed-off-by: Fan Wu --- security/ipe/policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/ipe/policy.c b/security/ipe/policy.c index d8e7db857a2e..dcaac8c4bb38 100644 --- a/security/ipe/policy.c +++ b/security/ipe/policy.c @@ -107,7 +107,7 @@ int ipe_update_policy(struct inode *root, const char *text, size_t textlen, } if (ver_to_u64(old) > ver_to_u64(new)) { - rc = -EINVAL; + rc = -ESTALE; goto err; } -- cgit v1.2.3 From 5ceecb301e50e933c1e621fbeea5ec239fbff858 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 25 Sep 2024 23:01:34 +0200 Subject: ipe: also reject policy updates with the same version Currently IPE accepts an update that has the same version as the policy being updated, but it doesn't make it a no-op nor it checks that the old and new policyes are the same. So it is possible to change the content of a policy, without changing its version. This is very confusing from userspace when managing policies. Instead change the update logic to reject updates that have the same version with ESTALE, as that is much clearer and intuitive behaviour. Signed-off-by: Luca Boccassi Reviewed-by: Serge Hallyn Signed-off-by: Fan Wu --- Documentation/admin-guide/LSM/ipe.rst | 2 +- security/ipe/policy.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst index f38e641df0e9..fcb3c493104b 100644 --- a/Documentation/admin-guide/LSM/ipe.rst +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -266,7 +266,7 @@ in the kernel. This file is write-only and accepts a PKCS#7 signed policy. Two checks will always be performed on this policy: First, the ``policy_names`` must match with the updated version and the existing version. Second the updated policy must have a policy version greater than -or equal to the currently-running version. This is to prevent rollback attacks. +the currently-running version. This is to prevent rollback attacks. The ``delete`` file is used to remove a policy that is no longer needed. This file is write-only and accepts a value of ``1`` to delete the policy. diff --git a/security/ipe/policy.c b/security/ipe/policy.c index dcaac8c4bb38..4cea067adf6a 100644 --- a/security/ipe/policy.c +++ b/security/ipe/policy.c @@ -106,7 +106,7 @@ int ipe_update_policy(struct inode *root, const char *text, size_t textlen, goto err; } - if (ver_to_u64(old) > ver_to_u64(new)) { + if (ver_to_u64(old) >= ver_to_u64(new)) { rc = -ESTALE; goto err; } -- cgit v1.2.3 From 02e2f9aa33e461468de02e35ad977bd7233960ae Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sun, 15 Sep 2024 11:11:19 +0200 Subject: ipe: allow secondary and platform keyrings to install/update policies The current policy management makes it impossible to use IPE in a general purpose distribution. In such cases the users are not building the kernel, the distribution is, and access to the private key included in the trusted keyring is, for obvious reason, not available. This means that users have no way to enable IPE, since there will be no built-in generic policy, and no access to the key to sign updates validated by the trusted keyring. Just as we do for dm-verity, kernel modules and more, allow the secondary and platform keyrings to also validate policies. This allows users enrolling their own keys in UEFI db or MOK to also sign policies, and enroll them. This makes it sensible to enable IPE in general purpose distributions, as it becomes usable by any user wishing to do so. Keys in these keyrings can already load kernels and kernel modules, so there is no security downgrade. Add a kconfig each, like dm-verity does, but default to enabled if the dependencies are available. Signed-off-by: Luca Boccassi Reviewed-by: Serge Hallyn [FW: fixed some style issues] Signed-off-by: Fan Wu --- Documentation/admin-guide/LSM/ipe.rst | 5 ++++- security/ipe/Kconfig | 19 +++++++++++++++++++ security/ipe/policy.c | 14 +++++++++++++- 3 files changed, 36 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/Documentation/admin-guide/LSM/ipe.rst b/Documentation/admin-guide/LSM/ipe.rst index fcb3c493104b..f93a467db628 100644 --- a/Documentation/admin-guide/LSM/ipe.rst +++ b/Documentation/admin-guide/LSM/ipe.rst @@ -223,7 +223,10 @@ are signed through the PKCS#7 message format to enforce some level of authorization of the policies (prohibiting an attacker from gaining unconstrained root, and deploying an "allow all" policy). These policies must be signed by a certificate that chains to the -``SYSTEM_TRUSTED_KEYRING``. With openssl, the policy can be signed by:: +``SYSTEM_TRUSTED_KEYRING``, or to the secondary and/or platform keyrings if +``CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING`` and/or +``CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING`` are enabled, respectively. +With openssl, the policy can be signed by:: openssl smime -sign \ -in "$MY_POLICY" \ diff --git a/security/ipe/Kconfig b/security/ipe/Kconfig index 3ab582606ed2..3c75bf267da4 100644 --- a/security/ipe/Kconfig +++ b/security/ipe/Kconfig @@ -31,6 +31,25 @@ config IPE_BOOT_POLICY If unsure, leave blank. +config IPE_POLICY_SIG_SECONDARY_KEYRING + bool "IPE policy update verification with secondary keyring" + default y + depends on SECONDARY_TRUSTED_KEYRING + help + Also allow the secondary trusted keyring to verify IPE policy + updates. + + If unsure, answer Y. + +config IPE_POLICY_SIG_PLATFORM_KEYRING + bool "IPE policy update verification with platform keyring" + default y + depends on INTEGRITY_PLATFORM_KEYRING + help + Also allow the platform keyring to verify IPE policy updates. + + If unsure, answer Y. + menu "IPE Trust Providers" config IPE_PROP_DM_VERITY diff --git a/security/ipe/policy.c b/security/ipe/policy.c index 4cea067adf6a..45f7d6a0ed23 100644 --- a/security/ipe/policy.c +++ b/security/ipe/policy.c @@ -169,9 +169,21 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen, goto err; } - rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len, NULL, + rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len, +#ifdef CONFIG_IPE_POLICY_SIG_SECONDARY_KEYRING + VERIFY_USE_SECONDARY_KEYRING, +#else + NULL, +#endif VERIFYING_UNSPECIFIED_SIGNATURE, set_pkcs7_data, new); +#ifdef CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING + if (rc == -ENOKEY) + rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len, + VERIFY_USE_PLATFORM_KEYRING, + VERIFYING_UNSPECIFIED_SIGNATURE, + set_pkcs7_data, new); +#endif if (rc) goto err; } else { -- cgit v1.2.3 From f40998a8e6bbf0314b8416350183a537f9b59ca9 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Fri, 27 Sep 2024 10:23:44 +0200 Subject: ipe: fallback to platform keyring also if key in trusted keyring is rejected If enabled, we fallback to the platform keyring if the trusted keyring doesn't have the key used to sign the ipe policy. But if pkcs7_verify() rejects the key for other reasons, such as usage restrictions, we do not fallback. Do so, following the same change in dm-verity. Signed-off-by: Luca Boccassi Suggested-by: Serge Hallyn [FW: fixed some line length issues and a typo in the commit message] Signed-off-by: Fan Wu --- security/ipe/policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/ipe/policy.c b/security/ipe/policy.c index 45f7d6a0ed23..b628f696e32b 100644 --- a/security/ipe/policy.c +++ b/security/ipe/policy.c @@ -178,7 +178,7 @@ struct ipe_policy *ipe_new_policy(const char *text, size_t textlen, VERIFYING_UNSPECIFIED_SIGNATURE, set_pkcs7_data, new); #ifdef CONFIG_IPE_POLICY_SIG_PLATFORM_KEYRING - if (rc == -ENOKEY) + if (rc == -ENOKEY || rc == -EKEYREJECTED) rc = verify_pkcs7_signature(NULL, 0, new->pkcs7, pkcs7len, VERIFY_USE_PLATFORM_KEYRING, VERIFYING_UNSPECIFIED_SIGNATURE, -- cgit v1.2.3