From ed35e2f2f0ded15df313ae6f8da21e85c8e1e493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCnther=20Noack?= Date: Tue, 21 Feb 2023 17:52:05 +0100 Subject: [PATCH 001/291] landlock: Clarify documentation for the LANDLOCK_ACCESS_FS_REFER right MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clarify the "refer" documentation by splitting up a big paragraph of text. - Call out specifically that the denial by default applies to ABI v1 as well. - Turn the three additional constraints for link/rename operations into bullet points, to give it more structure. Signed-off-by: Günther Noack Link: https://lore.kernel.org/r/20230221165205.4231-1-gnoack3000@gmail.com Signed-off-by: Mickaël Salaün --- include/uapi/linux/landlock.h | 46 +++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/include/uapi/linux/landlock.h b/include/uapi/linux/landlock.h index f3223f964691..81d09ef9aa50 100644 --- a/include/uapi/linux/landlock.h +++ b/include/uapi/linux/landlock.h @@ -130,21 +130,37 @@ struct landlock_path_beneath_attr { * - %LANDLOCK_ACCESS_FS_MAKE_BLOCK: Create (or rename or link) a block device. * - %LANDLOCK_ACCESS_FS_MAKE_SYM: Create (or rename or link) a symbolic link. * - %LANDLOCK_ACCESS_FS_REFER: Link or rename a file from or to a different - * directory (i.e. reparent a file hierarchy). This access right is - * available since the second version of the Landlock ABI. This is also the - * only access right which is always considered handled by any ruleset in - * such a way that reparenting a file hierarchy is always denied by default. - * To avoid privilege escalation, it is not enough to add a rule with this - * access right. When linking or renaming a file, the destination directory - * hierarchy must also always have the same or a superset of restrictions of - * the source hierarchy. If it is not the case, or if the domain doesn't - * handle this access right, such actions are denied by default with errno - * set to ``EXDEV``. Linking also requires a ``LANDLOCK_ACCESS_FS_MAKE_*`` - * access right on the destination directory, and renaming also requires a - * ``LANDLOCK_ACCESS_FS_REMOVE_*`` access right on the source's (file or - * directory) parent. Otherwise, such actions are denied with errno set to - * ``EACCES``. The ``EACCES`` errno prevails over ``EXDEV`` to let user space - * efficiently deal with an unrecoverable error. + * directory (i.e. reparent a file hierarchy). + * + * This access right is available since the second version of the Landlock + * ABI. + * + * This is the only access right which is denied by default by any ruleset, + * even if the right is not specified as handled at ruleset creation time. + * The only way to make a ruleset grant this right is to explicitly allow it + * for a specific directory by adding a matching rule to the ruleset. + * + * In particular, when using the first Landlock ABI version, Landlock will + * always deny attempts to reparent files between different directories. + * + * In addition to the source and destination directories having the + * %LANDLOCK_ACCESS_FS_REFER access right, the attempted link or rename + * operation must meet the following constraints: + * + * * The reparented file may not gain more access rights in the destination + * directory than it previously had in the source directory. If this is + * attempted, the operation results in an ``EXDEV`` error. + * + * * When linking or renaming, the ``LANDLOCK_ACCESS_FS_MAKE_*`` right for the + * respective file type must be granted for the destination directory. + * Otherwise, the operation results in an ``EACCES`` error. + * + * * When renaming, the ``LANDLOCK_ACCESS_FS_REMOVE_*`` right for the + * respective file type must be granted for the source directory. Otherwise, + * the operation results in an ``EACCES`` error. + * + * If multiple requirements are not met, the ``EACCES`` error code takes + * precedence over ``EXDEV``. * * .. warning:: * From c120c98486c2855d2ae266c2af63d26f61dfcc4e Mon Sep 17 00:00:00 2001 From: Vlastimil Babka Date: Tue, 28 Feb 2023 10:35:56 +0100 Subject: [PATCH 002/291] tomoyo: replace tomoyo_round2() with kmalloc_size_roundup() It seems tomoyo has had its own implementation of what kmalloc_size_roundup() does today. Remove the function tomoyo_round2() and replace it with kmalloc_size_roundup(). It provides more accurate results and doesn't contain a while loop. Signed-off-by: Vlastimil Babka Signed-off-by: Tetsuo Handa --- security/tomoyo/audit.c | 6 +++--- security/tomoyo/common.c | 2 +- security/tomoyo/common.h | 44 ---------------------------------------- 3 files changed, 4 insertions(+), 48 deletions(-) diff --git a/security/tomoyo/audit.c b/security/tomoyo/audit.c index 7cf8fdbb29bf..610c1536cf70 100644 --- a/security/tomoyo/audit.c +++ b/security/tomoyo/audit.c @@ -271,7 +271,7 @@ char *tomoyo_init_log(struct tomoyo_request_info *r, int len, const char *fmt, /* +18 is for " symlink.target=\"%s\"" */ len += 18 + strlen(symlink); } - len = tomoyo_round2(len); + len = kmalloc_size_roundup(len); buf = kzalloc(len, GFP_NOFS); if (!buf) goto out; @@ -382,12 +382,12 @@ void tomoyo_write_log2(struct tomoyo_request_info *r, int len, const char *fmt, goto out; } entry->log = buf; - len = tomoyo_round2(strlen(buf) + 1); + len = kmalloc_size_roundup(strlen(buf) + 1); /* * The entry->size is used for memory quota checks. * Don't go beyond strlen(entry->log). */ - entry->size = len + tomoyo_round2(sizeof(*entry)); + entry->size = len + kmalloc_size_roundup(sizeof(*entry)); spin_lock(&tomoyo_log_lock); if (tomoyo_memory_quota[TOMOYO_MEMORY_AUDIT] && tomoyo_memory_used[TOMOYO_MEMORY_AUDIT] + entry->size >= diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index f4cd9b58b205..969d4aa6fd55 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c @@ -2094,7 +2094,7 @@ int tomoyo_supervisor(struct tomoyo_request_info *r, const char *fmt, ...) tomoyo_add_entry(r->domain, entry.query); goto out; } - len = tomoyo_round2(entry.query_len); + len = kmalloc_size_roundup(entry.query_len); entry.domain = r->domain; spin_lock(&tomoyo_query_list_lock); if (tomoyo_memory_quota[TOMOYO_MEMORY_QUERY] && diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index ca285f362705..a539b2cbb5c4 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h @@ -1276,50 +1276,6 @@ static inline struct tomoyo_policy_namespace *tomoyo_current_namespace(void) return tomoyo_domain()->ns; } -#if defined(CONFIG_SLOB) - -/** - * tomoyo_round2 - Round up to power of 2 for calculating memory usage. - * - * @size: Size to be rounded up. - * - * Returns @size. - * - * Since SLOB does not round up, this function simply returns @size. - */ -static inline int tomoyo_round2(size_t size) -{ - return size; -} - -#else - -/** - * tomoyo_round2 - Round up to power of 2 for calculating memory usage. - * - * @size: Size to be rounded up. - * - * Returns rounded size. - * - * Strictly speaking, SLAB may be able to allocate (e.g.) 96 bytes instead of - * (e.g.) 128 bytes. - */ -static inline int tomoyo_round2(size_t size) -{ -#if PAGE_SIZE == 4096 - size_t bsize = 32; -#else - size_t bsize = 64; -#endif - if (!size) - return 0; - while (size > bsize) - bsize <<= 1; - return bsize; -} - -#endif - /** * list_for_each_cookie - iterate over a list with cookie. * @pos: the &struct list_head to use as a loop cursor. From 1661372c912d1966e21e0cb5463559984df8249b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 7 Feb 2023 17:06:51 -0500 Subject: [PATCH 003/291] lsm: move the program execution hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 52 ----------------------------- security/security.c | 69 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 52 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 6e156d2acffc..784e19fd665b 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,58 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for program execution operations. - * - * @bprm_creds_for_exec: - * If the setup in prepare_exec_creds did not setup @bprm->cred->security - * properly for executing @bprm->file, update the LSM's portion of - * @bprm->cred->security to be what commit_creds needs to install for the - * new program. This hook may also optionally check permissions - * (e.g. for transitions between security domains). - * The hook must set @bprm->secureexec to 1 if AT_SECURE should be set to - * request libc enable secure mode. - * @bprm contains the linux_binprm structure. - * Return 0 if the hook is successful and permission is granted. - * @bprm_creds_from_file: - * If @file is setpcap, suid, sgid or otherwise marked to change - * privilege upon exec, update @bprm->cred to reflect that change. - * This is called after finding the binary that will be executed. - * without an interpreter. This ensures that the credentials will not - * be derived from a script that the binary will need to reopen, which - * when reopend may end up being a completely different file. This - * hook may also optionally check permissions (e.g. for transitions - * between security domains). - * The hook must set @bprm->secureexec to 1 if AT_SECURE should be set to - * request libc enable secure mode. - * The hook must add to @bprm->per_clear any personality flags that - * should be cleared from current->personality. - * @bprm contains the linux_binprm structure. - * Return 0 if the hook is successful and permission is granted. - * @bprm_check_security: - * This hook mediates the point when a search for a binary handler will - * begin. It allows a check against the @bprm->cred->security value - * which was set in the preceding creds_for_exec call. The argv list and - * envp list are reliably available in @bprm. This hook may be called - * multiple times during a single execve. - * @bprm contains the linux_binprm structure. - * Return 0 if the hook is successful and permission is granted. - * @bprm_committing_creds: - * Prepare to install the new security attributes of a process being - * transformed by an execve operation, based on the old credentials - * pointed to by @current->cred and the information set in @bprm->cred by - * the bprm_creds_for_exec hook. @bprm points to the linux_binprm - * structure. This hook is a good place to perform state changes on the - * process such as closing open file descriptors to which access will no - * longer be granted when the attributes are changed. This is called - * immediately before commit_creds(). - * @bprm_committed_creds: - * Tidy up after the installation of the new security attributes of a - * process being transformed by an execve operation. The new credentials - * have, by this point, been set to @current->cred. @bprm points to the - * linux_binprm structure. This hook is a good place to perform state - * changes on the process such as clearing out non-inheritable signal - * state. This is called immediately after commit_creds(). - * * Security hooks for mount using fs_context. * [See also Documentation/filesystems/mount_api.rst] * diff --git a/security/security.c b/security/security.c index cf6cc576736f..1e7dbaf9ad28 100644 --- a/security/security.c +++ b/security/security.c @@ -6,6 +6,7 @@ * Copyright (C) 2001-2002 Greg Kroah-Hartman * Copyright (C) 2001 Networks Associates Technology, Inc * Copyright (C) 2016 Mellanox Technologies + * Copyright (C) 2023 Microsoft Corporation */ #define pr_fmt(fmt) "LSM: " fmt @@ -880,16 +881,61 @@ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) return __vm_enough_memory(mm, pages, cap_sys_admin); } +/** + * security_bprm_creds_for_exec() - Prepare the credentials for exec() + * @bprm: binary program information + * + * If the setup in prepare_exec_creds did not setup @bprm->cred->security + * properly for executing @bprm->file, update the LSM's portion of + * @bprm->cred->security to be what commit_creds needs to install for the new + * program. This hook may also optionally check permissions (e.g. for + * transitions between security domains). The hook must set @bprm->secureexec + * to 1 if AT_SECURE should be set to request libc enable secure mode. @bprm + * contains the linux_binprm structure. + * + * Return: Returns 0 if the hook is successful and permission is granted. + */ int security_bprm_creds_for_exec(struct linux_binprm *bprm) { return call_int_hook(bprm_creds_for_exec, 0, bprm); } +/** + * security_bprm_creds_from_file() - Update linux_binprm creds based on file + * @bprm: binary program information + * @file: associated file + * + * If @file is setpcap, suid, sgid or otherwise marked to change privilege upon + * exec, update @bprm->cred to reflect that change. This is called after + * finding the binary that will be executed without an interpreter. This + * ensures that the credentials will not be derived from a script that the + * binary will need to reopen, which when reopend may end up being a completely + * different file. This hook may also optionally check permissions (e.g. for + * transitions between security domains). The hook must set @bprm->secureexec + * to 1 if AT_SECURE should be set to request libc enable secure mode. The + * hook must add to @bprm->per_clear any personality flags that should be + * cleared from current->personality. @bprm contains the linux_binprm + * structure. + * + * Return: Returns 0 if the hook is successful and permission is granted. + */ int security_bprm_creds_from_file(struct linux_binprm *bprm, struct file *file) { return call_int_hook(bprm_creds_from_file, 0, bprm, file); } +/** + * security_bprm_check() - Mediate binary handler search + * @bprm: binary program information + * + * This hook mediates the point when a search for a binary handler will begin. + * It allows a check against the @bprm->cred->security value which was set in + * the preceding creds_for_exec call. The argv list and envp list are reliably + * available in @bprm. This hook may be called multiple times during a single + * execve. @bprm contains the linux_binprm structure. + * + * Return: Returns 0 if the hook is successful and permission is granted. + */ int security_bprm_check(struct linux_binprm *bprm) { int ret; @@ -900,11 +946,34 @@ int security_bprm_check(struct linux_binprm *bprm) return ima_bprm_check(bprm); } +/** + * security_bprm_committing_creds() - Install creds for a process during exec() + * @bprm: binary program information + * + * Prepare to install the new security attributes of a process being + * transformed by an execve operation, based on the old credentials pointed to + * by @current->cred and the information set in @bprm->cred by the + * bprm_creds_for_exec hook. @bprm points to the linux_binprm structure. This + * hook is a good place to perform state changes on the process such as closing + * open file descriptors to which access will no longer be granted when the + * attributes are changed. This is called immediately before commit_creds(). + */ void security_bprm_committing_creds(struct linux_binprm *bprm) { call_void_hook(bprm_committing_creds, bprm); } +/** + * security_bprm_committed_creds() - Tidy up after cred install during exec() + * @bprm: binary program information + * + * Tidy up after the installation of the new security attributes of a process + * being transformed by an execve operation. The new credentials have, by this + * point, been set to @current->cred. @bprm points to the linux_binprm + * structure. This hook is a good place to perform state changes on the + * process such as clearing out non-inheritable signal state. This is called + * immediately after commit_creds(). + */ void security_bprm_committed_creds(struct linux_binprm *bprm) { call_void_hook(bprm_committed_creds, bprm); From 36819f185590c1e0e47d095f04bf5da20650fe4d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 7 Feb 2023 17:33:31 -0500 Subject: [PATCH 004/291] lsm: move the fs_context hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 17 ----------------- security/security.c | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 784e19fd665b..a37f3a380918 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,23 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for mount using fs_context. - * [See also Documentation/filesystems/mount_api.rst] - * - * @fs_context_dup: - * Allocate and attach a security structure to sc->security. This pointer - * is initialised to NULL by the caller. - * @fc indicates the new filesystem context. - * @src_fc indicates the original filesystem context. - * Return 0 on success or a negative error code on failure. - * @fs_context_parse_param: - * Userspace provided a parameter to configure a superblock. The LSM may - * reject it with an error and may use it for itself, in which case it - * should return 0; otherwise it should return -ENOPARAM to pass it on to - * the filesystem. - * @fc indicates the filesystem context. - * @param The parameter. - * * Security hooks for filesystem operations. * * @sb_alloc_security: diff --git a/security/security.c b/security/security.c index 1e7dbaf9ad28..64c8805570b1 100644 --- a/security/security.c +++ b/security/security.c @@ -979,11 +979,34 @@ void security_bprm_committed_creds(struct linux_binprm *bprm) call_void_hook(bprm_committed_creds, bprm); } +/** + * security_fs_context_dup() - Duplicate a fs_context LSM blob + * @fc: destination filesystem context + * @src_fc: source filesystem context + * + * Allocate and attach a security structure to sc->security. This pointer is + * initialised to NULL by the caller. @fc indicates the new filesystem context. + * @src_fc indicates the original filesystem context. + * + * Return: Returns 0 on success or a negative error code on failure. + */ int security_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc) { return call_int_hook(fs_context_dup, 0, fc, src_fc); } +/** + * security_fs_context_parse_param() - Configure a filesystem context + * @fc: filesystem context + * @param: filesystem parameter + * + * Userspace provided a parameter to configure a superblock. The LSM can + * consume the parameter or return it to the caller for use elsewhere. + * + * Return: If the parameter is used by the LSM it should return 0, if it is + * returned to the caller -ENOPARAM is returned, otherwise a negative + * error code is returned. + */ int security_fs_context_parse_param(struct fs_context *fc, struct fs_parameter *param) { From 08526a902cc4bc57bb160e5b1114e67a56fc9280 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Tue, 7 Feb 2023 17:44:01 -0500 Subject: [PATCH 005/291] lsm: move the filesystem hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 106 ---------------------- security/security.c | 181 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+), 106 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index a37f3a380918..3cd6e7abe0df 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,112 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for filesystem operations. - * - * @sb_alloc_security: - * Allocate and attach a security structure to the sb->s_security field. - * The s_security field is initialized to NULL when the structure is - * allocated. - * @sb contains the super_block structure to be modified. - * Return 0 if operation was successful. - * @sb_delete: - * Release objects tied to a superblock (e.g. inodes). - * @sb contains the super_block structure being released. - * @sb_free_security: - * Deallocate and clear the sb->s_security field. - * @sb contains the super_block structure to be modified. - * @sb_free_mnt_opts: - * Free memory associated with @mnt_ops. - * @sb_eat_lsm_opts: - * Eat (scan @orig options) and save them in @mnt_opts. - * Return 0 on success, negative values on failure. - * @sb_statfs: - * Check permission before obtaining filesystem statistics for the @mnt - * mountpoint. - * @dentry is a handle on the superblock for the filesystem. - * Return 0 if permission is granted. - * @sb_mount: - * Check permission before an object specified by @dev_name is mounted on - * the mount point named by @nd. For an ordinary mount, @dev_name - * identifies a device if the file system type requires a device. For a - * remount (@flags & MS_REMOUNT), @dev_name is irrelevant. For a - * loopback/bind mount (@flags & MS_BIND), @dev_name identifies the - * pathname of the object being mounted. - * @dev_name contains the name for object being mounted. - * @path contains the path for mount point object. - * @type contains the filesystem type. - * @flags contains the mount flags. - * @data contains the filesystem-specific data. - * Return 0 if permission is granted. - * @sb_mnt_opts_compat: - * Determine if the new mount options in @mnt_opts are allowed given - * the existing mounted filesystem at @sb. - * @sb superblock being compared. - * @mnt_opts new mount options. - * Return 0 if options are compatible. - * @sb_remount: - * Extracts security system specific mount options and verifies no changes - * are being made to those options. - * @sb superblock being remounted. - * @data contains the filesystem-specific data. - * Return 0 if permission is granted. - * @sb_kern_mount: - * Mount this @sb if allowed by permissions. - * Return 0 if permission is granted. - * @sb_show_options: - * Show (print on @m) mount options for this @sb. - * Return 0 on success, negative values on failure. - * @sb_umount: - * Check permission before the @mnt file system is unmounted. - * @mnt contains the mounted file system. - * @flags contains the unmount flags, e.g. MNT_FORCE. - * Return 0 if permission is granted. - * @sb_pivotroot: - * Check permission before pivoting the root filesystem. - * @old_path contains the path for the new location of the - * current root (put_old). - * @new_path contains the path for the new root (new_root). - * Return 0 if permission is granted. - * @sb_set_mnt_opts: - * Set the security relevant mount options used for a superblock - * @sb the superblock to set security mount options for. - * @opts binary data structure containing all lsm mount data. - * Return 0 on success, error on failure. - * @sb_clone_mnt_opts: - * Copy all security options from a given superblock to another - * @oldsb old superblock which contain information to clone. - * @newsb new superblock which needs filled in. - * Return 0 on success, error on failure. - * @move_mount: - * Check permission before a mount is moved. - * @from_path indicates the mount that is going to be moved. - * @to_path indicates the mountpoint that will be mounted upon. - * Return 0 if permission is granted. - * @dentry_init_security: - * Compute a context for a dentry as the inode is not yet available - * since NFSv4 has no label backed by an EA anyway. - * @dentry dentry to use in calculating the context. - * @mode mode used to determine resource type. - * @name name of the last path component used to create file. - * @xattr_name pointer to place the pointer to security xattr name. - * Caller does not have to free the resulting pointer. Its - * a pointer to static string. - * @ctx pointer to place the pointer to the resulting context in. - * @ctxlen point to place the length of the resulting context. - * Return 0 on success, negative values on failure. - * @dentry_create_files_as: - * Compute a context for a dentry as the inode is not yet available - * and set that context in passed in creds so that new files are - * created using that context. Context is calculated using the - * passed in creds and not the creds of the caller. - * @dentry dentry to use in calculating the context. - * @mode mode used to determine resource type. - * @name name of the last path component used to create file. - * @old creds which should be used for context calculation. - * @new creds to modify. - * Return 0 on success, error on failure. - * - * * Security hooks for inode operations. * * @inode_alloc_security: diff --git a/security/security.c b/security/security.c index 64c8805570b1..f1ab64f390bf 100644 --- a/security/security.c +++ b/security/security.c @@ -1025,6 +1025,16 @@ int security_fs_context_parse_param(struct fs_context *fc, return rc; } +/** + * security_sb_alloc() - Allocate a super_block LSM blob + * @sb: filesystem superblock + * + * Allocate and attach a security structure to the sb->s_security field. The + * s_security field is initialized to NULL when the structure is allocated. + * @sb contains the super_block structure to be modified. + * + * Return: Returns 0 if operation was successful. + */ int security_sb_alloc(struct super_block *sb) { int rc = lsm_superblock_alloc(sb); @@ -1037,11 +1047,25 @@ int security_sb_alloc(struct super_block *sb) return rc; } +/** + * security_sb_delete() - Release super_block LSM associated objects + * @sb: filesystem superblock + * + * Release objects tied to a superblock (e.g. inodes). @sb contains the + * super_block structure being released. + */ void security_sb_delete(struct super_block *sb) { call_void_hook(sb_delete, sb); } +/** + * security_sb_free() - Free a super_block LSM blob + * @sb: filesystem superblock + * + * Deallocate and clear the sb->s_security field. @sb contains the super_block + * structure to be modified. + */ void security_sb_free(struct super_block *sb) { call_void_hook(sb_free_security, sb); @@ -1049,6 +1073,12 @@ void security_sb_free(struct super_block *sb) sb->s_security = NULL; } +/** + * security_free_mnt_opts() - Free memory associated with mount options + * @mnt_ops: LSM processed mount options + * + * Free memory associated with @mnt_ops. + */ void security_free_mnt_opts(void **mnt_opts) { if (!*mnt_opts) @@ -1058,12 +1088,31 @@ void security_free_mnt_opts(void **mnt_opts) } EXPORT_SYMBOL(security_free_mnt_opts); +/** + * security_sb_eat_lsm_opts() - Consume LSM mount options + * @options: mount options + * @mnt_ops: LSM processed mount options + * + * Eat (scan @options) and save them in @mnt_opts. + * + * Return: Returns 0 on success, negative values on failure. + */ int security_sb_eat_lsm_opts(char *options, void **mnt_opts) { return call_int_hook(sb_eat_lsm_opts, 0, options, mnt_opts); } EXPORT_SYMBOL(security_sb_eat_lsm_opts); +/** + * security_sb_mnt_opts_compat() - Check if new mount options are allowed + * @sb: filesystem superblock + * @mnt_opts: new mount options + * + * Determine if the new mount options in @mnt_opts are allowed given the + * existing mounted filesystem at @sb. @sb superblock being compared. + * + * Return: Returns 0 if options are compatible. + */ int security_sb_mnt_opts_compat(struct super_block *sb, void *mnt_opts) { @@ -1071,6 +1120,16 @@ int security_sb_mnt_opts_compat(struct super_block *sb, } EXPORT_SYMBOL(security_sb_mnt_opts_compat); +/** + * security_sb_remount() - Verify no incompatible mount changes during remount + * @sb: filesystem superblock + * @mnt_opts: (re)mount options + * + * Extracts security system specific mount options and verifies no changes are + * being made to those options. + * + * Return: Returns 0 if permission is granted. + */ int security_sb_remount(struct super_block *sb, void *mnt_opts) { @@ -1078,37 +1137,109 @@ int security_sb_remount(struct super_block *sb, } EXPORT_SYMBOL(security_sb_remount); +/** + * security_sb_kern_mount() - Check if a kernel mount is allowed + * @sb: filesystem superblock + * + * Mount this @sb if allowed by permissions. + * + * Return: Returns 0 if permission is granted. + */ int security_sb_kern_mount(struct super_block *sb) { return call_int_hook(sb_kern_mount, 0, sb); } +/** + * security_sb_show_options() - Output the mount options for a superblock + * @m: output file + * @sb: filesystem superblock + * + * Show (print on @m) mount options for this @sb. + * + * Return: Returns 0 on success, negative values on failure. + */ int security_sb_show_options(struct seq_file *m, struct super_block *sb) { return call_int_hook(sb_show_options, 0, m, sb); } +/** + * security_sb_statfs() - Check if accessing fs stats is allowed + * @dentry: superblock handle + * + * Check permission before obtaining filesystem statistics for the @mnt + * mountpoint. @dentry is a handle on the superblock for the filesystem. + * + * Return: Returns 0 if permission is granted. + */ int security_sb_statfs(struct dentry *dentry) { return call_int_hook(sb_statfs, 0, dentry); } +/** + * security_sb_mount() - Check permission for mounting a filesystem + * @dev_name: filesystem backing device + * @path: mount point + * @type: filesystem type + * @flags: mount flags + * @data: filesystem specific data + * + * Check permission before an object specified by @dev_name is mounted on the + * mount point named by @nd. For an ordinary mount, @dev_name identifies a + * device if the file system type requires a device. For a remount + * (@flags & MS_REMOUNT), @dev_name is irrelevant. For a loopback/bind mount + * (@flags & MS_BIND), @dev_name identifies the pathname of the object being + * mounted. + * + * Return: Returns 0 if permission is granted. + */ int security_sb_mount(const char *dev_name, const struct path *path, const char *type, unsigned long flags, void *data) { return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data); } +/** + * security_sb_umount() - Check permission for unmounting a filesystem + * @mnt: mounted filesystem + * @flags: unmount flags + * + * Check permission before the @mnt file system is unmounted. + * + * Return: Returns 0 if permission is granted. + */ int security_sb_umount(struct vfsmount *mnt, int flags) { return call_int_hook(sb_umount, 0, mnt, flags); } +/** + * security_sb_pivotroot() - Check permissions for pivoting the rootfs + * @old_path: new location for current rootfs + * @new_path: location of the new rootfs + * + * Check permission before pivoting the root filesystem. + * + * Return: Returns 0 if permission is granted. + */ int security_sb_pivotroot(const struct path *old_path, const struct path *new_path) { return call_int_hook(sb_pivotroot, 0, old_path, new_path); } +/** + * security_sb_set_mnt_opts() - Set the mount options for a filesystem + * @sb: filesystem superblock + * @mnt_opts: binary mount options + * @kern_flags: kernel flags (in) + * @set_kern_flags: kernel flags (out) + * + * Set the security relevant mount options used for a superblock. + * + * Return: Returns 0 on success, error on failure. + */ int security_sb_set_mnt_opts(struct super_block *sb, void *mnt_opts, unsigned long kern_flags, @@ -1120,6 +1251,17 @@ int security_sb_set_mnt_opts(struct super_block *sb, } EXPORT_SYMBOL(security_sb_set_mnt_opts); +/** + * security_sb_clone_mnt_opts() - Duplicate superblock mount options + * @olddb: source superblock + * @newdb: destination superblock + * @kern_flags: kernel flags (in) + * @set_kern_flags: kernel flags (out) + * + * Copy all security options from a given superblock to another. + * + * Return: Returns 0 on success, error on failure. + */ int security_sb_clone_mnt_opts(const struct super_block *oldsb, struct super_block *newsb, unsigned long kern_flags, @@ -1130,6 +1272,15 @@ int security_sb_clone_mnt_opts(const struct super_block *oldsb, } EXPORT_SYMBOL(security_sb_clone_mnt_opts); +/** + * security_move_mount() - Check permissions for moving a mount + * @from_path: source mount point + * @to_path: destination mount point + * + * Check permission before a mount is moved. + * + * Return: Returns 0 if permission is granted. + */ int security_move_mount(const struct path *from_path, const struct path *to_path) { return call_int_hook(move_mount, 0, from_path, to_path); @@ -1179,6 +1330,21 @@ void security_inode_free(struct inode *inode) inode_free_by_rcu); } +/** + * security_dentry_init_security() - Perform dentry initialization + * @dentry: the dentry to initialize + * @mode: mode used to determine resource type + * @name: name of the last path component + * @xattr_name: name of the security/LSM xattr + * @ctx: pointer to the resulting LSM context + * @ctxlen: length of @ctx + * + * Compute a context for a dentry as the inode is not yet available since NFSv4 + * has no label backed by an EA anyway. It is important to note that + * @xattr_name does not need to be free'd by the caller, it is a static string. + * + * Return: Returns 0 on success, negative values on failure. + */ int security_dentry_init_security(struct dentry *dentry, int mode, const struct qstr *name, const char **xattr_name, void **ctx, @@ -1200,6 +1366,21 @@ int security_dentry_init_security(struct dentry *dentry, int mode, } EXPORT_SYMBOL(security_dentry_init_security); +/** + * security_dentry_create_files_as() - Perform dentry initialization + * @dentry: the dentry to initialize + * @mode: mode used to determine resource type + * @name: name of the last path component + * @old: creds to use for LSM context calculations + * @new: creds to modify + * + * Compute a context for a dentry as the inode is not yet available and set + * that context in passed in creds so that new files are created using that + * context. Context is calculated using the passed in creds and not the creds + * of the caller. + * + * Return: Returns 0 on success, error on failure. + */ int security_dentry_create_files_as(struct dentry *dentry, int mode, struct qstr *name, const struct cred *old, struct cred *new) From 916e32584dfaff068792db70c89936801b476ad0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 8 Feb 2023 16:31:55 -0500 Subject: [PATCH 006/291] lsm: move the inode hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 303 ---------------------- security/security.c | 524 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 524 insertions(+), 303 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 3cd6e7abe0df..3cdd58424796 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,309 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for inode operations. - * - * @inode_alloc_security: - * Allocate and attach a security structure to @inode->i_security. The - * i_security field is initialized to NULL when the inode structure is - * allocated. - * @inode contains the inode structure. - * Return 0 if operation was successful. - * @inode_free_security: - * @inode contains the inode structure. - * Deallocate the inode security structure and set @inode->i_security to - * NULL. - * @inode_init_security: - * Obtain the security attribute name suffix and value to set on a newly - * created inode and set up the incore security field for the new inode. - * This hook is called by the fs code as part of the inode creation - * transaction and provides for atomic labeling of the inode, unlike - * the post_create/mkdir/... hooks called by the VFS. The hook function - * is expected to allocate the name and value via kmalloc, with the caller - * being responsible for calling kfree after using them. - * If the security module does not use security attributes or does - * not wish to put a security attribute on this particular inode, - * then it should return -EOPNOTSUPP to skip this processing. - * @inode contains the inode structure of the newly created inode. - * @dir contains the inode structure of the parent directory. - * @qstr contains the last path component of the new object. - * @name will be set to the allocated name suffix (e.g. selinux). - * @value will be set to the allocated attribute value. - * @len will be set to the length of the value. - * Returns 0 if @name and @value have been successfully set, - * -EOPNOTSUPP if no security attribute is needed, or - * -ENOMEM on memory allocation failure. - * @inode_init_security_anon: - * Set up the incore security field for the new anonymous inode - * and return whether the inode creation is permitted by the security - * module or not. - * @inode contains the inode structure. - * @name name of the anonymous inode class. - * @context_inode optional related inode. - * Returns 0 on success, -EACCES if the security module denies the - * creation of this inode, or another -errno upon other errors. - * @inode_create: - * Check permission to create a regular file. - * @dir contains inode structure of the parent of the new file. - * @dentry contains the dentry structure for the file to be created. - * @mode contains the file mode of the file to be created. - * Return 0 if permission is granted. - * @inode_link: - * Check permission before creating a new hard link to a file. - * @old_dentry contains the dentry structure for an existing - * link to the file. - * @dir contains the inode structure of the parent directory - * of the new link. - * @new_dentry contains the dentry structure for the new link. - * Return 0 if permission is granted. - * @path_link: - * Check permission before creating a new hard link to a file. - * @old_dentry contains the dentry structure for an existing link - * to the file. - * @new_dir contains the path structure of the parent directory of - * the new link. - * @new_dentry contains the dentry structure for the new link. - * Return 0 if permission is granted. - * @inode_unlink: - * Check the permission to remove a hard link to a file. - * @dir contains the inode structure of parent directory of the file. - * @dentry contains the dentry structure for file to be unlinked. - * Return 0 if permission is granted. - * @path_unlink: - * Check the permission to remove a hard link to a file. - * @dir contains the path structure of parent directory of the file. - * @dentry contains the dentry structure for file to be unlinked. - * Return 0 if permission is granted. - * @inode_symlink: - * Check the permission to create a symbolic link to a file. - * @dir contains the inode structure of parent directory of - * the symbolic link. - * @dentry contains the dentry structure of the symbolic link. - * @old_name contains the pathname of file. - * Return 0 if permission is granted. - * @path_symlink: - * Check the permission to create a symbolic link to a file. - * @dir contains the path structure of parent directory of - * the symbolic link. - * @dentry contains the dentry structure of the symbolic link. - * @old_name contains the pathname of file. - * Return 0 if permission is granted. - * @inode_mkdir: - * Check permissions to create a new directory in the existing directory - * associated with inode structure @dir. - * @dir contains the inode structure of parent of the directory - * to be created. - * @dentry contains the dentry structure of new directory. - * @mode contains the mode of new directory. - * Return 0 if permission is granted. - * @path_mkdir: - * Check permissions to create a new directory in the existing directory - * associated with path structure @path. - * @dir contains the path structure of parent of the directory - * to be created. - * @dentry contains the dentry structure of new directory. - * @mode contains the mode of new directory. - * Return 0 if permission is granted. - * @inode_rmdir: - * Check the permission to remove a directory. - * @dir contains the inode structure of parent of the directory - * to be removed. - * @dentry contains the dentry structure of directory to be removed. - * Return 0 if permission is granted. - * @path_rmdir: - * Check the permission to remove a directory. - * @dir contains the path structure of parent of the directory to be - * removed. - * @dentry contains the dentry structure of directory to be removed. - * Return 0 if permission is granted. - * @inode_mknod: - * Check permissions when creating a special file (or a socket or a fifo - * file created via the mknod system call). Note that if mknod operation - * is being done for a regular file, then the create hook will be called - * and not this hook. - * @dir contains the inode structure of parent of the new file. - * @dentry contains the dentry structure of the new file. - * @mode contains the mode of the new file. - * @dev contains the device number. - * Return 0 if permission is granted. - * @path_mknod: - * Check permissions when creating a file. Note that this hook is called - * even if mknod operation is being done for a regular file. - * @dir contains the path structure of parent of the new file. - * @dentry contains the dentry structure of the new file. - * @mode contains the mode of the new file. - * @dev contains the undecoded device number. Use new_decode_dev() to get - * the decoded device number. - * Return 0 if permission is granted. - * @inode_rename: - * Check for permission to rename a file or directory. - * @old_dir contains the inode structure for parent of the old link. - * @old_dentry contains the dentry structure of the old link. - * @new_dir contains the inode structure for parent of the new link. - * @new_dentry contains the dentry structure of the new link. - * Return 0 if permission is granted. - * @path_rename: - * Check for permission to rename a file or directory. - * @old_dir contains the path structure for parent of the old link. - * @old_dentry contains the dentry structure of the old link. - * @new_dir contains the path structure for parent of the new link. - * @new_dentry contains the dentry structure of the new link. - * @flags may contain rename options such as RENAME_EXCHANGE. - * Return 0 if permission is granted. - * @path_chmod: - * Check for permission to change a mode of the file @path. The new - * mode is specified in @mode. - * @path contains the path structure of the file to change the mode. - * @mode contains the new DAC's permission, which is a bitmask of - * constants from . - * Return 0 if permission is granted. - * @path_chown: - * Check for permission to change owner/group of a file or directory. - * @path contains the path structure. - * @uid contains new owner's ID. - * @gid contains new group's ID. - * Return 0 if permission is granted. - * @path_chroot: - * Check for permission to change root directory. - * @path contains the path structure. - * Return 0 if permission is granted. - * @path_notify: - * Check permissions before setting a watch on events as defined by @mask, - * on an object at @path, whose type is defined by @obj_type. - * Return 0 if permission is granted. - * @inode_readlink: - * Check the permission to read the symbolic link. - * @dentry contains the dentry structure for the file link. - * Return 0 if permission is granted. - * @inode_follow_link: - * Check permission to follow a symbolic link when looking up a pathname. - * @dentry contains the dentry structure for the link. - * @inode contains the inode, which itself is not stable in RCU-walk. - * @rcu indicates whether we are in RCU-walk mode. - * Return 0 if permission is granted. - * @inode_permission: - * Check permission before accessing an inode. This hook is called by the - * existing Linux permission function, so a security module can use it to - * provide additional checking for existing Linux permission checks. - * Notice that this hook is called when a file is opened (as well as many - * other operations), whereas the file_security_ops permission hook is - * called when the actual read/write operations are performed. - * @inode contains the inode structure to check. - * @mask contains the permission mask. - * Return 0 if permission is granted. - * @inode_setattr: - * Check permission before setting file attributes. Note that the kernel - * call to notify_change is performed from several locations, whenever - * file attributes change (such as when a file is truncated, chown/chmod - * operations, transferring disk quotas, etc). - * @dentry contains the dentry structure for the file. - * @attr is the iattr structure containing the new file attributes. - * Return 0 if permission is granted. - * @path_truncate: - * Check permission before truncating the file indicated by path. - * Note that truncation permissions may also be checked based on - * already opened files, using the @file_truncate hook. - * @path contains the path structure for the file. - * Return 0 if permission is granted. - * @inode_getattr: - * Check permission before obtaining file attributes. - * @path contains the path structure for the file. - * Return 0 if permission is granted. - * @inode_setxattr: - * Check permission before setting the extended attributes - * @value identified by @name for @dentry. - * Return 0 if permission is granted. - * @inode_post_setxattr: - * Update inode security field after successful setxattr operation. - * @value identified by @name for @dentry. - * @inode_getxattr: - * Check permission before obtaining the extended attributes - * identified by @name for @dentry. - * Return 0 if permission is granted. - * @inode_listxattr: - * Check permission before obtaining the list of extended attribute - * names for @dentry. - * Return 0 if permission is granted. - * @inode_removexattr: - * Check permission before removing the extended attribute - * identified by @name for @dentry. - * Return 0 if permission is granted. - * @inode_set_acl: - * Check permission before setting posix acls - * The posix acls in @kacl are identified by @acl_name. - * Return 0 if permission is granted. - * @inode_get_acl: - * Check permission before getting osix acls - * The posix acls are identified by @acl_name. - * Return 0 if permission is granted. - * @inode_remove_acl: - * Check permission before removing posix acls - * The posix acls are identified by @acl_name. - * Return 0 if permission is granted. - * @inode_getsecurity: - * Retrieve a copy of the extended attribute representation of the - * security label associated with @name for @inode via @buffer. Note that - * @name is the remainder of the attribute name after the security prefix - * has been removed. @alloc is used to specify if the call should return a - * value via the buffer or just the value length. - * Return size of buffer on success. - * @inode_setsecurity: - * Set the security label associated with @name for @inode from the - * extended attribute value @value. @size indicates the size of the - * @value in bytes. @flags may be XATTR_CREATE, XATTR_REPLACE, or 0. - * Note that @name is the remainder of the attribute name after the - * security. prefix has been removed. - * Return 0 on success. - * @inode_listsecurity: - * Copy the extended attribute names for the security labels - * associated with @inode into @buffer. The maximum size of @buffer - * is specified by @buffer_size. @buffer may be NULL to request - * the size of the buffer required. - * Returns number of bytes used/required on success. - * @inode_need_killpriv: - * Called when an inode has been changed. - * @dentry is the dentry being changed. - * Return <0 on error to abort the inode change operation. - * Return 0 if inode_killpriv does not need to be called. - * Return >0 if inode_killpriv does need to be called. - * @inode_killpriv: - * The setuid bit is being removed. Remove similar security labels. - * Called with the dentry->d_inode->i_mutex held. - * @idmap: idmap of the mount. - * @dentry is the dentry being changed. - * Return 0 on success. If error is returned, then the operation - * causing setuid bit removal is failed. - * @inode_getsecid: - * Get the secid associated with the node. - * @inode contains a pointer to the inode. - * @secid contains a pointer to the location where result will be saved. - * In case of failure, @secid will be set to zero. - * @inode_copy_up: - * A file is about to be copied up from lower layer to upper layer of - * overlay filesystem. Security module can prepare a set of new creds - * and modify as need be and return new creds. Caller will switch to - * new creds temporarily to create new file and release newly allocated - * creds. - * @src indicates the union dentry of file that is being copied up. - * @new pointer to pointer to return newly allocated creds. - * Returns 0 on success or a negative error code on error. - * @inode_copy_up_xattr: - * Filter the xattrs being copied up when a unioned file is copied - * up from a lower layer to the union/overlay layer. - * @name indicates the name of the xattr. - * Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP if - * security module does not know about attribute or a negative error code - * to abort the copy up. Note that the caller is responsible for reading - * and writing the xattrs as this hook is merely a filter. - * @d_instantiate: - * Fill in @inode security information for a @dentry if allowed. - * @getprocattr: - * Read attribute @name for process @p and store it into @value if allowed. - * Return the length of @value on success, a negative value otherwise. - * @setprocattr: - * Write (set) attribute @name to @value, size @size if allowed. - * Return written bytes on success, a negative value otherwise. - * * Security hooks for kernfs node operations * * @kernfs_init_security: diff --git a/security/security.c b/security/security.c index f1ab64f390bf..bd35854f956a 100644 --- a/security/security.c +++ b/security/security.c @@ -1286,12 +1286,33 @@ int security_move_mount(const struct path *from_path, const struct path *to_path return call_int_hook(move_mount, 0, from_path, to_path); } +/** + * security_path_notify() - Check if setting a watch is allowed + * @path: file path + * @mask: event mask + * @obj_type: file path type + * + * Check permissions before setting a watch on events as defined by @mask, on + * an object at @path, whose type is defined by @obj_type. + * + * Return: Returns 0 if permission is granted. + */ int security_path_notify(const struct path *path, u64 mask, unsigned int obj_type) { return call_int_hook(path_notify, 0, path, mask, obj_type); } +/** + * security_inode_alloc() - Allocate an inode LSM blob + * @inode: the inode + * + * Allocate and attach a security structure to @inode->i_security. The + * i_security field is initialized to NULL when the inode structure is + * allocated. + * + * Return: Return 0 if operation was successful. + */ int security_inode_alloc(struct inode *inode) { int rc = lsm_inode_alloc(inode); @@ -1312,6 +1333,12 @@ static void inode_free_by_rcu(struct rcu_head *head) kmem_cache_free(lsm_inode_cache, head); } +/** + * security_inode_free() - Free an inode's LSM blob + * @inode: the inode + * + * Deallocate the inode security structure and set @inode->i_security to NULL. + */ void security_inode_free(struct inode *inode) { integrity_inode_free(inode); @@ -1390,6 +1417,27 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, } EXPORT_SYMBOL(security_dentry_create_files_as); +/** + * security_inode_init_security() - Initialize an inode's LSM context + * @inode: the inode + * @dir: parent directory + * @qstr: last component of the pathname + * @initxattrs: callback function to write xattrs + * @fs_data: filesystem specific data + * + * Obtain the security attribute name suffix and value to set on a newly + * created inode and set up the incore security field for the new inode. This + * hook is called by the fs code as part of the inode creation transaction and + * provides for atomic labeling of the inode, unlike the post_create/mkdir/... + * hooks called by the VFS. The hook function is expected to allocate the name + * and value via kmalloc, with the caller being responsible for calling kfree + * after using them. If the security module does not use security attributes + * or does not wish to put a security attribute on this particular inode, then + * it should return -EOPNOTSUPP to skip this processing. + * + * Return: Returns 0 on success, -EOPNOTSUPP if no security attribute is + * needed, or -ENOMEM on memory allocation failure. + */ int security_inode_init_security(struct inode *inode, struct inode *dir, const struct qstr *qstr, const initxattrs initxattrs, void *fs_data) @@ -1425,6 +1473,18 @@ out: } EXPORT_SYMBOL(security_inode_init_security); +/** + * security_inode_init_security_anon() - Initialize an anonymous inode + * @inode: the inode + * @name: the anonymous inode class + * @context_inode: an optional related inode + * + * Set up the incore security field for the new anonymous inode and return + * whether the inode creation is permitted by the security module or not. + * + * Return: Returns 0 on success, -EACCES if the security module denies the + * creation of this inode, or another -errno upon other errors. + */ int security_inode_init_security_anon(struct inode *inode, const struct qstr *name, const struct inode *context_inode) @@ -1445,6 +1505,18 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir, EXPORT_SYMBOL(security_old_inode_init_security); #ifdef CONFIG_SECURITY_PATH +/** + * security_path_mknod() - Check if creating a special file is allowed + * @dir: parent directory + * @dentry: new file + * @mode: new file mode + * @dev: device number + * + * Check permissions when creating a file. Note that this hook is called even + * if mknod operation is being done for a regular file. + * + * Return: Returns 0 if permission is granted. + */ int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, unsigned int dev) { @@ -1454,6 +1526,16 @@ int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t m } EXPORT_SYMBOL(security_path_mknod); +/** + * security_path_mkdir() - Check if creating a new directory is allowed + * @dir: parent directory + * @dentry: new directory + * @mode: new directory mode + * + * Check permissions to create a new directory in the existing directory. + * + * Return: Returns 0 if permission is granted. + */ int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) @@ -1462,6 +1544,15 @@ int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t m } EXPORT_SYMBOL(security_path_mkdir); +/** + * security_path_rmdir() - Check if removing a directory is allowed + * @dir: parent directory + * @dentry: directory to remove + * + * Check the permission to remove a directory. + * + * Return: Returns 0 if permission is granted. + */ int security_path_rmdir(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) @@ -1469,6 +1560,15 @@ int security_path_rmdir(const struct path *dir, struct dentry *dentry) return call_int_hook(path_rmdir, 0, dir, dentry); } +/** + * security_path_unlink() - Check if removing a hard link is allowed + * @dir: parent directory + * @dentry: file + * + * Check the permission to remove a hard link to a file. + * + * Return: Returns 0 if permission is granted. + */ int security_path_unlink(const struct path *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) @@ -1477,6 +1577,16 @@ int security_path_unlink(const struct path *dir, struct dentry *dentry) } EXPORT_SYMBOL(security_path_unlink); +/** + * security_path_symlink() - Check if creating a symbolic link is allowed + * @dir: parent directory + * @dentry: symbolic link + * @old_name: file pathname + * + * Check the permission to create a symbolic link to a file. + * + * Return: Returns 0 if permission is granted. + */ int security_path_symlink(const struct path *dir, struct dentry *dentry, const char *old_name) { @@ -1485,6 +1595,16 @@ int security_path_symlink(const struct path *dir, struct dentry *dentry, return call_int_hook(path_symlink, 0, dir, dentry, old_name); } +/** + * security_path_link - Check if creating a hard link is allowed + * @old_dentry: existing file + * @new_dir: new parent directory + * @new_dentry: new link + * + * Check permission before creating a new hard link to a file. + * + * Return: Returns 0 if permission is granted. + */ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry) { @@ -1493,6 +1613,18 @@ int security_path_link(struct dentry *old_dentry, const struct path *new_dir, return call_int_hook(path_link, 0, old_dentry, new_dir, new_dentry); } +/** + * security_path_rename() - Check if renaming a file is allowed + * @old_dir: parent directory of the old file + * @old_dentry: the old file + * @new_dir: parent directory of the new file + * @new_dentry: the new file + * @flags: flags + * + * Check for permission to rename a file or directory. + * + * Return: Returns 0 if permission is granted. + */ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, const struct path *new_dir, struct dentry *new_dentry, unsigned int flags) @@ -1506,6 +1638,16 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, } EXPORT_SYMBOL(security_path_rename); +/** + * security_path_truncate() - Check if truncating a file is allowed + * @path: file + * + * Check permission before truncating the file indicated by path. Note that + * truncation permissions may also be checked based on already opened files, + * using the security_file_truncate() hook. + * + * Return: Returns 0 if permission is granted. + */ int security_path_truncate(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) @@ -1513,6 +1655,17 @@ int security_path_truncate(const struct path *path) return call_int_hook(path_truncate, 0, path); } +/** + * security_path_chmod() - Check if changing the file's mode is allowed + * @path: file + * @mode: new mode + * + * Check for permission to change a mode of the file @path. The new mode is + * specified in @mode which is a bitmask of constants from + * . + * + * Return: Returns 0 if permission is granted. + */ int security_path_chmod(const struct path *path, umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) @@ -1520,6 +1673,16 @@ int security_path_chmod(const struct path *path, umode_t mode) return call_int_hook(path_chmod, 0, path, mode); } +/** + * security_path_chown() - Check if changing the file's owner/group is allowed + * @path: file + * @uid: file owner + * @gid: file group + * + * Check for permission to change owner/group of a file or directory. + * + * Return: Returns 0 if permission is granted. + */ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) @@ -1527,12 +1690,30 @@ int security_path_chown(const struct path *path, kuid_t uid, kgid_t gid) return call_int_hook(path_chown, 0, path, uid, gid); } +/** + * security_path_chroot() - Check if changing the root directory is allowed + * @path: directory + * + * Check for permission to change root directory. + * + * Return: Returns 0 if permission is granted. + */ int security_path_chroot(const struct path *path) { return call_int_hook(path_chroot, 0, path); } #endif +/** + * security_inode_create() - Check if creating a file is allowed + * @dir: the parent directory + * @dentry: the file being created + * @mode: requested file mode + * + * Check permission to create a regular file. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) @@ -1541,6 +1722,16 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode } EXPORT_SYMBOL_GPL(security_inode_create); +/** + * security_inode_link() - Check if creating a hard link is allowed + * @old_dentry: existing file + * @dir: new parent directory + * @new_dentry: new link + * + * Check permission before creating a new hard link to a file. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry) { @@ -1549,6 +1740,15 @@ int security_inode_link(struct dentry *old_dentry, struct inode *dir, return call_int_hook(inode_link, 0, old_dentry, dir, new_dentry); } +/** + * security_inode_unlink() - Check if removing a hard link is allowed + * @dir: parent directory + * @dentry: file + * + * Check the permission to remove a hard link to a file. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_unlink(struct inode *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) @@ -1556,6 +1756,16 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) return call_int_hook(inode_unlink, 0, dir, dentry); } +/** + * security_inode_symlink() Check if creating a symbolic link is allowed + * @dir: parent directory + * @dentry: symbolic link + * @old_name: existing filename + * + * Check the permission to create a symbolic link to a file. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_symlink(struct inode *dir, struct dentry *dentry, const char *old_name) { @@ -1564,6 +1774,17 @@ int security_inode_symlink(struct inode *dir, struct dentry *dentry, return call_int_hook(inode_symlink, 0, dir, dentry, old_name); } +/** + * security_inode_mkdir() - Check if creation a new director is allowed + * @dir: parent directory + * @dentry: new directory + * @mode: new directory mode + * + * Check permissions to create a new directory in the existing directory + * associated with inode structure @dir. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) { if (unlikely(IS_PRIVATE(dir))) @@ -1572,6 +1793,15 @@ int security_inode_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) } EXPORT_SYMBOL_GPL(security_inode_mkdir); +/** + * security_inode_rmdir() - Check if removing a directory is allowed + * @dir: parent directory + * @dentry: directory to be removed + * + * Check the permission to remove a directory. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) @@ -1579,6 +1809,20 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) return call_int_hook(inode_rmdir, 0, dir, dentry); } +/** + * security_inode_mknod() - Check if creating a special file is allowed + * @dir: parent directory + * @dentry: new file + * @mode: new file mode + * @dev: device number + * + * Check permissions when creating a special file (or a socket or a fifo file + * created via the mknod system call). Note that if mknod operation is being + * done for a regular file, then the create hook will be called and not this + * hook. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) { if (unlikely(IS_PRIVATE(dir))) @@ -1586,6 +1830,18 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, return call_int_hook(inode_mknod, 0, dir, dentry, mode, dev); } +/** + * security_inode_rename() - Check if renaming a file is allowed + * @old_dir: parent directory of the old file + * @old_dentry: the old file + * @new_dir: parent directory of the new file + * @new_dentry: the new file + * @flags: flags + * + * Check for permission to rename a file or directory. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, struct inode *new_dir, struct dentry *new_dentry, unsigned int flags) @@ -1605,6 +1861,14 @@ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, new_dir, new_dentry); } +/** + * security_inode_readlink() - Check if reading a symbolic link is allowed + * @dentry: link + * + * Check the permission to read the symbolic link. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_readlink(struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) @@ -1612,6 +1876,17 @@ int security_inode_readlink(struct dentry *dentry) return call_int_hook(inode_readlink, 0, dentry); } +/** + * security_inode_follow_link() - Check if following a symbolic link is allowed + * @dentry: link dentry + * @inode: link inode + * @rcu: true if in RCU-walk mode + * + * Check permission to follow a symbolic link when looking up a pathname. If + * @rcu is true, @inode is not stable. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, bool rcu) { @@ -1620,6 +1895,20 @@ int security_inode_follow_link(struct dentry *dentry, struct inode *inode, return call_int_hook(inode_follow_link, 0, dentry, inode, rcu); } +/** + * security_inode_permission() - Check if accessing an inode is allowed + * @inode: inode + * @mask: access mask + * + * Check permission before accessing an inode. This hook is called by the + * existing Linux permission function, so a security module can use it to + * provide additional checking for existing Linux permission checks. Notice + * that this hook is called when a file is opened (as well as many other + * operations), whereas the file_security_ops permission hook is called when + * the actual read/write operations are performed. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_permission(struct inode *inode, int mask) { if (unlikely(IS_PRIVATE(inode))) @@ -1627,6 +1916,19 @@ int security_inode_permission(struct inode *inode, int mask) return call_int_hook(inode_permission, 0, inode, mask); } +/** + * security_inode_setattr() - Check if setting file attributes is allowed + * @idmap: idmap of the mount + * @dentry: file + * @attr: new attributes + * + * Check permission before setting file attributes. Note that the kernel call + * to notify_change is performed from several locations, whenever file + * attributes change (such as when a file is truncated, chown/chmod operations, + * transferring disk quotas, etc). + * + * Return: Returns 0 if permission is granted. + */ int security_inode_setattr(struct mnt_idmap *idmap, struct dentry *dentry, struct iattr *attr) { @@ -1641,6 +1943,14 @@ int security_inode_setattr(struct mnt_idmap *idmap, } EXPORT_SYMBOL_GPL(security_inode_setattr); +/** + * security_inode_getattr() - Check if getting file attributes is allowed + * @path: file + * + * Check permission before obtaining file attributes. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_getattr(const struct path *path) { if (unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))) @@ -1648,6 +1958,18 @@ int security_inode_getattr(const struct path *path) return call_int_hook(inode_getattr, 0, path); } +/** + * security_inode_setxattr() - Check if setting file xattrs is allowed + * @idmap: idmap of the mount + * @dentry: file + * @name: xattr name + * @value: xattr value + * @flags: flags + * + * Check permission before setting the extended attributes. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_setxattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name, const void *value, size_t size, int flags) @@ -1673,6 +1995,18 @@ int security_inode_setxattr(struct mnt_idmap *idmap, return evm_inode_setxattr(idmap, dentry, name, value, size); } +/** + * security_inode_set_acl() - Check if setting posix acls is allowed + * @idmap: idmap of the mount + * @dentry: file + * @acl_name: acl name + * @kacl: acl struct + * + * Check permission before setting posix acls, the posix acls in @kacl are + * identified by @acl_name. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_set_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name, struct posix_acl *kacl) @@ -1691,6 +2025,17 @@ int security_inode_set_acl(struct mnt_idmap *idmap, return evm_inode_set_acl(idmap, dentry, acl_name, kacl); } +/** + * security_inode_get_acl() - Check if reading posix acls is allowed + * @idmap: idmap of the mount + * @dentry: file + * @acl_name: acl name + * + * Check permission before getting osix acls, the posix acls are identified by + * @acl_name. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_get_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) { @@ -1699,6 +2044,17 @@ int security_inode_get_acl(struct mnt_idmap *idmap, return call_int_hook(inode_get_acl, 0, idmap, dentry, acl_name); } +/** + * security_inode_remove_acl() - Check if removing a posix acl is allowed + * @idmap: idmap of the mount + * @dentry: file + * @acl_name: acl name + * + * Check permission before removing posix acls, the posix acls are identified + * by @acl_name. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_remove_acl(struct mnt_idmap *idmap, struct dentry *dentry, const char *acl_name) { @@ -1715,6 +2071,16 @@ int security_inode_remove_acl(struct mnt_idmap *idmap, return evm_inode_remove_acl(idmap, dentry, acl_name); } +/** + * security_inode_post_setxattr() - Update the inode after a setxattr operation + * @dentry: file + * @name: xattr name + * @value: xattr value + * @size: xattr value size + * @flags: flags + * + * Update inode security field after successful setxattr operation. + */ void security_inode_post_setxattr(struct dentry *dentry, const char *name, const void *value, size_t size, int flags) { @@ -1724,6 +2090,16 @@ void security_inode_post_setxattr(struct dentry *dentry, const char *name, evm_inode_post_setxattr(dentry, name, value, size); } +/** + * security_inode_getxattr() - Check if xattr access is allowed + * @dentry: file + * @name: xattr name + * + * Check permission before obtaining the extended attributes identified by + * @name for @dentry. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_getxattr(struct dentry *dentry, const char *name) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) @@ -1731,6 +2107,15 @@ int security_inode_getxattr(struct dentry *dentry, const char *name) return call_int_hook(inode_getxattr, 0, dentry, name); } +/** + * security_inode_listxattr() - Check if listing xattrs is allowed + * @dentry: file + * + * Check permission before obtaining the list of extended attribute names for + * @dentry. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_listxattr(struct dentry *dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(dentry)))) @@ -1738,6 +2123,17 @@ int security_inode_listxattr(struct dentry *dentry) return call_int_hook(inode_listxattr, 0, dentry); } +/** + * security_inode_removexattr() - Check if removing an xattr is allowed + * @idmap: idmap of the mount + * @dentry: file + * @name: xattr name + * + * Check permission before removing the extended attribute identified by @name + * for @dentry. + * + * Return: Returns 0 if permission is granted. + */ int security_inode_removexattr(struct mnt_idmap *idmap, struct dentry *dentry, const char *name) { @@ -1760,17 +2156,55 @@ int security_inode_removexattr(struct mnt_idmap *idmap, return evm_inode_removexattr(idmap, dentry, name); } +/** + * security_inode_need_killpriv() - Check if security_inode_killpriv() required + * @dentry: associated dentry + * + * Called when an inode has been changed to determine if + * security_inode_killpriv() should be called. + * + * Return: Return <0 on error to abort the inode change operation, return 0 if + * security_inode_killpriv() does not need to be called, return >0 if + * security_inode_killpriv() does need to be called. + */ int security_inode_need_killpriv(struct dentry *dentry) { return call_int_hook(inode_need_killpriv, 0, dentry); } +/** + * security_inode_killpriv() - The setuid bit is removed, update LSM state + * @idmap: idmap of the mount + * @dentry: associated dentry + * + * The @dentry's setuid bit is being removed. Remove similar security labels. + * Called with the dentry->d_inode->i_mutex held. + * + * Return: Return 0 on success. If error is returned, then the operation + * causing setuid bit removal is failed. + */ int security_inode_killpriv(struct mnt_idmap *idmap, struct dentry *dentry) { return call_int_hook(inode_killpriv, 0, idmap, dentry); } +/** + * security_inode_getsecurity() - Get the xattr security label of an inode + * @idmap: idmap of the mount + * @inode: inode + * @name: xattr name + * @buffer: security label buffer + * @alloc: allocation flag + * + * Retrieve a copy of the extended attribute representation of the security + * label associated with @name for @inode via @buffer. Note that @name is the + * remainder of the attribute name after the security prefix has been removed. + * @alloc is used to specify if the call should return a value via the buffer + * or just the value length. + * + * Return: Returns size of buffer on success. + */ int security_inode_getsecurity(struct mnt_idmap *idmap, struct inode *inode, const char *name, void **buffer, bool alloc) @@ -1791,6 +2225,21 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, return LSM_RET_DEFAULT(inode_getsecurity); } +/** + * security_inode_setsecurity() - Set the xattr security label of an inode + * @inode: inode + * @name: xattr name + * @value: security label + * @size: length of security label + * @flags: flags + * + * Set the security label associated with @name for @inode from the extended + * attribute value @value. @size indicates the size of the @value in bytes. + * @flags may be XATTR_CREATE, XATTR_REPLACE, or 0. Note that @name is the + * remainder of the attribute name after the security. prefix has been removed. + * + * Return: Returns 0 on success. + */ int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) { struct security_hook_list *hp; @@ -1810,6 +2259,19 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void return LSM_RET_DEFAULT(inode_setsecurity); } +/** + * security_inode_listsecurity() - List the xattr security label names + * @inode: inode + * @buffer: buffer + * @buffer_size: size of buffer + * + * Copy the extended attribute names for the security labels associated with + * @inode into @buffer. The maximum size of @buffer is specified by + * @buffer_size. @buffer may be NULL to request the size of the buffer + * required. + * + * Return: Returns number of bytes used/required on success. + */ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) { if (unlikely(IS_PRIVATE(inode))) @@ -1818,17 +2280,49 @@ int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer } EXPORT_SYMBOL(security_inode_listsecurity); +/** + * security_inode_getsecid() - Get an inode's secid + * @inode: inode + * @secid: secid to return + * + * Get the secid associated with the node. In case of failure, @secid will be + * set to zero. + */ void security_inode_getsecid(struct inode *inode, u32 *secid) { call_void_hook(inode_getsecid, inode, secid); } +/** + * security_inode_copy_up() - Create new creds for an overlayfs copy-up op + * @src: union dentry of copy-up file + * @new: newly created creds + * + * A file is about to be copied up from lower layer to upper layer of overlay + * filesystem. Security module can prepare a set of new creds and modify as + * need be and return new creds. Caller will switch to new creds temporarily to + * create new file and release newly allocated creds. + * + * Return: Returns 0 on success or a negative error code on error. + */ int security_inode_copy_up(struct dentry *src, struct cred **new) { return call_int_hook(inode_copy_up, 0, src, new); } EXPORT_SYMBOL(security_inode_copy_up); +/** + * security_inode_copy_up_xattr() - Filter xattrs in an overlayfs copy-up op + * @name: xattr name + * + * Filter the xattrs being copied up when a unioned file is copied up from a + * lower layer to the union/overlay layer. The caller is responsible for + * reading and writing the xattrs, this hook is merely a filter. + * + * Return: Returns 0 to accept the xattr, 1 to discard the xattr, -EOPNOTSUPP + * if the security module does not know about attribute, or a negative + * error code to abort the copy up. + */ int security_inode_copy_up_xattr(const char *name) { struct security_hook_list *hp; @@ -2405,6 +2899,13 @@ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, return call_int_hook(sem_semop, 0, sma, sops, nsops, alter); } +/** + * security_d_instantiate() - Populate an inode's LSM state based on a dentry + * @dentry: dentry + * @inode: inode + * + * Fill in @inode security information for a @dentry if allowed. + */ void security_d_instantiate(struct dentry *dentry, struct inode *inode) { if (unlikely(inode && IS_PRIVATE(inode))) @@ -2413,6 +2914,17 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode) } EXPORT_SYMBOL(security_d_instantiate); +/** + * security_getprocattr() - Read an attribute for a task + * @p: the task + * @lsm: LSM name + * @name: attribute name + * @value: attribute value + * + * Read attribute @name for task @p and store it into @value if allowed. + * + * Return: Returns the length of @value on success, a negative value otherwise. + */ int security_getprocattr(struct task_struct *p, const char *lsm, const char *name, char **value) { @@ -2426,6 +2938,18 @@ int security_getprocattr(struct task_struct *p, const char *lsm, return LSM_RET_DEFAULT(getprocattr); } +/** + * security_setprocattr() - Set an attribute for a task + * @lsm: LSM name + * @name: attribute name + * @value: attribute value + * @size: attribute value size + * + * Write (set) the current task's attribute @name to @value, size @size if + * allowed. + * + * Return: Returns bytes written on success, a negative value otherwise. + */ int security_setprocattr(const char *lsm, const char *name, void *value, size_t size) { From 9348944b775d9a12ee7ab698df5bad85409bdd48 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Feb 2023 13:20:33 -0500 Subject: [PATCH 007/291] lsm: move the kernfs hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 9 --------- security/security.c | 10 ++++++++++ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 3cdd58424796..c953f6c356f2 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,15 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for kernfs node operations - * - * @kernfs_init_security: - * Initialize the security context of a newly created kernfs node based - * on its own and its parent's attributes. - * @kn_dir the parent kernfs node. - * @kn the new child kernfs node. - * Return 0 if permission is granted. - * * Security hooks for file operations * * @file_permission: diff --git a/security/security.c b/security/security.c index bd35854f956a..b070a24157ec 100644 --- a/security/security.c +++ b/security/security.c @@ -2344,6 +2344,16 @@ int security_inode_copy_up_xattr(const char *name) } EXPORT_SYMBOL(security_inode_copy_up_xattr); +/** + * security_kernfs_init_security() - Init LSM context for a kernfs node + * @kn_dir: parent kernfs node + * @kn: the kernfs node to initialize + * + * Initialize the security context of a newly created kernfs node based on its + * own and its parent's attributes. + * + * Return: Returns 0 if permission is granted. + */ int security_kernfs_init_security(struct kernfs_node *kn_dir, struct kernfs_node *kn) { From a0fd6480de489780cdf0940a38bb75b949976d6c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Fri, 10 Feb 2023 13:23:09 -0500 Subject: [PATCH 008/291] lsm: move the file hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 104 -------------------------- security/security.c | 151 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 151 insertions(+), 104 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index c953f6c356f2..7c58683b9288 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,110 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for file operations - * - * @file_permission: - * Check file permissions before accessing an open file. This hook is - * called by various operations that read or write files. A security - * module can use this hook to perform additional checking on these - * operations, e.g. to revalidate permissions on use to support privilege - * bracketing or policy changes. Notice that this hook is used when the - * actual read/write operations are performed, whereas the - * inode_security_ops hook is called when a file is opened (as well as - * many other operations). - * Caveat: Although this hook can be used to revalidate permissions for - * various system call operations that read or write files, it does not - * address the revalidation of permissions for memory-mapped files. - * Security modules must handle this separately if they need such - * revalidation. - * @file contains the file structure being accessed. - * @mask contains the requested permissions. - * Return 0 if permission is granted. - * @file_alloc_security: - * Allocate and attach a security structure to the file->f_security field. - * The security field is initialized to NULL when the structure is first - * created. - * @file contains the file structure to secure. - * Return 0 if the hook is successful and permission is granted. - * @file_free_security: - * Deallocate and free any security structures stored in file->f_security. - * @file contains the file structure being modified. - * @file_ioctl: - * @file contains the file structure. - * @cmd contains the operation to perform. - * @arg contains the operational arguments. - * Check permission for an ioctl operation on @file. Note that @arg - * sometimes represents a user space pointer; in other cases, it may be a - * simple integer value. When @arg represents a user space pointer, it - * should never be used by the security module. - * Return 0 if permission is granted. - * @mmap_addr: - * Check permissions for a mmap operation at @addr. - * @addr contains virtual address that will be used for the operation. - * Return 0 if permission is granted. - * @mmap_file: - * Check permissions for a mmap operation. The @file may be NULL, e.g. - * if mapping anonymous memory. - * @file contains the file structure for file to map (may be NULL). - * @reqprot contains the protection requested by the application. - * @prot contains the protection that will be applied by the kernel. - * @flags contains the operational flags. - * Return 0 if permission is granted. - * @file_mprotect: - * Check permissions before changing memory access permissions. - * @vma contains the memory region to modify. - * @reqprot contains the protection requested by the application. - * @prot contains the protection that will be applied by the kernel. - * Return 0 if permission is granted. - * @file_lock: - * Check permission before performing file locking operations. - * Note the hook mediates both flock and fcntl style locks. - * @file contains the file structure. - * @cmd contains the posix-translated lock operation to perform - * (e.g. F_RDLCK, F_WRLCK). - * Return 0 if permission is granted. - * @file_fcntl: - * Check permission before allowing the file operation specified by @cmd - * from being performed on the file @file. Note that @arg sometimes - * represents a user space pointer; in other cases, it may be a simple - * integer value. When @arg represents a user space pointer, it should - * never be used by the security module. - * @file contains the file structure. - * @cmd contains the operation to be performed. - * @arg contains the operational arguments. - * Return 0 if permission is granted. - * @file_set_fowner: - * Save owner security information (typically from current->security) in - * file->f_security for later use by the send_sigiotask hook. - * @file contains the file structure to update. - * Return 0 on success. - * @file_send_sigiotask: - * Check permission for the file owner @fown to send SIGIO or SIGURG to the - * process @tsk. Note that this hook is sometimes called from interrupt. - * Note that the fown_struct, @fown, is never outside the context of a - * struct file, so the file structure (and associated security information) - * can always be obtained: container_of(fown, struct file, f_owner) - * @tsk contains the structure of task receiving signal. - * @fown contains the file owner information. - * @sig is the signal that will be sent. When 0, kernel sends SIGIO. - * Return 0 if permission is granted. - * @file_receive: - * This hook allows security modules to control the ability of a process - * to receive an open file descriptor via socket IPC. - * @file contains the file structure being received. - * Return 0 if permission is granted. - * @file_truncate: - * Check permission before truncating a file, i.e. using ftruncate. - * Note that truncation permission may also be checked based on the path, - * using the @path_truncate hook. - * @file contains the file structure for the file. - * Return 0 if permission is granted. - * @file_open: - * Save open-time permission checking state for later use upon - * file_permission, and recheck access if anything has changed - * since inode_permission. - * Return 0 if permission is granted. - * * Security hooks for task operations. * * @task_alloc: diff --git a/security/security.c b/security/security.c index b070a24157ec..a527291c191d 100644 --- a/security/security.c +++ b/security/security.c @@ -2360,6 +2360,25 @@ int security_kernfs_init_security(struct kernfs_node *kn_dir, return call_int_hook(kernfs_init_security, 0, kn_dir, kn); } +/** + * security_file_permission() - Check file permissions + * @file: file + * @mask: requested permissions + * + * Check file permissions before accessing an open file. This hook is called + * by various operations that read or write files. A security module can use + * this hook to perform additional checking on these operations, e.g. to + * revalidate permissions on use to support privilege bracketing or policy + * changes. Notice that this hook is used when the actual read/write + * operations are performed, whereas the inode_security_ops hook is called when + * a file is opened (as well as many other operations). Although this hook can + * be used to revalidate permissions for various system call operations that + * read or write files, it does not address the revalidation of permissions for + * memory-mapped files. Security modules must handle this separately if they + * need such revalidation. + * + * Return: Returns 0 if permission is granted. + */ int security_file_permission(struct file *file, int mask) { int ret; @@ -2371,6 +2390,15 @@ int security_file_permission(struct file *file, int mask) return fsnotify_perm(file, mask); } +/** + * security_file_alloc() - Allocate and init a file's LSM blob + * @file: the file + * + * Allocate and attach a security structure to the file->f_security field. The + * security field is initialized to NULL when the structure is first created. + * + * Return: Return 0 if the hook is successful and permission is granted. + */ int security_file_alloc(struct file *file) { int rc = lsm_file_alloc(file); @@ -2383,6 +2411,12 @@ int security_file_alloc(struct file *file) return rc; } +/** + * security_file_free() - Free a file's LSM blob + * @file: the file + * + * Deallocate and free any security structures stored in file->f_security. + */ void security_file_free(struct file *file) { void *blob; @@ -2396,6 +2430,19 @@ void security_file_free(struct file *file) } } +/** + * security_file_ioctl() - Check if an ioctl is allowed + * @file: associated file + * @cmd: ioctl cmd + * @arg: ioctl arguments + * + * Check permission for an ioctl operation on @file. Note that @arg sometimes + * represents a user space pointer; in other cases, it may be a simple integer + * value. When @arg represents a user space pointer, it should never be used + * by the security module. + * + * Return: Returns 0 if permission is granted. + */ int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { return call_int_hook(file_ioctl, 0, file, cmd, arg); @@ -2435,6 +2482,17 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot) return prot; } +/** + * security_mmap_file() - Check if mmap'ing a file is allowed + * @file: file + * @prot: protection applied by the kernel + * @flags: flags + * + * Check permissions for a mmap operation. The @file may be NULL, e.g. if + * mapping anonymous memory. + * + * Return: Returns 0 if permission is granted. + */ int security_mmap_file(struct file *file, unsigned long prot, unsigned long flags) { @@ -2447,11 +2505,29 @@ int security_mmap_file(struct file *file, unsigned long prot, return ima_file_mmap(file, prot, prot_adj, flags); } +/** + * security_mmap_addr() - Check if mmap'ing an address is allowed + * @addr: address + * + * Check permissions for a mmap operation at @addr. + * + * Return: Returns 0 if permission is granted. + */ int security_mmap_addr(unsigned long addr) { return call_int_hook(mmap_addr, 0, addr); } +/** + * security_file_mprotect() - Check if changing memory protections is allowed + * @vma: memory region + * @reqprot: application requested protection + * @prog: protection applied by the kernel + * + * Check permissions before changing memory access permissions. + * + * Return: Returns 0 if permission is granted. + */ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, unsigned long prot) { @@ -2463,32 +2539,97 @@ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, return ima_file_mprotect(vma, prot); } +/** + * security_file_lock() - Check if a file lock is allowed + * @file: file + * @cmd: lock operation (e.g. F_RDLCK, F_WRLCK) + * + * Check permission before performing file locking operations. Note the hook + * mediates both flock and fcntl style locks. + * + * Return: Returns 0 if permission is granted. + */ int security_file_lock(struct file *file, unsigned int cmd) { return call_int_hook(file_lock, 0, file, cmd); } +/** + * security_file_fcntl() - Check if fcntl() op is allowed + * @file: file + * @cmd: fnctl command + * @arg: command argument + * + * Check permission before allowing the file operation specified by @cmd from + * being performed on the file @file. Note that @arg sometimes represents a + * user space pointer; in other cases, it may be a simple integer value. When + * @arg represents a user space pointer, it should never be used by the + * security module. + * + * Return: Returns 0 if permission is granted. + */ int security_file_fcntl(struct file *file, unsigned int cmd, unsigned long arg) { return call_int_hook(file_fcntl, 0, file, cmd, arg); } +/** + * security_file_set_fowner() - Set the file owner info in the LSM blob + * @file: the file + * + * Save owner security information (typically from current->security) in + * file->f_security for later use by the send_sigiotask hook. + * + * Return: Returns 0 on success. + */ void security_file_set_fowner(struct file *file) { call_void_hook(file_set_fowner, file); } +/** + * security_file_send_sigiotask() - Check if sending SIGIO/SIGURG is allowed + * @tsk: target task + * @fown: signal sender + * @sig: signal to be sent, SIGIO is sent if 0 + * + * Check permission for the file owner @fown to send SIGIO or SIGURG to the + * process @tsk. Note that this hook is sometimes called from interrupt. Note + * that the fown_struct, @fown, is never outside the context of a struct file, + * so the file structure (and associated security information) can always be + * obtained: container_of(fown, struct file, f_owner). + * + * Return: Returns 0 if permission is granted. + */ int security_file_send_sigiotask(struct task_struct *tsk, struct fown_struct *fown, int sig) { return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig); } +/** + * security_file_receive() - Check is receiving a file via IPC is allowed + * @file: file being received + * + * This hook allows security modules to control the ability of a process to + * receive an open file descriptor via socket IPC. + * + * Return: Returns 0 if permission is granted. + */ int security_file_receive(struct file *file) { return call_int_hook(file_receive, 0, file); } +/** + * security_file_open() - Save open() time state for late use by the LSM + * @file: + * + * Save open-time permission checking state for later use upon file_permission, + * and recheck access if anything has changed since inode_permission. + * + * Return: Returns 0 if permission is granted. + */ int security_file_open(struct file *file) { int ret; @@ -2500,6 +2641,16 @@ int security_file_open(struct file *file) return fsnotify_perm(file, MAY_OPEN); } +/** + * security_file_truncate() - Check if truncating a file is allowed + * @file: file + * + * Check permission before truncating a file, i.e. using ftruncate. Note that + * truncation permission may also be checked based on the path, using the + * @path_truncate hook. + * + * Return: Returns 0 if permission is granted. + */ int security_file_truncate(struct file *file) { return call_int_hook(file_truncate, 0, file); From 130c53bfee4bc70919d356bd8b30137ba4d665b1 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sat, 11 Feb 2023 19:27:58 -0500 Subject: [PATCH 009/291] lsm: move the task hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 210 ------------------------ security/security.c | 334 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 334 insertions(+), 210 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 7c58683b9288..5578a13729bd 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,216 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for task operations. - * - * @task_alloc: - * @task task being allocated. - * @clone_flags contains the flags indicating what should be shared. - * Handle allocation of task-related resources. - * Returns a zero on success, negative values on failure. - * @task_free: - * @task task about to be freed. - * Handle release of task-related resources. (Note that this can be called - * from interrupt context.) - * @cred_alloc_blank: - * @cred points to the credentials. - * @gfp indicates the atomicity of any memory allocations. - * Only allocate sufficient memory and attach to @cred such that - * cred_transfer() will not get ENOMEM. - * Return 0 on success, negative values on failure. - * @cred_free: - * @cred points to the credentials. - * Deallocate and clear the cred->security field in a set of credentials. - * @cred_prepare: - * @new points to the new credentials. - * @old points to the original credentials. - * @gfp indicates the atomicity of any memory allocations. - * Prepare a new set of credentials by copying the data from the old set. - * Return 0 on success, negative values on failure. - * @cred_transfer: - * @new points to the new credentials. - * @old points to the original credentials. - * Transfer data from original creds to new creds - * @cred_getsecid: - * Retrieve the security identifier of the cred structure @c - * @c contains the credentials, secid will be placed into @secid. - * In case of failure, @secid will be set to zero. - * @kernel_act_as: - * Set the credentials for a kernel service to act as (subjective context). - * @new points to the credentials to be modified. - * @secid specifies the security ID to be set. - * The current task must be the one that nominated @secid. - * Return 0 if successful. - * @kernel_create_files_as: - * Set the file creation context in a set of credentials to be the same as - * the objective context of the specified inode. - * @new points to the credentials to be modified. - * @inode points to the inode to use as a reference. - * The current task must be the one that nominated @inode. - * Return 0 if successful. - * @kernel_module_request: - * Ability to trigger the kernel to automatically upcall to userspace for - * userspace to load a kernel module with the given name. - * @kmod_name name of the module requested by the kernel. - * Return 0 if successful. - * @kernel_load_data: - * Load data provided by userspace. - * @id kernel load data identifier. - * @contents if a subsequent @kernel_post_load_data will be called. - * Return 0 if permission is granted. - * @kernel_post_load_data: - * Load data provided by a non-file source (usually userspace buffer). - * @buf pointer to buffer containing the data contents. - * @size length of the data contents. - * @id kernel load data identifier. - * @description a text description of what was loaded, @id-specific. - * Return 0 if permission is granted. - * This must be paired with a prior @kernel_load_data call that had - * @contents set to true. - * @kernel_read_file: - * Read a file specified by userspace. - * @file contains the file structure pointing to the file being read - * by the kernel. - * @id kernel read file identifier. - * @contents if a subsequent @kernel_post_read_file will be called. - * Return 0 if permission is granted. - * @kernel_post_read_file: - * Read a file specified by userspace. - * @file contains the file structure pointing to the file being read - * by the kernel. - * @buf pointer to buffer containing the file contents. - * @size length of the file contents. - * @id kernel read file identifier. - * This must be paired with a prior @kernel_read_file call that had - * @contents set to true. - * Return 0 if permission is granted. - * @task_fix_setuid: - * Update the module's state after setting one or more of the user - * identity attributes of the current process. The @flags parameter - * indicates which of the set*uid system calls invoked this hook. If - * @new is the set of credentials that will be installed. Modifications - * should be made to this rather than to @current->cred. - * @old is the set of credentials that are being replaced. - * @flags contains one of the LSM_SETID_* values. - * Return 0 on success. - * @task_fix_setgid: - * Update the module's state after setting one or more of the group - * identity attributes of the current process. The @flags parameter - * indicates which of the set*gid system calls invoked this hook. - * @new is the set of credentials that will be installed. Modifications - * should be made to this rather than to @current->cred. - * @old is the set of credentials that are being replaced. - * @flags contains one of the LSM_SETID_* values. - * Return 0 on success. - * @task_fix_setgroups: - * Update the module's state after setting the supplementary group - * identity attributes of the current process. - * @new is the set of credentials that will be installed. Modifications - * should be made to this rather than to @current->cred. - * @old is the set of credentials that are being replaced. - * Return 0 on success. - * @task_setpgid: - * Check permission before setting the process group identifier of the - * process @p to @pgid. - * @p contains the task_struct for process being modified. - * @pgid contains the new pgid. - * Return 0 if permission is granted. - * @task_getpgid: - * Check permission before getting the process group identifier of the - * process @p. - * @p contains the task_struct for the process. - * Return 0 if permission is granted. - * @task_getsid: - * Check permission before getting the session identifier of the process - * @p. - * @p contains the task_struct for the process. - * Return 0 if permission is granted. - * @current_getsecid_subj: - * Retrieve the subjective security identifier of the current task and - * return it in @secid. - * In case of failure, @secid will be set to zero. - * @task_getsecid_obj: - * Retrieve the objective security identifier of the task_struct in @p - * and return it in @secid. - * In case of failure, @secid will be set to zero. - * - * @task_setnice: - * Check permission before setting the nice value of @p to @nice. - * @p contains the task_struct of process. - * @nice contains the new nice value. - * Return 0 if permission is granted. - * @task_setioprio: - * Check permission before setting the ioprio value of @p to @ioprio. - * @p contains the task_struct of process. - * @ioprio contains the new ioprio value. - * Return 0 if permission is granted. - * @task_getioprio: - * Check permission before getting the ioprio value of @p. - * @p contains the task_struct of process. - * Return 0 if permission is granted. - * @task_prlimit: - * Check permission before getting and/or setting the resource limits of - * another task. - * @cred points to the cred structure for the current task. - * @tcred points to the cred structure for the target task. - * @flags contains the LSM_PRLIMIT_* flag bits indicating whether the - * resource limits are being read, modified, or both. - * Return 0 if permission is granted. - * @task_setrlimit: - * Check permission before setting the resource limits of process @p - * for @resource to @new_rlim. The old resource limit values can - * be examined by dereferencing (p->signal->rlim + resource). - * @p points to the task_struct for the target task's group leader. - * @resource contains the resource whose limit is being set. - * @new_rlim contains the new limits for @resource. - * Return 0 if permission is granted. - * @task_setscheduler: - * Check permission before setting scheduling policy and/or parameters of - * process @p. - * @p contains the task_struct for process. - * Return 0 if permission is granted. - * @task_getscheduler: - * Check permission before obtaining scheduling information for process - * @p. - * @p contains the task_struct for process. - * Return 0 if permission is granted. - * @task_movememory: - * Check permission before moving memory owned by process @p. - * @p contains the task_struct for process. - * Return 0 if permission is granted. - * @task_kill: - * Check permission before sending signal @sig to @p. @info can be NULL, - * the constant 1, or a pointer to a kernel_siginfo structure. If @info is 1 or - * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming - * from the kernel and should typically be permitted. - * SIGIO signals are handled separately by the send_sigiotask hook in - * file_security_ops. - * @p contains the task_struct for process. - * @info contains the signal information. - * @sig contains the signal value. - * @cred contains the cred of the process where the signal originated, or - * NULL if the current task is the originator. - * Return 0 if permission is granted. - * @task_prctl: - * Check permission before performing a process control operation on the - * current process. - * @option contains the operation. - * @arg2 contains a argument. - * @arg3 contains a argument. - * @arg4 contains a argument. - * @arg5 contains a argument. - * Return -ENOSYS if no-one wanted to handle this op, any other value to - * cause prctl() to return immediately with that value. - * @task_to_inode: - * Set the security attributes for an inode based on an associated task's - * security attributes, e.g. for /proc/pid inodes. - * @p contains the task_struct for the task. - * @inode contains the inode structure for the inode. - * @userns_create: - * Check permission prior to creating a new user namespace. - * @cred points to prepared creds. - * Return 0 if successful, otherwise < 0 error code. - * * Security hooks for Netlink messaging. * * @netlink_send: diff --git a/security/security.c b/security/security.c index a527291c191d..766595a76ab4 100644 --- a/security/security.c +++ b/security/security.c @@ -2656,6 +2656,15 @@ int security_file_truncate(struct file *file) return call_int_hook(file_truncate, 0, file); } +/** + * security_task_alloc() - Allocate a task's LSM blob + * @task: the task + * @clone_flags: flags indicating what is being shared + * + * Handle allocation of task-related resources. + * + * Return: Returns a zero on success, negative values on failure. + */ int security_task_alloc(struct task_struct *task, unsigned long clone_flags) { int rc = lsm_task_alloc(task); @@ -2668,6 +2677,13 @@ int security_task_alloc(struct task_struct *task, unsigned long clone_flags) return rc; } +/** + * security_task_free() - Free a task's LSM blob and related resources + * @task: task + * + * Handle release of task-related resources. Note that this can be called from + * interrupt context. + */ void security_task_free(struct task_struct *task) { call_void_hook(task_free, task); @@ -2676,6 +2692,16 @@ void security_task_free(struct task_struct *task) task->security = NULL; } +/** + * security_cred_alloc_blank() - Allocate the min memory to allow cred_transfer + * @cred: credentials + * @gfp: gfp flags + * + * Only allocate sufficient memory and attach to @cred such that + * cred_transfer() will not get ENOMEM. + * + * Return: Returns 0 on success, negative values on failure. + */ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) { int rc = lsm_cred_alloc(cred, gfp); @@ -2689,6 +2715,12 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp) return rc; } +/** + * security_cred_free() - Free the cred's LSM blob and associated resources + * @cred: credentials + * + * Deallocate and clear the cred->security field in a set of credentials. + */ void security_cred_free(struct cred *cred) { /* @@ -2704,6 +2736,16 @@ void security_cred_free(struct cred *cred) cred->security = NULL; } +/** + * security_prepare_creds() - Prepare a new set of credentials + * @new: new credentials + * @old: original credentials + * @gfp: gfp flags + * + * Prepare a new set of credentials by copying the data from the old set. + * + * Return: Returns 0 on success, negative values on failure. + */ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) { int rc = lsm_cred_alloc(new, gfp); @@ -2717,11 +2759,26 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp) return rc; } +/** + * security_transfer_creds() - Transfer creds + * @new: target credentials + * @old: original credentials + * + * Transfer data from original creds to new creds. + */ void security_transfer_creds(struct cred *new, const struct cred *old) { call_void_hook(cred_transfer, new, old); } +/** + * security_cred_getsecid() - Get the secid from a set of credentials + * @c: credentials + * @secid: secid value + * + * Retrieve the security identifier of the cred structure @c. In case of + * failure, @secid will be set to zero. + */ void security_cred_getsecid(const struct cred *c, u32 *secid) { *secid = 0; @@ -2729,16 +2786,46 @@ void security_cred_getsecid(const struct cred *c, u32 *secid) } EXPORT_SYMBOL(security_cred_getsecid); +/** + * security_kernel_act_as() - Set the kernel credentials to act as secid + * @new: credentials + * @secid: secid + * + * Set the credentials for a kernel service to act as (subjective context). + * The current task must be the one that nominated @secid. + * + * Return: Returns 0 if successful. + */ int security_kernel_act_as(struct cred *new, u32 secid) { return call_int_hook(kernel_act_as, 0, new, secid); } +/** + * security_kernel_create_files_as() - Set file creation context using an inode + * @new: target credentials + * @inode: reference inode + * + * Set the file creation context in a set of credentials to be the same as the + * objective context of the specified inode. The current task must be the one + * that nominated @inode. + * + * Return: Returns 0 if successful. + */ int security_kernel_create_files_as(struct cred *new, struct inode *inode) { return call_int_hook(kernel_create_files_as, 0, new, inode); } +/** + * security_kernel_module_request() - Check is loading a module is allowed + * @kmod_name: module name + * + * Ability to trigger the kernel to automatically upcall to userspace for + * userspace to load a kernel module with the given name. + * + * Return: Returns 0 if successful. + */ int security_kernel_module_request(char *kmod_name) { int ret; @@ -2749,6 +2836,16 @@ int security_kernel_module_request(char *kmod_name) return integrity_kernel_module_request(kmod_name); } +/** + * security_kernel_read_file() - Read a file specified by userspace + * @file: file + * @id: file identifier + * @contents: trust if security_kernel_post_read_file() will be called + * + * Read a file specified by userspace. + * + * Return: Returns 0 if permission is granted. + */ int security_kernel_read_file(struct file *file, enum kernel_read_file_id id, bool contents) { @@ -2761,6 +2858,19 @@ int security_kernel_read_file(struct file *file, enum kernel_read_file_id id, } EXPORT_SYMBOL_GPL(security_kernel_read_file); +/** + * security_kernel_post_read_file() - Read a file specified by userspace + * @file: file + * @buf: file contents + * @size: size of file contents + * @id: file identifier + * + * Read a file specified by userspace. This must be paired with a prior call + * to security_kernel_read_file() call that indicated this hook would also be + * called, see security_kernel_read_file() for more information. + * + * Return: Returns 0 if permission is granted. + */ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) { @@ -2773,6 +2883,15 @@ int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); +/** + * security_kernel_load_data() - Load data provided by userspace + * @id: data identifier + * @contents: true if security_kernel_post_load_data() will be called + * + * Load data provided by userspace. + * + * Return: Returns 0 if permission is granted. + */ int security_kernel_load_data(enum kernel_load_data_id id, bool contents) { int ret; @@ -2784,6 +2903,20 @@ int security_kernel_load_data(enum kernel_load_data_id id, bool contents) } EXPORT_SYMBOL_GPL(security_kernel_load_data); +/** + * security_kernel_post_load_data() - Load userspace data from a non-file source + * @buf: data + * @size: size of data + * @id: data identifier + * @description: text description of data, specific to the id value + * + * Load data provided by a non-file source (usually userspace buffer). This + * must be paired with a prior security_kernel_load_data() call that indicated + * this hook would also be called, see security_kernel_load_data() for more + * information. + * + * Return: Returns 0 if permission is granted. + */ int security_kernel_post_load_data(char *buf, loff_t size, enum kernel_load_data_id id, char *description) @@ -2798,38 +2931,112 @@ int security_kernel_post_load_data(char *buf, loff_t size, } EXPORT_SYMBOL_GPL(security_kernel_post_load_data); +/** + * security_task_fix_setuid() - Update LSM with new user id attributes + * @new: updated credentials + * @old: credentials being replaced + * @flags: LSM_SETID_* flag values + * + * Update the module's state after setting one or more of the user identity + * attributes of the current process. The @flags parameter indicates which of + * the set*uid system calls invoked this hook. If @new is the set of + * credentials that will be installed. Modifications should be made to this + * rather than to @current->cred. + * + * Return: Returns 0 on success. + */ int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { return call_int_hook(task_fix_setuid, 0, new, old, flags); } +/** + * security_task_fix_setgid() - Update LSM with new group id attributes + * @new: updated credentials + * @old: credentials being replaced + * @flags: LSM_SETID_* flag value + * + * Update the module's state after setting one or more of the group identity + * attributes of the current process. The @flags parameter indicates which of + * the set*gid system calls invoked this hook. @new is the set of credentials + * that will be installed. Modifications should be made to this rather than to + * @current->cred. + * + * Return: Returns 0 on success. + */ int security_task_fix_setgid(struct cred *new, const struct cred *old, int flags) { return call_int_hook(task_fix_setgid, 0, new, old, flags); } +/** + * security_task_fix_setgroups() - Update LSM with new supplementary groups + * @new: updated credentials + * @old: credentials being replaced + * + * Update the module's state after setting the supplementary group identity + * attributes of the current process. @new is the set of credentials that will + * be installed. Modifications should be made to this rather than to + * @current->cred. + * + * Return: Returns 0 on success. + */ int security_task_fix_setgroups(struct cred *new, const struct cred *old) { return call_int_hook(task_fix_setgroups, 0, new, old); } +/** + * security_task_setpgid() - Check if setting the pgid is allowed + * @p: task being modified + * @pgid: new pgid + * + * Check permission before setting the process group identifier of the process + * @p to @pgid. + * + * Return: Returns 0 if permission is granted. + */ int security_task_setpgid(struct task_struct *p, pid_t pgid) { return call_int_hook(task_setpgid, 0, p, pgid); } +/** + * security_task_getpgid() - Check if getting the pgid is allowed + * @p: task + * + * Check permission before getting the process group identifier of the process + * @p. + * + * Return: Returns 0 if permission is granted. + */ int security_task_getpgid(struct task_struct *p) { return call_int_hook(task_getpgid, 0, p); } +/** + * security_task_getsid() - Check if getting the session id is allowed + * @p: task + * + * Check permission before getting the session identifier of the process @p. + * + * Return: Returns 0 if permission is granted. + */ int security_task_getsid(struct task_struct *p) { return call_int_hook(task_getsid, 0, p); } +/** + * security_current_getsecid_subj() - Get the current task's subjective secid + * @secid: secid value + * + * Retrieve the subjective security identifier of the current task and return + * it in @secid. In case of failure, @secid will be set to zero. + */ void security_current_getsecid_subj(u32 *secid) { *secid = 0; @@ -2837,6 +3044,14 @@ void security_current_getsecid_subj(u32 *secid) } EXPORT_SYMBOL(security_current_getsecid_subj); +/** + * security_task_getsecid_obj() - Get a task's objective secid + * @p: target task + * @secid: secid value + * + * Retrieve the objective security identifier of the task_struct in @p and + * return it in @secid. In case of failure, @secid will be set to zero. + */ void security_task_getsecid_obj(struct task_struct *p, u32 *secid) { *secid = 0; @@ -2844,54 +3059,157 @@ void security_task_getsecid_obj(struct task_struct *p, u32 *secid) } EXPORT_SYMBOL(security_task_getsecid_obj); +/** + * security_task_setnice() - Check if setting a task's nice value is allowed + * @p: target task + * @nice: nice value + * + * Check permission before setting the nice value of @p to @nice. + * + * Return: Returns 0 if permission is granted. + */ int security_task_setnice(struct task_struct *p, int nice) { return call_int_hook(task_setnice, 0, p, nice); } +/** + * security_task_setioprio() - Check if setting a task's ioprio is allowed + * @p: target task + * @ioprio: ioprio value + * + * Check permission before setting the ioprio value of @p to @ioprio. + * + * Return: Returns 0 if permission is granted. + */ int security_task_setioprio(struct task_struct *p, int ioprio) { return call_int_hook(task_setioprio, 0, p, ioprio); } +/** + * security_task_getioprio() - Check if getting a task's ioprio is allowed + * @p: task + * + * Check permission before getting the ioprio value of @p. + * + * Return: Returns 0 if permission is granted. + */ int security_task_getioprio(struct task_struct *p) { return call_int_hook(task_getioprio, 0, p); } +/** + * security_task_prlimit() - Check if get/setting resources limits is allowed + * @cred: current task credentials + * @tcred: target task credentials + * @flags: LSM_PRLIMIT_* flag bits indicating a get/set/both + * + * Check permission before getting and/or setting the resource limits of + * another task. + * + * Return: Returns 0 if permission is granted. + */ int security_task_prlimit(const struct cred *cred, const struct cred *tcred, unsigned int flags) { return call_int_hook(task_prlimit, 0, cred, tcred, flags); } +/** + * security_task_setrlimit() - Check if setting a new rlimit value is allowed + * @p: target task's group leader + * @resource: resource whose limit is being set + * @new_rlim: new resource limit + * + * Check permission before setting the resource limits of process @p for + * @resource to @new_rlim. The old resource limit values can be examined by + * dereferencing (p->signal->rlim + resource). + * + * Return: Returns 0 if permission is granted. + */ int security_task_setrlimit(struct task_struct *p, unsigned int resource, struct rlimit *new_rlim) { return call_int_hook(task_setrlimit, 0, p, resource, new_rlim); } +/** + * security_task_setscheduler() - Check if setting sched policy/param is allowed + * @p: target task + * + * Check permission before setting scheduling policy and/or parameters of + * process @p. + * + * Return: Returns 0 if permission is granted. + */ int security_task_setscheduler(struct task_struct *p) { return call_int_hook(task_setscheduler, 0, p); } +/** + * security_task_getscheduler() - Check if getting scheduling info is allowed + * @p: target task + * + * Check permission before obtaining scheduling information for process @p. + * + * Return: Returns 0 if permission is granted. + */ int security_task_getscheduler(struct task_struct *p) { return call_int_hook(task_getscheduler, 0, p); } +/** + * security_task_movememory() - Check if moving memory is allowed + * @p: task + * + * Check permission before moving memory owned by process @p. + * + * Return: Returns 0 if permission is granted. + */ int security_task_movememory(struct task_struct *p) { return call_int_hook(task_movememory, 0, p); } +/** + * security_task_kill() - Check if sending a signal is allowed + * @p: target process + * @info: signal information + * @sig: signal value + * @cred: credentials of the signal sender, NULL if @current + * + * Check permission before sending signal @sig to @p. @info can be NULL, the + * constant 1, or a pointer to a kernel_siginfo structure. If @info is 1 or + * SI_FROMKERNEL(info) is true, then the signal should be viewed as coming from + * the kernel and should typically be permitted. SIGIO signals are handled + * separately by the send_sigiotask hook in file_security_ops. + * + * Return: Returns 0 if permission is granted. + */ int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, int sig, const struct cred *cred) { return call_int_hook(task_kill, 0, p, info, sig, cred); } +/** + * security_task_prctl() - Check if a prctl op is allowed + * @option: operation + * @arg2: argument + * @arg3: argument + * @arg4: argument + * @arg5: argument + * + * Check permission before performing a process control operation on the + * current process. + * + * Return: Return -ENOSYS if no-one wanted to handle this op, any other value + * to cause prctl() to return immediately with that value. + */ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5) { @@ -2910,11 +3228,27 @@ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, return rc; } +/** + * security_task_to_inode() - Set the security attributes of a task's inode + * @p: task + * @inode: inode + * + * Set the security attributes for an inode based on an associated task's + * security attributes, e.g. for /proc/pid inodes. + */ void security_task_to_inode(struct task_struct *p, struct inode *inode) { call_void_hook(task_to_inode, p, inode); } +/** + * security_create_user_ns() - Check if creating a new userns is allowed + * @cred: prepared creds + * + * Check permission prior to creating a new user namespace. + * + * Return: Returns 0 if successful, otherwise < 0 error code. + */ int security_create_user_ns(const struct cred *cred) { return call_int_hook(userns_create, 0, cred); From 2bcf51bf2f03cc9fccd3316d361cdf9695fccd11 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sun, 12 Feb 2023 15:06:59 -0500 Subject: [PATCH 010/291] lsm: move the netlink hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 13 ------------- security/security.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 5578a13729bd..ba2daec1bc35 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,19 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for Netlink messaging. - * - * @netlink_send: - * Save security information for a netlink message so that permission - * checking can be performed when the message is processed. The security - * information can be saved using the eff_cap field of the - * netlink_skb_parms structure. Also may be used to provide fine - * grained control over message transmission. - * @sk associated sock of task sending the message. - * @skb contains the sk_buff structure for the netlink message. - * Return 0 if the information was successfully saved and message - * is allowed to be transmitted. - * * Security hooks for Unix domain networking. * * @unix_stream_connect: diff --git a/security/security.c b/security/security.c index 766595a76ab4..b5fe49ac564e 100644 --- a/security/security.c +++ b/security/security.c @@ -3458,6 +3458,19 @@ int security_setprocattr(const char *lsm, const char *name, void *value, return LSM_RET_DEFAULT(setprocattr); } +/** + * security_netlink_send() - Save info and check if netlink sending is allowed + * @sk: sending socket + * @skb: netlink message + * + * Save security information for a netlink message so that permission checking + * can be performed when the message is processed. The security information + * can be saved using the eff_cap field of the netlink_skb_parms structure. + * Also may be used to provide fine grained control over message transmission. + * + * Return: Returns 0 if the information was successfully saved and message is + * allowed to be transmitted. + */ int security_netlink_send(struct sock *sk, struct sk_buff *skb) { return call_int_hook(netlink_send, 0, sk, skb); From 2c2442fd46cd162c0b6a07b4560095f03bd3275f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sun, 12 Feb 2023 15:10:23 -0500 Subject: [PATCH 011/291] lsm: move the AF_UNIX hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 26 ------------------------ security/security.c | 42 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 27 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index ba2daec1bc35..1fc1e2aa7d01 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,32 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for Unix domain networking. - * - * @unix_stream_connect: - * Check permissions before establishing a Unix domain stream connection - * between @sock and @other. - * @sock contains the sock structure. - * @other contains the peer sock structure. - * @newsk contains the new sock structure. - * Return 0 if permission is granted. - * @unix_may_send: - * Check permissions before connecting or sending datagrams from @sock to - * @other. - * @sock contains the socket structure. - * @other contains the peer socket structure. - * Return 0 if permission is granted. - * - * The @unix_stream_connect and @unix_may_send hooks were necessary because - * Linux provides an alternative to the conventional file name space for Unix - * domain sockets. Whereas binding and connecting to sockets in the file name - * space is mediated by the typical file permissions (and caught by the mknod - * and permission hooks in inode_security_ops), binding and connecting to - * sockets in the abstract name space is completely unmediated. Sufficient - * control of Unix domain sockets in the abstract name space isn't possible - * using only the socket layer hooks, since we need to know the actual target - * socket, which is not looked up until we are inside the af_unix code. - * * Security hooks for socket operations. * * @socket_create: diff --git a/security/security.c b/security/security.c index b5fe49ac564e..9112531e6c2e 100644 --- a/security/security.c +++ b/security/security.c @@ -3555,13 +3555,53 @@ int security_watch_key(struct key *key) #endif #ifdef CONFIG_SECURITY_NETWORK - +/** + * security_unix_stream_connect() - Check if a AF_UNIX stream is allowed + * @sock: originating sock + * @other: peer sock + * @newsk: new sock + * + * Check permissions before establishing a Unix domain stream connection + * between @sock and @other. + * + * The @unix_stream_connect and @unix_may_send hooks were necessary because + * Linux provides an alternative to the conventional file name space for Unix + * domain sockets. Whereas binding and connecting to sockets in the file name + * space is mediated by the typical file permissions (and caught by the mknod + * and permission hooks in inode_security_ops), binding and connecting to + * sockets in the abstract name space is completely unmediated. Sufficient + * control of Unix domain sockets in the abstract name space isn't possible + * using only the socket layer hooks, since we need to know the actual target + * socket, which is not looked up until we are inside the af_unix code. + * + * Return: Returns 0 if permission is granted. + */ int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) { return call_int_hook(unix_stream_connect, 0, sock, other, newsk); } EXPORT_SYMBOL(security_unix_stream_connect); +/** + * security_unix_may_send() - Check if AF_UNIX socket can send datagrams + * @sock: originating sock + * @other: peer sock + * + * Check permissions before connecting or sending datagrams from @sock to + * @other. + * + * The @unix_stream_connect and @unix_may_send hooks were necessary because + * Linux provides an alternative to the conventional file name space for Unix + * domain sockets. Whereas binding and connecting to sockets in the file name + * space is mediated by the typical file permissions (and caught by the mknod + * and permission hooks in inode_security_ops), binding and connecting to + * sockets in the abstract name space is completely unmediated. Sufficient + * control of Unix domain sockets in the abstract name space isn't possible + * using only the socket layer hooks, since we need to know the actual target + * socket, which is not looked up until we are inside the af_unix code. + * + * Return: Returns 0 if permission is granted. + */ int security_unix_may_send(struct socket *sock, struct socket *other) { return call_int_hook(unix_may_send, 0, sock, other); From 6b6bbe8c02a1bc7ef7f0aa490a3601a16cd145fe Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Sun, 12 Feb 2023 15:15:29 -0500 Subject: [PATCH 012/291] lsm: move the socket hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 191 ---------------------- security/security.c | 322 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 322 insertions(+), 191 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 1fc1e2aa7d01..531d141083ed 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,197 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for socket operations. - * - * @socket_create: - * Check permissions prior to creating a new socket. - * @family contains the requested protocol family. - * @type contains the requested communications type. - * @protocol contains the requested protocol. - * @kern set to 1 if a kernel socket. - * Return 0 if permission is granted. - * @socket_post_create: - * This hook allows a module to update or allocate a per-socket security - * structure. Note that the security field was not added directly to the - * socket structure, but rather, the socket security information is stored - * in the associated inode. Typically, the inode alloc_security hook will - * allocate and attach security information to - * SOCK_INODE(sock)->i_security. This hook may be used to update the - * SOCK_INODE(sock)->i_security field with additional information that - * wasn't available when the inode was allocated. - * @sock contains the newly created socket structure. - * @family contains the requested protocol family. - * @type contains the requested communications type. - * @protocol contains the requested protocol. - * @kern set to 1 if a kernel socket. - * Return 0 if permission is granted. - * @socket_socketpair: - * Check permissions before creating a fresh pair of sockets. - * @socka contains the first socket structure. - * @sockb contains the second socket structure. - * Return 0 if permission is granted and the connection was established. - * @socket_bind: - * Check permission before socket protocol layer bind operation is - * performed and the socket @sock is bound to the address specified in the - * @address parameter. - * @sock contains the socket structure. - * @address contains the address to bind to. - * @addrlen contains the length of address. - * Return 0 if permission is granted. - * @socket_connect: - * Check permission before socket protocol layer connect operation - * attempts to connect socket @sock to a remote address, @address. - * @sock contains the socket structure. - * @address contains the address of remote endpoint. - * @addrlen contains the length of address. - * Return 0 if permission is granted. - * @socket_listen: - * Check permission before socket protocol layer listen operation. - * @sock contains the socket structure. - * @backlog contains the maximum length for the pending connection queue. - * Return 0 if permission is granted. - * @socket_accept: - * Check permission before accepting a new connection. Note that the new - * socket, @newsock, has been created and some information copied to it, - * but the accept operation has not actually been performed. - * @sock contains the listening socket structure. - * @newsock contains the newly created server socket for connection. - * Return 0 if permission is granted. - * @socket_sendmsg: - * Check permission before transmitting a message to another socket. - * @sock contains the socket structure. - * @msg contains the message to be transmitted. - * @size contains the size of message. - * Return 0 if permission is granted. - * @socket_recvmsg: - * Check permission before receiving a message from a socket. - * @sock contains the socket structure. - * @msg contains the message structure. - * @size contains the size of message structure. - * @flags contains the operational flags. - * Return 0 if permission is granted. - * @socket_getsockname: - * Check permission before the local address (name) of the socket object - * @sock is retrieved. - * @sock contains the socket structure. - * Return 0 if permission is granted. - * @socket_getpeername: - * Check permission before the remote address (name) of a socket object - * @sock is retrieved. - * @sock contains the socket structure. - * Return 0 if permission is granted. - * @socket_getsockopt: - * Check permissions before retrieving the options associated with socket - * @sock. - * @sock contains the socket structure. - * @level contains the protocol level to retrieve option from. - * @optname contains the name of option to retrieve. - * Return 0 if permission is granted. - * @socket_setsockopt: - * Check permissions before setting the options associated with socket - * @sock. - * @sock contains the socket structure. - * @level contains the protocol level to set options for. - * @optname contains the name of the option to set. - * Return 0 if permission is granted. - * @socket_shutdown: - * Checks permission before all or part of a connection on the socket - * @sock is shut down. - * @sock contains the socket structure. - * @how contains the flag indicating how future sends and receives - * are handled. - * Return 0 if permission is granted. - * @socket_sock_rcv_skb: - * Check permissions on incoming network packets. This hook is distinct - * from Netfilter's IP input hooks since it is the first time that the - * incoming sk_buff @skb has been associated with a particular socket, @sk. - * Must not sleep inside this hook because some callers hold spinlocks. - * @sk contains the sock (not socket) associated with the incoming sk_buff. - * @skb contains the incoming network data. - * Return 0 if permission is granted. - * @socket_getpeersec_stream: - * This hook allows the security module to provide peer socket security - * state for unix or connected tcp sockets to userspace via getsockopt - * SO_GETPEERSEC. For tcp sockets this can be meaningful if the - * socket is associated with an ipsec SA. - * @sock is the local socket. - * @optval memory where the security state is to be copied. - * @optlen memory where the module should copy the actual length - * of the security state. - * @len as input is the maximum length to copy to userspace provided - * by the caller. - * Return 0 if all is well, otherwise, typical getsockopt return - * values. - * @socket_getpeersec_dgram: - * This hook allows the security module to provide peer socket security - * state for udp sockets on a per-packet basis to userspace via - * getsockopt SO_GETPEERSEC. The application must first have indicated - * the IP_PASSSEC option via getsockopt. It can then retrieve the - * security state returned by this hook for a packet via the SCM_SECURITY - * ancillary message type. - * @sock contains the peer socket. May be NULL. - * @skb is the sk_buff for the packet being queried. May be NULL. - * @secid pointer to store the secid of the packet. - * Return 0 on success, error on failure. - * @sk_alloc_security: - * Allocate and attach a security structure to the sk->sk_security field, - * which is used to copy security attributes between local stream sockets. - * Return 0 on success, error on failure. - * @sk_free_security: - * Deallocate security structure. - * @sk_clone_security: - * Clone/copy security structure. - * @sk_getsecid: - * Retrieve the LSM-specific secid for the sock to enable caching - * of network authorizations. - * @sock_graft: - * Sets the socket's isec sid to the sock's sid. - * @inet_conn_request: - * Sets the openreq's sid to socket's sid with MLS portion taken - * from peer sid. - * Return 0 if permission is granted. - * @inet_csk_clone: - * Sets the new child socket's sid to the openreq sid. - * @inet_conn_established: - * Sets the connection's peersid to the secmark on skb. - * @secmark_relabel_packet: - * Check if the process should be allowed to relabel packets to - * the given secid. - * Return 0 if permission is granted. - * @secmark_refcount_inc: - * Tells the LSM to increment the number of secmark labeling rules loaded. - * @secmark_refcount_dec: - * Tells the LSM to decrement the number of secmark labeling rules loaded. - * @req_classify_flow: - * Sets the flow's sid to the openreq sid. - * @tun_dev_alloc_security: - * This hook allows a module to allocate a security structure for a TUN - * device. - * @security pointer to a security structure pointer. - * Returns a zero on success, negative values on failure. - * @tun_dev_free_security: - * This hook allows a module to free the security structure for a TUN - * device. - * @security pointer to the TUN device's security structure. - * @tun_dev_create: - * Check permissions prior to creating a new TUN device. - * Return 0 if permission is granted. - * @tun_dev_attach_queue: - * Check permissions prior to attaching to a TUN device queue. - * @security pointer to the TUN device's security structure. - * Return 0 if permission is granted. - * @tun_dev_attach: - * This hook can be used by the module to update any security state - * associated with the TUN device's sock structure. - * @sk contains the existing sock structure. - * @security pointer to the TUN device's security structure. - * Return 0 if permission is granted. - * @tun_dev_open: - * This hook can be used by the module to update any security state - * associated with the TUN device's security structure. - * @security pointer to the TUN devices's security structure. - * Return 0 if permission is granted. - * * Security hooks for SCTP * * @sctp_assoc_request: diff --git a/security/security.c b/security/security.c index 9112531e6c2e..1b2eca6437c4 100644 --- a/security/security.c +++ b/security/security.c @@ -3608,11 +3608,40 @@ int security_unix_may_send(struct socket *sock, struct socket *other) } EXPORT_SYMBOL(security_unix_may_send); +/** + * security_socket_create() - Check if creating a new socket is allowed + * @family: protocol family + * @type: communications type + * @protocol: requested protocol + * @kern: set to 1 if a kernel socket is requested + * + * Check permissions prior to creating a new socket. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_create(int family, int type, int protocol, int kern) { return call_int_hook(socket_create, 0, family, type, protocol, kern); } +/** + * security_socket_create() - Initialize a newly created socket + * @sock: socket + * @family: protocol family + * @type: communications type + * @protocol: requested protocol + * @kern: set to 1 if a kernel socket is requested + * + * This hook allows a module to update or allocate a per-socket security + * structure. Note that the security field was not added directly to the socket + * structure, but rather, the socket security information is stored in the + * associated inode. Typically, the inode alloc_security hook will allocate + * and attach security information to SOCK_INODE(sock)->i_security. This hook + * may be used to update the SOCK_INODE(sock)->i_security field with additional + * information that wasn't available when the inode was allocated. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { @@ -3620,74 +3649,223 @@ int security_socket_post_create(struct socket *sock, int family, protocol, kern); } +/** + * security_socket_socketpair() - Check if creating a socketpair is allowed + * @socka: first socket + * @sockb: second socket + * + * Check permissions before creating a fresh pair of sockets. + * + * Return: Returns 0 if permission is granted and the connection was + * established. + */ int security_socket_socketpair(struct socket *socka, struct socket *sockb) { return call_int_hook(socket_socketpair, 0, socka, sockb); } EXPORT_SYMBOL(security_socket_socketpair); +/** + * security_socket_bind() - Check if a socket bind operation is allowed + * @sock: socket + * @address: requested bind address + * @addrlen: length of address + * + * Check permission before socket protocol layer bind operation is performed + * and the socket @sock is bound to the address specified in the @address + * parameter. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) { return call_int_hook(socket_bind, 0, sock, address, addrlen); } +/** + * security_socket_connect() - Check if a socket connect operation is allowed + * @sock: socket + * @address: address of remote connection point + * @addrlen: length of address + * + * Check permission before socket protocol layer connect operation attempts to + * connect socket @sock to a remote address, @address. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) { return call_int_hook(socket_connect, 0, sock, address, addrlen); } +/** + * security_socket_listen() - Check if a socket is allowed to listen + * @sock: socket + * @backlog: connection queue size + * + * Check permission before socket protocol layer listen operation. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_listen(struct socket *sock, int backlog) { return call_int_hook(socket_listen, 0, sock, backlog); } +/** + * security_socket_accept() - Check if a socket is allowed to accept connections + * @sock: listening socket + * @newsock: newly creation connection socket + * + * Check permission before accepting a new connection. Note that the new + * socket, @newsock, has been created and some information copied to it, but + * the accept operation has not actually been performed. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_accept(struct socket *sock, struct socket *newsock) { return call_int_hook(socket_accept, 0, sock, newsock); } +/** + * security_socket_sendmsg() - Check is sending a message is allowed + * @sock: sending socket + * @msg: message to send + * @size: size of message + * + * Check permission before transmitting a message to another socket. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_sendmsg(struct socket *sock, struct msghdr *msg, int size) { return call_int_hook(socket_sendmsg, 0, sock, msg, size); } +/** + * security_socket_recvmsg() - Check if receiving a message is allowed + * @sock: receiving socket + * @msg: message to receive + * @size: size of message + * @flags: operational flags + * + * Check permission before receiving a message from a socket. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_recvmsg(struct socket *sock, struct msghdr *msg, int size, int flags) { return call_int_hook(socket_recvmsg, 0, sock, msg, size, flags); } +/** + * security_socket_getsockname() - Check if reading the socket addr is allowed + * @sock: socket + * + * Check permission before reading the local address (name) of the socket + * object. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_getsockname(struct socket *sock) { return call_int_hook(socket_getsockname, 0, sock); } +/** + * security_socket_getpeername() - Check if reading the peer's addr is allowed + * @sock: socket + * + * Check permission before the remote address (name) of a socket object. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_getpeername(struct socket *sock) { return call_int_hook(socket_getpeername, 0, sock); } +/** + * security_socket_getsockopt() - Check if reading a socket option is allowed + * @sock: socket + * @level: option's protocol level + * @optname: option name + * + * Check permissions before retrieving the options associated with socket + * @sock. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_getsockopt(struct socket *sock, int level, int optname) { return call_int_hook(socket_getsockopt, 0, sock, level, optname); } +/** + * security_socket_setsockopt() - Check if setting a socket option is allowed + * @sock: socket + * @level: option's protocol level + * @optname: option name + * + * Check permissions before setting the options associated with socket @sock. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_setsockopt(struct socket *sock, int level, int optname) { return call_int_hook(socket_setsockopt, 0, sock, level, optname); } +/** + * security_socket_shutdown() - Checks if shutting down the socket is allowed + * @sock: socket + * @how: flag indicating how sends and receives are handled + * + * Checks permission before all or part of a connection on the socket @sock is + * shut down. + * + * Return: Returns 0 if permission is granted. + */ int security_socket_shutdown(struct socket *sock, int how) { return call_int_hook(socket_shutdown, 0, sock, how); } +/** + * security_sock_rcv_skb() - Check if an incoming network packet is allowed + * @sk: destination sock + * @skb: incoming packet + * + * Check permissions on incoming network packets. This hook is distinct from + * Netfilter's IP input hooks since it is the first time that the incoming + * sk_buff @skb has been associated with a particular socket, @sk. Must not + * sleep inside this hook because some callers hold spinlocks. + * + * Return: Returns 0 if permission is granted. + */ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) { return call_int_hook(socket_sock_rcv_skb, 0, sk, skb); } EXPORT_SYMBOL(security_sock_rcv_skb); +/** + * security_socket_getpeersec_stream() - Get the remote peer label + * @sock: socket + * @optval: destination buffer + * @optlen: size of peer label copied into the buffer + * @len: maximum size of the destination buffer + * + * This hook allows the security module to provide peer socket security state + * for unix or connected tcp sockets to userspace via getsockopt SO_GETPEERSEC. + * For tcp sockets this can be meaningful if the socket is associated with an + * ipsec SA. + * + * Return: Returns 0 if all is well, otherwise, typical getsockopt return + * values. + */ int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, sockptr_t optlen, unsigned int len) { @@ -3695,6 +3873,20 @@ int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, optval, optlen, len); } +/** + * security_socket_getpeersec_dgram() - Get the remote peer label + * @sock: socket + * @skb: datagram packet + * @secid: remote peer label secid + * + * This hook allows the security module to provide peer socket security state + * for udp sockets on a per-packet basis to userspace via getsockopt + * SO_GETPEERSEC. The application must first have indicated the IP_PASSSEC + * option via getsockopt. It can then retrieve the security state returned by + * this hook for a packet via the SCM_SECURITY ancillary message type. + * + * Return: Returns 0 on success, error on failure. + */ int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) { return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock, @@ -3702,16 +3894,40 @@ int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u } EXPORT_SYMBOL(security_socket_getpeersec_dgram); +/** + * security_sk_alloc() - Allocate and initialize a sock's LSM blob + * @sk: sock + * @family: protocol family + * @priotity: gfp flags + * + * Allocate and attach a security structure to the sk->sk_security field, which + * is used to copy security attributes between local stream sockets. + * + * Return: Returns 0 on success, error on failure. + */ int security_sk_alloc(struct sock *sk, int family, gfp_t priority) { return call_int_hook(sk_alloc_security, 0, sk, family, priority); } +/** + * security_sk_free() - Free the sock's LSM blob + * @sk: sock + * + * Deallocate security structure. + */ void security_sk_free(struct sock *sk) { call_void_hook(sk_free_security, sk); } +/** + * security_sk_clone() - Clone a sock's LSM state + * @sk: original sock + * @newsk: target sock + * + * Clone/copy security structure. + */ void security_sk_clone(const struct sock *sk, struct sock *newsk) { call_void_hook(sk_clone_security, sk, newsk); @@ -3724,6 +3940,13 @@ void security_sk_classify_flow(struct sock *sk, struct flowi_common *flic) } EXPORT_SYMBOL(security_sk_classify_flow); +/** + * security_req_classify_flow() - Set a flow's secid based on request_sock + * @req: request_sock + * @flic: target flow + * + * Sets @flic's secid to @req's secid. + */ void security_req_classify_flow(const struct request_sock *req, struct flowi_common *flic) { @@ -3731,12 +3954,30 @@ void security_req_classify_flow(const struct request_sock *req, } EXPORT_SYMBOL(security_req_classify_flow); +/** + * security_sock_graft() - Reconcile LSM state when grafting a sock on a socket + * @sk: sock being grafted + * @sock: target socket + * + * Sets @sock's inode secid to @sk's secid and update @sk with any necessary + * LSM state from @sock. + */ void security_sock_graft(struct sock *sk, struct socket *parent) { call_void_hook(sock_graft, sk, parent); } EXPORT_SYMBOL(security_sock_graft); +/** + * security_inet_conn_request() - Set request_sock state using incoming connect + * @sk: parent listening sock + * @skb: incoming connection + * @req: new request_sock + * + * Initialize the @req LSM state based on @sk and the incoming connect in @skb. + * + * Return: Returns 0 if permission is granted. + */ int security_inet_conn_request(const struct sock *sk, struct sk_buff *skb, struct request_sock *req) { @@ -3744,12 +3985,26 @@ int security_inet_conn_request(const struct sock *sk, } EXPORT_SYMBOL(security_inet_conn_request); +/** + * security_inet_csk_clone() - Set new sock LSM state based on request_sock + * @newsk: new sock + * @req: connection request_sock + * + * Set that LSM state of @sock using the LSM state from @req. + */ void security_inet_csk_clone(struct sock *newsk, const struct request_sock *req) { call_void_hook(inet_csk_clone, newsk, req); } +/** + * security_inet_conn_established() - Update sock's LSM state with connection + * @sk: sock + * @skb: connection packet + * + * Update @sock's LSM state to represent a new connection from @skb. + */ void security_inet_conn_established(struct sock *sk, struct sk_buff *skb) { @@ -3757,54 +4012,121 @@ void security_inet_conn_established(struct sock *sk, } EXPORT_SYMBOL(security_inet_conn_established); +/** + * security_secmark_relabel_packet() - Check if setting a secmark is allowed + * @secid: new secmark value + * + * Check if the process should be allowed to relabel packets to @secid. + * + * Return: Returns 0 if permission is granted. + */ int security_secmark_relabel_packet(u32 secid) { return call_int_hook(secmark_relabel_packet, 0, secid); } EXPORT_SYMBOL(security_secmark_relabel_packet); +/** + * security_secmark_refcount_inc() - Increment the secmark labeling rule count + * + * Tells the LSM to increment the number of secmark labeling rules loaded. + */ void security_secmark_refcount_inc(void) { call_void_hook(secmark_refcount_inc); } EXPORT_SYMBOL(security_secmark_refcount_inc); +/** + * security_secmark_refcount_dec() - Decrement the secmark labeling rule count + * + * Tells the LSM to decrement the number of secmark labeling rules loaded. + */ void security_secmark_refcount_dec(void) { call_void_hook(secmark_refcount_dec); } EXPORT_SYMBOL(security_secmark_refcount_dec); +/** + * security_tun_dev_alloc_security() - Allocate a LSM blob for a TUN device + * @security: pointer to the LSM blob + * + * This hook allows a module to allocate a security structure for a TUN device, + * returning the pointer in @security. + * + * Return: Returns a zero on success, negative values on failure. + */ int security_tun_dev_alloc_security(void **security) { return call_int_hook(tun_dev_alloc_security, 0, security); } EXPORT_SYMBOL(security_tun_dev_alloc_security); +/** + * security_tun_dev_free_security() - Free a TUN device LSM blob + * @security: LSM blob + * + * This hook allows a module to free the security structure for a TUN device. + */ void security_tun_dev_free_security(void *security) { call_void_hook(tun_dev_free_security, security); } EXPORT_SYMBOL(security_tun_dev_free_security); +/** + * security_tun_dev_create() - Check if creating a TUN device is allowed + * + * Check permissions prior to creating a new TUN device. + * + * Return: Returns 0 if permission is granted. + */ int security_tun_dev_create(void) { return call_int_hook(tun_dev_create, 0); } EXPORT_SYMBOL(security_tun_dev_create); +/** + * security_tun_dev_attach_queue() - Check if attaching a TUN queue is allowed + * @security: TUN device LSM blob + * + * Check permissions prior to attaching to a TUN device queue. + * + * Return: Returns 0 if permission is granted. + */ int security_tun_dev_attach_queue(void *security) { return call_int_hook(tun_dev_attach_queue, 0, security); } EXPORT_SYMBOL(security_tun_dev_attach_queue); +/** + * security_tun_dev_attach() - Update TUN device LSM state on attach + * @sk: associated sock + * @security: TUN device LSM blob + * + * This hook can be used by the module to update any security state associated + * with the TUN device's sock structure. + * + * Return: Returns 0 if permission is granted. + */ int security_tun_dev_attach(struct sock *sk, void *security) { return call_int_hook(tun_dev_attach, 0, sk, security); } EXPORT_SYMBOL(security_tun_dev_attach); +/** + * security_tun_dev_open() - Update TUN device LSM state on open + * @security: TUN device LSM blob + * + * This hook can be used by the module to update any security state associated + * with the TUN device's security structure. + * + * Return: Returns 0 if permission is granted. + */ int security_tun_dev_open(void *security) { return call_int_hook(tun_dev_open, 0, security); From 4a49f592e931962ab3feb9fbb43bea719517670d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 15 Feb 2023 17:47:10 -0500 Subject: [PATCH 013/291] lsm: move the SCTP hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 33 ------------------------------ security/security.c | 43 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 531d141083ed..bb460e0b1ff2 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,39 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for SCTP - * - * @sctp_assoc_request: - * Passes the @asoc and @chunk->skb of the association INIT packet to - * the security module. - * @asoc pointer to sctp association structure. - * @skb pointer to skbuff of association packet. - * Return 0 on success, error on failure. - * @sctp_bind_connect: - * Validiate permissions required for each address associated with sock - * @sk. Depending on @optname, the addresses will be treated as either - * for a connect or bind service. The @addrlen is calculated on each - * ipv4 and ipv6 address using sizeof(struct sockaddr_in) or - * sizeof(struct sockaddr_in6). - * @sk pointer to sock structure. - * @optname name of the option to validate. - * @address list containing one or more ipv4/ipv6 addresses. - * @addrlen total length of address(s). - * Return 0 on success, error on failure. - * @sctp_sk_clone: - * Called whenever a new socket is created by accept(2) (i.e. a TCP - * style socket) or when a socket is 'peeled off' e.g userspace - * calls sctp_peeloff(3). - * @asoc pointer to current sctp association structure. - * @sk pointer to current sock structure. - * @newsk pointer to new sock structure. - * @sctp_assoc_established: - * Passes the @asoc and @chunk->skb of the association COOKIE_ACK packet - * to the security module. - * @asoc pointer to sctp association structure. - * @skb pointer to skbuff of association packet. - * Return 0 if permission is granted. - * * Security hooks for Infiniband * * @ib_pkey_access: diff --git a/security/security.c b/security/security.c index 1b2eca6437c4..4f57c49bf561 100644 --- a/security/security.c +++ b/security/security.c @@ -4133,12 +4133,35 @@ int security_tun_dev_open(void *security) } EXPORT_SYMBOL(security_tun_dev_open); +/** + * security_sctp_assoc_request() - Update the LSM on a SCTP association req + * @asoc: SCTP association + * @skb: packet requesting the association + * + * Passes the @asoc and @chunk->skb of the association INIT packet to the LSM. + * + * Return: Returns 0 on success, error on failure. + */ int security_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb) { return call_int_hook(sctp_assoc_request, 0, asoc, skb); } EXPORT_SYMBOL(security_sctp_assoc_request); +/** + * security_sctp_bind_connect() - Validate a list of addrs for a SCTP option + * @sk: socket + * @optname: SCTP option to validate + * @address: list of IP addresses to validate + * @addrlen: length of the address list + * + * Validiate permissions required for each address associated with sock @sk. + * Depending on @optname, the addresses will be treated as either a connect or + * bind service. The @addrlen is calculated on each IPv4 and IPv6 address using + * sizeof(struct sockaddr_in) or sizeof(struct sockaddr_in6). + * + * Return: Returns 0 on success, error on failure. + */ int security_sctp_bind_connect(struct sock *sk, int optname, struct sockaddr *address, int addrlen) { @@ -4147,6 +4170,16 @@ int security_sctp_bind_connect(struct sock *sk, int optname, } EXPORT_SYMBOL(security_sctp_bind_connect); +/** + * security_sctp_sk_clone() - Clone a SCTP sock's LSM state + * @asoc: SCTP association + * @sk: original sock + * @newsk: target sock + * + * Called whenever a new socket is created by accept(2) (i.e. a TCP style + * socket) or when a socket is 'peeled off' e.g userspace calls + * sctp_peeloff(3). + */ void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk, struct sock *newsk) { @@ -4154,6 +4187,16 @@ void security_sctp_sk_clone(struct sctp_association *asoc, struct sock *sk, } EXPORT_SYMBOL(security_sctp_sk_clone); +/** + * security_sctp_assoc_established() - Update LSM state when assoc established + * @asoc: SCTP association + * @skb: packet establishing the association + * + * Passes the @asoc and @chunk->skb of the association COOKIE_ACK packet to the + * security module. + * + * Return: Returns 0 if permission is granted. + */ int security_sctp_assoc_established(struct sctp_association *asoc, struct sk_buff *skb) { From ac318aed54987e6bd52dba90dd2ea3dca725b5c0 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 15 Feb 2023 18:07:41 -0500 Subject: [PATCH 014/291] lsm: move the Infiniband hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 22 ---------------------- security/security.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index bb460e0b1ff2..9fc6417af980 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,28 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for Infiniband - * - * @ib_pkey_access: - * Check permission to access a pkey when modifing a QP. - * @subnet_prefix the subnet prefix of the port being used. - * @pkey the pkey to be accessed. - * @sec pointer to a security structure. - * Return 0 if permission is granted. - * @ib_endport_manage_subnet: - * Check permissions to send and receive SMPs on a end port. - * @dev_name the IB device name (i.e. mlx4_0). - * @port_num the port number. - * @sec pointer to a security structure. - * Return 0 if permission is granted. - * @ib_alloc_security: - * Allocate a security structure for Infiniband objects. - * @sec pointer to a security structure pointer. - * Returns 0 on success, non-zero on failure. - * @ib_free_security: - * Deallocate an Infiniband security structure. - * @sec contains the security structure to be freed. - * * Security hooks for XFRM operations. * * @xfrm_policy_alloc_security: diff --git a/security/security.c b/security/security.c index 4f57c49bf561..6e786e277a7f 100644 --- a/security/security.c +++ b/security/security.c @@ -4208,24 +4208,58 @@ EXPORT_SYMBOL(security_sctp_assoc_established); #ifdef CONFIG_SECURITY_INFINIBAND +/** + * security_ib_pkey_access() - Check if access to an IB pkey is allowed + * @sec: LSM blob + * @subnet_prefix: subnet prefix of the port + * @pkey: IB pkey + * + * Check permission to access a pkey when modifing a QP. + * + * Return: Returns 0 if permission is granted. + */ int security_ib_pkey_access(void *sec, u64 subnet_prefix, u16 pkey) { return call_int_hook(ib_pkey_access, 0, sec, subnet_prefix, pkey); } EXPORT_SYMBOL(security_ib_pkey_access); +/** + * security_ib_endport_manage_subnet() - Check if SMPs traffic is allowed + * @sec: LSM blob + * @dev_name: IB device name + * @port_num: port number + * + * Check permissions to send and receive SMPs on a end port. + * + * Return: Returns 0 if permission is granted. + */ int security_ib_endport_manage_subnet(void *sec, const char *dev_name, u8 port_num) { return call_int_hook(ib_endport_manage_subnet, 0, sec, dev_name, port_num); } EXPORT_SYMBOL(security_ib_endport_manage_subnet); +/** + * security_ib_alloc_security() - Allocate an Infiniband LSM blob + * @sec: LSM blob + * + * Allocate a security structure for Infiniband objects. + * + * Return: Returns 0 on success, non-zero on failure. + */ int security_ib_alloc_security(void **sec) { return call_int_hook(ib_alloc_security, 0, sec); } EXPORT_SYMBOL(security_ib_alloc_security); +/** + * security_ib_free_security() - Free an Infiniband LSM blob + * @sec: LSM blob + * + * Deallocate an Infiniband security structure. + */ void security_ib_free_security(void *sec) { call_void_hook(ib_free_security, sec); From 742b99456e86aa3e9176fb1c7db200101876c614 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 15 Feb 2023 18:14:01 -0500 Subject: [PATCH 015/291] lsm: move the xfrm hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 73 --------------------------- security/security.c | 103 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 73 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9fc6417af980..9c5254e4e9d1 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,79 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks for XFRM operations. - * - * @xfrm_policy_alloc_security: - * @ctxp is a pointer to the xfrm_sec_ctx being added to Security Policy - * Database used by the XFRM system. - * @sec_ctx contains the security context information being provided by - * the user-level policy update program (e.g., setkey). - * @gfp is to specify the context for the allocation. - * Allocate a security structure to the xp->security field; the security - * field is initialized to NULL when the xfrm_policy is allocated. - * Return 0 if operation was successful (memory to allocate, legal - * context). - * @xfrm_policy_clone_security: - * @old_ctx contains an existing xfrm_sec_ctx. - * @new_ctxp contains a new xfrm_sec_ctx being cloned from old. - * Allocate a security structure in new_ctxp that contains the - * information from the old_ctx structure. - * Return 0 if operation was successful (memory to allocate). - * @xfrm_policy_free_security: - * @ctx contains the xfrm_sec_ctx. - * Deallocate xp->security. - * @xfrm_policy_delete_security: - * @ctx contains the xfrm_sec_ctx. - * Authorize deletion of xp->security. - * Return 0 if permission is granted. - * @xfrm_state_alloc: - * @x contains the xfrm_state being added to the Security Association - * Database by the XFRM system. - * @sec_ctx contains the security context information being provided by - * the user-level SA generation program (e.g., setkey or racoon). - * Allocate a security structure to the x->security field; the security - * field is initialized to NULL when the xfrm_state is allocated. Set the - * context to correspond to sec_ctx. Return 0 if operation was successful - * (memory to allocate, legal context). - * @xfrm_state_alloc_acquire: - * @x contains the xfrm_state being added to the Security Association - * Database by the XFRM system. - * @polsec contains the policy's security context. - * @secid contains the secid from which to take the mls portion of the - * context. - * Allocate a security structure to the x->security field; the security - * field is initialized to NULL when the xfrm_state is allocated. Set the - * context to correspond to secid. Return 0 if operation was successful - * (memory to allocate, legal context). - * @xfrm_state_free_security: - * @x contains the xfrm_state. - * Deallocate x->security. - * @xfrm_state_delete_security: - * @x contains the xfrm_state. - * Authorize deletion of x->security. - * Return 0 if permission is granted. - * @xfrm_policy_lookup: - * @ctx contains the xfrm_sec_ctx for which the access control is being - * checked. - * @fl_secid contains the flow security label that is used to authorize - * access to the policy xp. - * @dir contains the direction of the flow (input or output). - * Check permission when a flow selects a xfrm_policy for processing - * XFRMs on a packet. The hook is called when selecting either a - * per-socket policy or a generic xfrm policy. - * Return 0 if permission is granted, -ESRCH otherwise, or -errno - * on other errors. - * @xfrm_state_pol_flow_match: - * @x contains the state to match. - * @xp contains the policy to check for a match. - * @flic contains the flowi_common struct to check for a match. - * Return 1 if there is a match. - * @xfrm_decode_session: - * @skb points to skb to decode. - * @secid points to the flow key secid to set. - * @ckall says if all xfrms used should be checked for same secid. - * Return 0 if ckall is zero or all xfrms used have the same secid. - * * Security hooks affecting all Key Management operations * * @key_alloc: diff --git a/security/security.c b/security/security.c index 6e786e277a7f..d3880096922e 100644 --- a/security/security.c +++ b/security/security.c @@ -4269,6 +4269,17 @@ EXPORT_SYMBOL(security_ib_free_security); #ifdef CONFIG_SECURITY_NETWORK_XFRM +/** + * security_xfrm_policy_alloc() - Allocate a xfrm policy LSM blob + * @ctxp: xfrm security context being added to the SPD + * @sec_ctx: security label provided by userspace + * @gfp: gfp flags + * + * Allocate a security structure to the xp->security field; the security field + * is initialized to NULL when the xfrm_policy is allocated. + * + * Return: Return 0 if operation was successful. + */ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, struct xfrm_user_sec_ctx *sec_ctx, gfp_t gfp) @@ -4277,23 +4288,58 @@ int security_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, } EXPORT_SYMBOL(security_xfrm_policy_alloc); +/** + * security_xfrm_policy_clone() - Clone xfrm policy LSM state + * @old_ctx: xfrm security context + * @new_ctxp: target xfrm security context + * + * Allocate a security structure in new_ctxp that contains the information from + * the old_ctx structure. + * + * Return: Return 0 if operation was successful. + */ int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, struct xfrm_sec_ctx **new_ctxp) { return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp); } +/** + * security_xfrm_policy_free() - Free a xfrm security context + * @ctx: xfrm security context + * + * Free LSM resources associated with @ctx. + */ void security_xfrm_policy_free(struct xfrm_sec_ctx *ctx) { call_void_hook(xfrm_policy_free_security, ctx); } EXPORT_SYMBOL(security_xfrm_policy_free); +/** + * security_xfrm_policy_delete() - Check if deleting a xfrm policy is allowed + * @ctx: xfrm security context + * + * Authorize deletion of a SPD entry. + * + * Return: Returns 0 if permission is granted. + */ int security_xfrm_policy_delete(struct xfrm_sec_ctx *ctx) { return call_int_hook(xfrm_policy_delete_security, 0, ctx); } +/** + * security_xfrm_state_alloc() - Allocate a xfrm state LSM blob + * @x: xfrm state being added to the SAD + * @sec_ctx: security label provided by userspace + * + * Allocate a security structure to the @x->security field; the security field + * is initialized to NULL when the xfrm_state is allocated. Set the context to + * correspond to @sec_ctx. + * + * Return: Return 0 if operation was successful. + */ int security_xfrm_state_alloc(struct xfrm_state *x, struct xfrm_user_sec_ctx *sec_ctx) { @@ -4301,28 +4347,76 @@ int security_xfrm_state_alloc(struct xfrm_state *x, } EXPORT_SYMBOL(security_xfrm_state_alloc); +/** + * security_xfrm_state_alloc_acquire() - Allocate a xfrm state LSM blob + * @x: xfrm state being added to the SAD + * @polsec: associated policy's security context + * @secid: secid from the flow + * + * Allocate a security structure to the x->security field; the security field + * is initialized to NULL when the xfrm_state is allocated. Set the context to + * correspond to secid. + * + * Return: Returns 0 if operation was successful. + */ int security_xfrm_state_alloc_acquire(struct xfrm_state *x, struct xfrm_sec_ctx *polsec, u32 secid) { return call_int_hook(xfrm_state_alloc_acquire, 0, x, polsec, secid); } +/** + * security_xfrm_state_delete() - Check if deleting a xfrm state is allowed + * @x: xfrm state + * + * Authorize deletion of x->security. + * + * Return: Returns 0 if permission is granted. + */ int security_xfrm_state_delete(struct xfrm_state *x) { return call_int_hook(xfrm_state_delete_security, 0, x); } EXPORT_SYMBOL(security_xfrm_state_delete); +/** + * security_xfrm_state_free() - Free a xfrm state + * @x: xfrm state + * + * Deallocate x->security. + */ void security_xfrm_state_free(struct xfrm_state *x) { call_void_hook(xfrm_state_free_security, x); } +/** + * security_xfrm_policy_lookup() - Check if using a xfrm policy is allowed + * @ctx: target xfrm security context + * @fl_secid: flow secid used to authorize access + * + * Check permission when a flow selects a xfrm_policy for processing XFRMs on a + * packet. The hook is called when selecting either a per-socket policy or a + * generic xfrm policy. + * + * Return: Return 0 if permission is granted, -ESRCH otherwise, or -errno on + * other errors. + */ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) { return call_int_hook(xfrm_policy_lookup, 0, ctx, fl_secid); } +/** + * security_xfrm_state_pol_flow_match() - Check for a xfrm match + * @x: xfrm state to match + * @xp xfrm policy to check for a match + * @flic: flow to check for a match. + * + * Check @xp and @flic for a match with @x. + * + * Return: Returns 1 if there is a match. + */ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, struct xfrm_policy *xp, const struct flowi_common *flic) @@ -4347,6 +4441,15 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, return rc; } +/** + * security_xfrm_decode_session() - Determine the xfrm secid for a packet + * @skb: xfrm packet + * @secid: secid + * + * Decode the packet in @skb and return the security label in @secid. + * + * Return: Return 0 if all xfrms used have the same secid. + */ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) { return call_int_hook(xfrm_decode_session, 0, skb, secid, 1); From ecc419a4453530c410c7031bc69ef34782b1c8ff Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 15 Feb 2023 21:46:31 -0500 Subject: [PATCH 016/291] lsm: move the key hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 32 ------------------------------- security/security.c | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 32 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9c5254e4e9d1..2cfa56e3abc3 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,38 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks affecting all Key Management operations - * - * @key_alloc: - * Permit allocation of a key and assign security data. Note that key does - * not have a serial number assigned at this point. - * @key points to the key. - * @flags is the allocation flags. - * Return 0 if permission is granted, -ve error otherwise. - * @key_free: - * Notification of destruction; free security data. - * @key points to the key. - * No return value. - * @key_permission: - * See whether a specific operational right is granted to a process on a - * key. - * @key_ref refers to the key (key pointer + possession attribute bit). - * @cred points to the credentials to provide the context against which to - * evaluate the security data on the key. - * @perm describes the combination of permissions required of this key. - * Return 0 if permission is granted, -ve error otherwise. - * @key_getsecurity: - * Get a textual representation of the security context attached to a key - * for the purposes of honouring KEYCTL_GETSECURITY. This function - * allocates the storage for the NUL-terminated string and the caller - * should free it. - * @key points to the key to be queried. - * @_buffer points to a pointer that should be set to point to the - * resulting string (if no label or an error occurs). - * Return the length of the string (including terminating NUL) or -ve if - * an error. - * May also return 0 (and a NULL buffer pointer) if there is no label. - * * Security hooks affecting all System V IPC operations. * * @ipc_permission: diff --git a/security/security.c b/security/security.c index d3880096922e..bde8d24af6ac 100644 --- a/security/security.c +++ b/security/security.c @@ -4468,23 +4468,63 @@ EXPORT_SYMBOL(security_skb_classify_flow); #ifdef CONFIG_KEYS +/** + * security_key_alloc() - Allocate and initialize a kernel key LSM blob + * @key: key + * @cred: credentials + * @flags: allocation flags + * + * Permit allocation of a key and assign security data. Note that key does not + * have a serial number assigned at this point. + * + * Return: Return 0 if permission is granted, -ve error otherwise. + */ int security_key_alloc(struct key *key, const struct cred *cred, unsigned long flags) { return call_int_hook(key_alloc, 0, key, cred, flags); } +/** + * security_key_free() - Free a kernel key LSM blob + * @key: key + * + * Notification of destruction; free security data. + */ void security_key_free(struct key *key) { call_void_hook(key_free, key); } +/** + * security_key_permission() - Check if a kernel key operation is allowed + * @key_ref: key reference + * @cred: credentials of actor requesting access + * @need_perm: requested permissions + * + * See whether a specific operational right is granted to a process on a key. + * + * Return: Return 0 if permission is granted, -ve error otherwise. + */ int security_key_permission(key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) { return call_int_hook(key_permission, 0, key_ref, cred, need_perm); } +/** + * security_key_getsecurity() - Get the key's security label + * @key: key + * @buffer: security label buffer + * + * Get a textual representation of the security context attached to a key for + * the purposes of honouring KEYCTL_GETSECURITY. This function allocates the + * storage for the NUL-terminated string and the caller should free it. + * + * Return: Returns the length of @buffer (including terminating NUL) or -ve if + * an error occurs. May also return 0 (and a NULL buffer pointer) if + * there is no security label assigned to the key. + */ int security_key_getsecurity(struct key *key, char **_buffer) { *_buffer = NULL; From 43fad282187695e25c51425ee9f5f9f08fe5e15d Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 11:53:49 -0500 Subject: [PATCH 017/291] lsm: move the sysv hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 141 ---------------------------- security/security.c | 191 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 141 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 2cfa56e3abc3..f6679fead627 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,147 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * Security hooks affecting all System V IPC operations. - * - * @ipc_permission: - * Check permissions for access to IPC - * @ipcp contains the kernel IPC permission structure. - * @flag contains the desired (requested) permission set. - * Return 0 if permission is granted. - * @ipc_getsecid: - * Get the secid associated with the ipc object. - * @ipcp contains the kernel IPC permission structure. - * @secid contains a pointer to the location where result will be saved. - * In case of failure, @secid will be set to zero. - * - * Security hooks for individual messages held in System V IPC message queues - * - * @msg_msg_alloc_security: - * Allocate and attach a security structure to the msg->security field. - * The security field is initialized to NULL when the structure is first - * created. - * @msg contains the message structure to be modified. - * Return 0 if operation was successful and permission is granted. - * @msg_msg_free_security: - * Deallocate the security structure for this message. - * @msg contains the message structure to be modified. - * - * Security hooks for System V IPC Message Queues - * - * @msg_queue_alloc_security: - * Allocate and attach a security structure to the - * @perm->security field. The security field is initialized to - * NULL when the structure is first created. - * @perm contains the IPC permissions of the message queue. - * Return 0 if operation was successful and permission is granted. - * @msg_queue_free_security: - * Deallocate security field @perm->security for the message queue. - * @perm contains the IPC permissions of the message queue. - * @msg_queue_associate: - * Check permission when a message queue is requested through the - * msgget system call. This hook is only called when returning the - * message queue identifier for an existing message queue, not when a - * new message queue is created. - * @perm contains the IPC permissions of the message queue. - * @msqflg contains the operation control flags. - * Return 0 if permission is granted. - * @msg_queue_msgctl: - * Check permission when a message control operation specified by @cmd - * is to be performed on the message queue with permissions @perm. - * The @perm may be NULL, e.g. for IPC_INFO or MSG_INFO. - * @perm contains the IPC permissions of the msg queue. May be NULL. - * @cmd contains the operation to be performed. - * Return 0 if permission is granted. - * @msg_queue_msgsnd: - * Check permission before a message, @msg, is enqueued on the message - * queue with permissions @perm. - * @perm contains the IPC permissions of the message queue. - * @msg contains the message to be enqueued. - * @msqflg contains operational flags. - * Return 0 if permission is granted. - * @msg_queue_msgrcv: - * Check permission before a message, @msg, is removed from the message - * queue. The @target task structure contains a pointer to the - * process that will be receiving the message (not equal to the current - * process when inline receives are being performed). - * @perm contains the IPC permissions of the message queue. - * @msg contains the message destination. - * @target contains the task structure for recipient process. - * @type contains the type of message requested. - * @mode contains the operational flags. - * Return 0 if permission is granted. - * - * Security hooks for System V Shared Memory Segments - * - * @shm_alloc_security: - * Allocate and attach a security structure to the @perm->security - * field. The security field is initialized to NULL when the structure is - * first created. - * @perm contains the IPC permissions of the shared memory structure. - * Return 0 if operation was successful and permission is granted. - * @shm_free_security: - * Deallocate the security structure @perm->security for the memory segment. - * @perm contains the IPC permissions of the shared memory structure. - * @shm_associate: - * Check permission when a shared memory region is requested through the - * shmget system call. This hook is only called when returning the shared - * memory region identifier for an existing region, not when a new shared - * memory region is created. - * @perm contains the IPC permissions of the shared memory structure. - * @shmflg contains the operation control flags. - * Return 0 if permission is granted. - * @shm_shmctl: - * Check permission when a shared memory control operation specified by - * @cmd is to be performed on the shared memory region with permissions @perm. - * The @perm may be NULL, e.g. for IPC_INFO or SHM_INFO. - * @perm contains the IPC permissions of the shared memory structure. - * @cmd contains the operation to be performed. - * Return 0 if permission is granted. - * @shm_shmat: - * Check permissions prior to allowing the shmat system call to attach the - * shared memory segment with permissions @perm to the data segment of the - * calling process. The attaching address is specified by @shmaddr. - * @perm contains the IPC permissions of the shared memory structure. - * @shmaddr contains the address to attach memory region to. - * @shmflg contains the operational flags. - * Return 0 if permission is granted. - * - * Security hooks for System V Semaphores - * - * @sem_alloc_security: - * Allocate and attach a security structure to the @perm->security - * field. The security field is initialized to NULL when the structure is - * first created. - * @perm contains the IPC permissions of the semaphore. - * Return 0 if operation was successful and permission is granted. - * @sem_free_security: - * Deallocate security structure @perm->security for the semaphore. - * @perm contains the IPC permissions of the semaphore. - * @sem_associate: - * Check permission when a semaphore is requested through the semget - * system call. This hook is only called when returning the semaphore - * identifier for an existing semaphore, not when a new one must be - * created. - * @perm contains the IPC permissions of the semaphore. - * @semflg contains the operation control flags. - * Return 0 if permission is granted. - * @sem_semctl: - * Check permission when a semaphore operation specified by @cmd is to be - * performed on the semaphore. The @perm may be NULL, e.g. for - * IPC_INFO or SEM_INFO. - * @perm contains the IPC permissions of the semaphore. May be NULL. - * @cmd contains the operation to be performed. - * Return 0 if permission is granted. - * @sem_semop: - * Check permissions before performing operations on members of the - * semaphore set. If the @alter flag is nonzero, the semaphore set - * may be modified. - * @perm contains the IPC permissions of the semaphore. - * @sops contains the operations to perform. - * @nsops contains the number of operations to perform. - * @alter contains the flag indicating whether changes are to be made. - * Return 0 if permission is granted. - * * @binder_set_context_mgr: * Check whether @mgr is allowed to be the binder context manager. * @mgr contains the struct cred for the current binder process. diff --git a/security/security.c b/security/security.c index bde8d24af6ac..83443984b11a 100644 --- a/security/security.c +++ b/security/security.c @@ -3254,17 +3254,43 @@ int security_create_user_ns(const struct cred *cred) return call_int_hook(userns_create, 0, cred); } +/** + * security_ipc_permission() - Check if sysv ipc access is allowed + * @ipcp: ipc permission structure + * @flags: requested permissions + * + * Check permissions for access to IPC. + * + * Return: Returns 0 if permission is granted. + */ int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag) { return call_int_hook(ipc_permission, 0, ipcp, flag); } +/** + * security_ipc_getsecid() - Get the sysv ipc object's secid + * @ipcp: ipc permission structure + * @secid: secid pointer + * + * Get the secid associated with the ipc object. In case of failure, @secid + * will be set to zero. + */ void security_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid) { *secid = 0; call_void_hook(ipc_getsecid, ipcp, secid); } +/** + * security_msg_msg_alloc() - Allocate a sysv ipc message LSM blob + * @msg: message structure + * + * Allocate and attach a security structure to the msg->security field. The + * security field is initialized to NULL when the structure is first created. + * + * Return: Return 0 if operation was successful and permission is granted. + */ int security_msg_msg_alloc(struct msg_msg *msg) { int rc = lsm_msg_msg_alloc(msg); @@ -3277,6 +3303,12 @@ int security_msg_msg_alloc(struct msg_msg *msg) return rc; } +/** + * security_msg_msg_free() - Free a sysv ipc message LSM blob + * @msg: message structure + * + * Deallocate the security structure for this message. + */ void security_msg_msg_free(struct msg_msg *msg) { call_void_hook(msg_msg_free_security, msg); @@ -3284,6 +3316,15 @@ void security_msg_msg_free(struct msg_msg *msg) msg->security = NULL; } +/** + * security_msg_queue_alloc() - Allocate a sysv ipc msg queue LSM blob + * @msq: sysv ipc permission structure + * + * Allocate and attach a security structure to @msg. The security field is + * initialized to NULL when the structure is first created. + * + * Return: Returns 0 if operation was successful and permission is granted. + */ int security_msg_queue_alloc(struct kern_ipc_perm *msq) { int rc = lsm_ipc_alloc(msq); @@ -3296,6 +3337,12 @@ int security_msg_queue_alloc(struct kern_ipc_perm *msq) return rc; } +/** + * security_msg_queue_free() - Free a sysv ipc msg queue LSM blob + * @msq: sysv ipc permission structure + * + * Deallocate security field @perm->security for the message queue. + */ void security_msg_queue_free(struct kern_ipc_perm *msq) { call_void_hook(msg_queue_free_security, msq); @@ -3303,28 +3350,84 @@ void security_msg_queue_free(struct kern_ipc_perm *msq) msq->security = NULL; } +/** + * security_msg_queue_associate() - Check if a msg queue operation is allowed + * @msq: sysv ipc permission structure + * @msqflg: operation flags + * + * Check permission when a message queue is requested through the msgget system + * call. This hook is only called when returning the message queue identifier + * for an existing message queue, not when a new message queue is created. + * + * Return: Return 0 if permission is granted. + */ int security_msg_queue_associate(struct kern_ipc_perm *msq, int msqflg) { return call_int_hook(msg_queue_associate, 0, msq, msqflg); } +/** + * security_msg_queue_msgctl() - Check if a msg queue operation is allowed + * @msq: sysv ipc permission structure + * @cmd: operation + * + * Check permission when a message control operation specified by @cmd is to be + * performed on the message queue with permissions. + * + * Return: Returns 0 if permission is granted. + */ int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) { return call_int_hook(msg_queue_msgctl, 0, msq, cmd); } +/** + * security_msg_queue_msgsnd() - Check if sending a sysv ipc message is allowed + * @msq: sysv ipc permission structure + * @msg: message + * @msqflg: operation flags + * + * Check permission before a message, @msg, is enqueued on the message queue + * with permissions specified in @msq. + * + * Return: Returns 0 if permission is granted. + */ int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, struct msg_msg *msg, int msqflg) { return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg); } +/** + * security_msg_queue_msgrcv() - Check if receiving a sysv ipc msg is allowed + * @msq: sysv ipc permission structure + * @msg: message + * @target: target task + * @type: type of message requested + * @mode: operation flags + * + * Check permission before a message, @msg, is removed from the message queue. + * The @target task structure contains a pointer to the process that will be + * receiving the message (not equal to the current process when inline receives + * are being performed). + * + * Return: Returns 0 if permission is granted. + */ int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, struct task_struct *target, long type, int mode) { return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode); } +/** + * security_shm_alloc() - Allocate a sysv shm LSM blob + * @shp: sysv ipc permission structure + * + * Allocate and attach a security structure to the @shp security field. The + * security field is initialized to NULL when the structure is first created. + * + * Return: Returns 0 if operation was successful and permission is granted. + */ int security_shm_alloc(struct kern_ipc_perm *shp) { int rc = lsm_ipc_alloc(shp); @@ -3337,6 +3440,12 @@ int security_shm_alloc(struct kern_ipc_perm *shp) return rc; } +/** + * security_shm_free() - Free a sysv shm LSM blob + * @shp: sysv ipc permission structure + * + * Deallocate the security structure @perm->security for the memory segment. + */ void security_shm_free(struct kern_ipc_perm *shp) { call_void_hook(shm_free_security, shp); @@ -3344,21 +3453,64 @@ void security_shm_free(struct kern_ipc_perm *shp) shp->security = NULL; } +/** + * security_shm_associate() - Check if a sysv shm operation is allowed + * @shp: sysv ipc permission structure + * @shmflg: operation flags + * + * Check permission when a shared memory region is requested through the shmget + * system call. This hook is only called when returning the shared memory + * region identifier for an existing region, not when a new shared memory + * region is created. + * + * Return: Returns 0 if permission is granted. + */ int security_shm_associate(struct kern_ipc_perm *shp, int shmflg) { return call_int_hook(shm_associate, 0, shp, shmflg); } +/** + * security_shm_shmctl() - Check if a sysv shm operation is allowed + * @shp: sysv ipc permission structure + * @cmd: operation + * + * Check permission when a shared memory control operation specified by @cmd is + * to be performed on the shared memory region with permissions in @shp. + * + * Return: Return 0 if permission is granted. + */ int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) { return call_int_hook(shm_shmctl, 0, shp, cmd); } +/** + * security_shm_shmat() - Check if a sysv shm attach operation is allowed + * @shp: sysv ipc permission structure + * @shmaddr: address of memory region to attach + * @shmflg: operation flags + * + * Check permissions prior to allowing the shmat system call to attach the + * shared memory segment with permissions @shp to the data segment of the + * calling process. The attaching address is specified by @shmaddr. + * + * Return: Returns 0 if permission is granted. + */ int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) { return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg); } +/** + * security_sem_alloc() - Allocate a sysv semaphore LSM blob + * @sma: sysv ipc permission structure + * + * Allocate and attach a security structure to the @sma security field. The + * security field is initialized to NULL when the structure is first created. + * + * Return: Returns 0 if operation was successful and permission is granted. + */ int security_sem_alloc(struct kern_ipc_perm *sma) { int rc = lsm_ipc_alloc(sma); @@ -3371,6 +3523,12 @@ int security_sem_alloc(struct kern_ipc_perm *sma) return rc; } +/** + * security_sem_free() - Free a sysv semaphore LSM blob + * @sma: sysv ipc permission structure + * + * Deallocate security structure @sma->security for the semaphore. + */ void security_sem_free(struct kern_ipc_perm *sma) { call_void_hook(sem_free_security, sma); @@ -3378,16 +3536,49 @@ void security_sem_free(struct kern_ipc_perm *sma) sma->security = NULL; } +/** + * security_sem_associate() - Check if a sysv semaphore operation is allowed + * @sma: sysv ipc permission structure + * @semflg: operation flags + * + * Check permission when a semaphore is requested through the semget system + * call. This hook is only called when returning the semaphore identifier for + * an existing semaphore, not when a new one must be created. + * + * Return: Returns 0 if permission is granted. + */ int security_sem_associate(struct kern_ipc_perm *sma, int semflg) { return call_int_hook(sem_associate, 0, sma, semflg); } +/** + * security_sem_ctl() - Check if a sysv semaphore operation is allowed + * @sma: sysv ipc permission structure + * @cmd: operation + * + * Check permission when a semaphore operation specified by @cmd is to be + * performed on the semaphore. + * + * Return: Returns 0 if permission is granted. + */ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) { return call_int_hook(sem_semctl, 0, sma, cmd); } +/** + * security_sem_semop() - Check if a sysv semaphore operation is allowed + * @sma: sysv ipc permission structure + * @sops: operations to perform + * @nsops: number of operations + * @alter: flag indicating changes will be made + * + * Check permissions before performing operations on members of the semaphore + * set. If the @alter flag is nonzero, the semaphore set may be modified. + * + * Return: Returns 0 if permission is granted. + */ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, unsigned nsops, int alter) { From 1427ddbe5cc1a3d4ac068cea78638baf95f16c18 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 16:39:08 -0500 Subject: [PATCH 018/291] lsm: move the binder hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 22 ---------------------- security/security.c | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index f6679fead627..0a5b3b46fc2b 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -32,28 +32,6 @@ /** * union security_list_options - Linux Security Module hook function list * - * @binder_set_context_mgr: - * Check whether @mgr is allowed to be the binder context manager. - * @mgr contains the struct cred for the current binder process. - * Return 0 if permission is granted. - * @binder_transaction: - * Check whether @from is allowed to invoke a binder transaction call - * to @to. - * @from contains the struct cred for the sending process. - * @to contains the struct cred for the receiving process. - * Return 0 if permission is granted. - * @binder_transfer_binder: - * Check whether @from is allowed to transfer a binder reference to @to. - * @from contains the struct cred for the sending process. - * @to contains the struct cred for the receiving process. - * Return 0 if permission is granted. - * @binder_transfer_file: - * Check whether @from is allowed to transfer @file to @to. - * @from contains the struct cred for the sending process. - * @file contains the struct file being transferred. - * @to contains the struct cred for the receiving process. - * Return 0 if permission is granted. - * * @ptrace_access_check: * Check permission before allowing the current process to trace the * @child process. diff --git a/security/security.c b/security/security.c index 83443984b11a..b21154ed152f 100644 --- a/security/security.c +++ b/security/security.c @@ -779,23 +779,59 @@ static int lsm_superblock_alloc(struct super_block *sb) /* Security operations */ +/** + * security_binder_set_context_mgr() - Check if becoming binder ctx mgr is ok + * @mgr: task credentials of current binder process + * + * Check whether @mgr is allowed to be the binder context manager. + * + * Return: Return 0 if permission is granted. + */ int security_binder_set_context_mgr(const struct cred *mgr) { return call_int_hook(binder_set_context_mgr, 0, mgr); } +/** + * security_binder_transaction() - Check if a binder transaction is allowed + * @from: sending process + * @to: receiving process + * + * Check whether @from is allowed to invoke a binder transaction call to @to. + * + * Return: Returns 0 if permission is granted. + */ int security_binder_transaction(const struct cred *from, const struct cred *to) { return call_int_hook(binder_transaction, 0, from, to); } +/** + * security_binder_transfer_binder() - Check if a binder transfer is allowed + * @from: sending process + * @to: receiving process + * + * Check whether @from is allowed to transfer a binder reference to @to. + * + * Return: Returns 0 if permission is granted. + */ int security_binder_transfer_binder(const struct cred *from, const struct cred *to) { return call_int_hook(binder_transfer_binder, 0, from, to); } +/** + * security_binder_transfer_file() - Check if a binder file xfer is allowed + * @from: sending process + * @to: receiving process + * @file: file being transferred + * + * Check whether @from is allowed to transfer @file to @to. + * + * Return: Returns 0 if permission is granted. + */ int security_binder_transfer_file(const struct cred *from, const struct cred *to, struct file *file) { From b14faf9c94a66ef398c2c3fa6e141814f04e274e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 17:00:01 -0500 Subject: [PATCH 019/291] lsm: move the audit hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 32 ------------------------------ security/security.c | 41 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 32 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 0a5b3b46fc2b..e36387f88083 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -135,38 +135,6 @@ * @secdata contains the security context. * @seclen contains the length of the security context. * - * Security hooks for Audit - * - * @audit_rule_init: - * Allocate and initialize an LSM audit rule structure. - * @field contains the required Audit action. - * Fields flags are defined in - * @op contains the operator the rule uses. - * @rulestr contains the context where the rule will be applied to. - * @lsmrule contains a pointer to receive the result. - * Return 0 if @lsmrule has been successfully set, - * -EINVAL in case of an invalid rule. - * - * @audit_rule_known: - * Specifies whether given @krule contains any fields related to - * current LSM. - * @krule contains the audit rule of interest. - * Return 1 in case of relation found, 0 otherwise. - * - * @audit_rule_match: - * Determine if given @secid matches a rule previously approved - * by @audit_rule_known. - * @secid contains the security id in question. - * @field contains the field which relates to current LSM. - * @op contains the operator that will be used for matching. - * @lrule points to the audit rule that will be checked against. - * Return 1 if secid matches the rule, 0 if it does not, -ERRNO on failure. - * - * @audit_rule_free: - * Deallocate the LSM audit rule structure previously allocated by - * audit_rule_init. - * @lsmrule contains the allocated rule. - * * @inode_invalidate_secctx: * Notify the security module that it must revalidate the security context * of an inode. diff --git a/security/security.c b/security/security.c index b21154ed152f..80c05c28b7ff 100644 --- a/security/security.c +++ b/security/security.c @@ -4762,21 +4762,62 @@ int security_key_getsecurity(struct key *key, char **_buffer) #ifdef CONFIG_AUDIT +/** + * security_audit_rule_init() - Allocate and init an LSM audit rule struct + * @field: audit action + * @op: rule operator + * @rulestr: rule context + * @lsmrule: receive buffer for audit rule struct + * + * Allocate and initialize an LSM audit rule structure. + * + * Return: Return 0 if @lsmrule has been successfully set, -EINVAL in case of + * an invalid rule. + */ int security_audit_rule_init(u32 field, u32 op, char *rulestr, void **lsmrule) { return call_int_hook(audit_rule_init, 0, field, op, rulestr, lsmrule); } +/** + * security_audit_rule_known() - Check if an audit rule contains LSM fields + * @krule: audit rule + * + * Specifies whether given @krule contains any fields related to the current + * LSM. + * + * Return: Returns 1 in case of relation found, 0 otherwise. + */ int security_audit_rule_known(struct audit_krule *krule) { return call_int_hook(audit_rule_known, 0, krule); } +/** + * security_audit_rule_free() - Free an LSM audit rule struct + * @lsmrule: audit rule struct + * + * Deallocate the LSM audit rule structure previously allocated by + * audit_rule_init(). + */ void security_audit_rule_free(void *lsmrule) { call_void_hook(audit_rule_free, lsmrule); } +/** + * security_audit_rule_match() - Check if a label matches an audit rule + * @secid: security label + * @field: LSM audit field + * @op: matching operator + * @lsmrule: audit rule + * + * Determine if given @secid matches a rule previously approved by + * security_audit_rule_known(). + * + * Return: Returns 1 if secid matches the rule, 0 if it does not, -ERRNO on + * failure. + */ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) { return call_int_hook(audit_rule_match, 0, secid, field, op, lsmrule); From 55e853201a9e0383c9f6d5d800155e334685cd7e Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 17:13:40 -0500 Subject: [PATCH 020/291] lsm: move the bpf hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 36 ---------------------- security/security.c | 65 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index e36387f88083..601d1ecdae0f 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -190,42 +190,6 @@ * @key: The key to watch. * Return 0 if permission is granted. * - * Security hooks for using the eBPF maps and programs functionalities through - * eBPF syscalls. - * - * @bpf: - * Do a initial check for all bpf syscalls after the attribute is copied - * into the kernel. The actual security module can implement their own - * rules to check the specific cmd they need. - * Return 0 if permission is granted. - * - * @bpf_map: - * Do a check when the kernel generate and return a file descriptor for - * eBPF maps. - * @map: bpf map that we want to access. - * @mask: the access flags. - * Return 0 if permission is granted. - * - * @bpf_prog: - * Do a check when the kernel generate and return a file descriptor for - * eBPF programs. - * @prog: bpf prog that userspace want to use. - * Return 0 if permission is granted. - * - * @bpf_map_alloc_security: - * Initialize the security field inside bpf map. - * Return 0 on success, error on failure. - * - * @bpf_map_free_security: - * Clean up the security information stored inside bpf map. - * - * @bpf_prog_alloc_security: - * Initialize the security field inside bpf program. - * Return 0 on success, error on failure. - * - * @bpf_prog_free_security: - * Clean up the security information stored inside bpf prog. - * * @locked_down: * Determine whether a kernel feature that potentially enables arbitrary * code execution in kernel space should be permitted. diff --git a/security/security.c b/security/security.c index 80c05c28b7ff..4037af6b5196 100644 --- a/security/security.c +++ b/security/security.c @@ -4825,30 +4825,95 @@ int security_audit_rule_match(u32 secid, u32 field, u32 op, void *lsmrule) #endif /* CONFIG_AUDIT */ #ifdef CONFIG_BPF_SYSCALL +/** + * security_bpf() - Check if the bpf syscall operation is allowed + * @cmd: command + * @attr: bpf attribute + * @size: size + * + * Do a initial check for all bpf syscalls after the attribute is copied into + * the kernel. The actual security module can implement their own rules to + * check the specific cmd they need. + * + * Return: Returns 0 if permission is granted. + */ int security_bpf(int cmd, union bpf_attr *attr, unsigned int size) { return call_int_hook(bpf, 0, cmd, attr, size); } + +/** + * security_bpf_map() - Check if access to a bpf map is allowed + * @map: bpf map + * @fmode: mode + * + * Do a check when the kernel generates and returns a file descriptor for eBPF + * maps. + * + * Return: Returns 0 if permission is granted. + */ int security_bpf_map(struct bpf_map *map, fmode_t fmode) { return call_int_hook(bpf_map, 0, map, fmode); } + +/** + * security_bpf_prog() - Check if access to a bpf program is allowed + * @prog: bpf program + * + * Do a check when the kernel generates and returns a file descriptor for eBPF + * programs. + * + * Return: Returns 0 if permission is granted. + */ int security_bpf_prog(struct bpf_prog *prog) { return call_int_hook(bpf_prog, 0, prog); } + +/** + * security_bpf_map_alloc() - Allocate a bpf map LSM blob + * @map: bpf map + * + * Initialize the security field inside bpf map. + * + * Return: Returns 0 on success, error on failure. + */ int security_bpf_map_alloc(struct bpf_map *map) { return call_int_hook(bpf_map_alloc_security, 0, map); } + +/** + * security_bpf_prog_alloc() - Allocate a bpf program LSM blob + * @aux: bpf program aux info struct + * + * Initialize the security field inside bpf program. + * + * Return: Returns 0 on success, error on failure. + */ int security_bpf_prog_alloc(struct bpf_prog_aux *aux) { return call_int_hook(bpf_prog_alloc_security, 0, aux); } + +/** + * security_bpf_map_free() - Free a bpf map's LSM blob + * @map: bpf map + * + * Clean up the security information stored inside bpf map. + */ void security_bpf_map_free(struct bpf_map *map) { call_void_hook(bpf_map_free_security, map); } + +/** + * security_bpf_prog_free() - Free a bpf program's LSM blob + * @aux: bpf program aux info struct + * + * Clean up the security information stored inside bpf prog. + */ void security_bpf_prog_free(struct bpf_prog_aux *aux) { call_void_hook(bpf_prog_free_security, aux); From 452b670c7222c7bf11b45b13f5a736f96d0be1e3 Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 17:22:36 -0500 Subject: [PATCH 021/291] lsm: move the perf hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 17 ----------------- security/security.c | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 17 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 601d1ecdae0f..3d8d430e271a 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -196,23 +196,6 @@ * @what: kernel feature being accessed. * Return 0 if permission is granted. * - * Security hooks for perf events - * - * @perf_event_open: - * Check whether the @type of perf_event_open syscall is allowed. - * Return 0 if permission is granted. - * @perf_event_alloc: - * Allocate and save perf_event security info. - * Return 0 on success, error on failure. - * @perf_event_free: - * Release (free) perf_event security info. - * @perf_event_read: - * Read perf_event security info if allowed. - * Return 0 if permission is granted. - * @perf_event_write: - * Write perf_event security info if allowed. - * Return 0 if permission is granted. - * * Security hooks for io_uring * * @uring_override_creds: diff --git a/security/security.c b/security/security.c index 4037af6b5196..47506ae1b187 100644 --- a/security/security.c +++ b/security/security.c @@ -4927,26 +4927,65 @@ int security_locked_down(enum lockdown_reason what) EXPORT_SYMBOL(security_locked_down); #ifdef CONFIG_PERF_EVENTS +/** + * security_perf_event_open() - Check if a perf event open is allowed + * @attr: perf event attribute + * @type: type of event + * + * Check whether the @type of perf_event_open syscall is allowed. + * + * Return: Returns 0 if permission is granted. + */ int security_perf_event_open(struct perf_event_attr *attr, int type) { return call_int_hook(perf_event_open, 0, attr, type); } +/** + * security_perf_event_alloc() - Allocate a perf event LSM blob + * @event: perf event + * + * Allocate and save perf_event security info. + * + * Return: Returns 0 on success, error on failure. + */ int security_perf_event_alloc(struct perf_event *event) { return call_int_hook(perf_event_alloc, 0, event); } +/** + * security_perf_event_free() - Free a perf event LSM blob + * @event: perf event + * + * Release (free) perf_event security info. + */ void security_perf_event_free(struct perf_event *event) { call_void_hook(perf_event_free, event); } +/** + * security_perf_event_read() - Check if reading a perf event label is allowed + * @event: perf event + * + * Read perf_event security info if allowed. + * + * Return: Returns 0 if permission is granted. + */ int security_perf_event_read(struct perf_event *event) { return call_int_hook(perf_event_read, 0, event); } +/** + * security_perf_event_write() - Check if writing a perf event label is allowed + * @event: perf event + * + * Write perf_event security info if allowed. + * + * Return: Returns 0 if permission is granted. + */ int security_perf_event_write(struct perf_event *event) { return call_int_hook(perf_event_write, 0, event); From 1cd2aca64a5dc4edb65539dc26f24e162ab0e11c Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 17:28:31 -0500 Subject: [PATCH 022/291] lsm: move the io_uring hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 17 ----------------- security/security.c | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 3d8d430e271a..8e006df1db56 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -196,23 +196,6 @@ * @what: kernel feature being accessed. * Return 0 if permission is granted. * - * Security hooks for io_uring - * - * @uring_override_creds: - * Check if the current task, executing an io_uring operation, is allowed - * to override it's credentials with @new. - * @new: the new creds to use. - * Return 0 if permission is granted. - * - * @uring_sqpoll: - * Check whether the current task is allowed to spawn a io_uring polling - * thread (IORING_SETUP_SQPOLL). - * Return 0 if permission is granted. - * - * @uring_cmd: - * Check whether the file_operations uring_cmd is allowed to run. - * Return 0 if permission is granted. - * */ union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); diff --git a/security/security.c b/security/security.c index 47506ae1b187..af1db3fa7cd0 100644 --- a/security/security.c +++ b/security/security.c @@ -4993,15 +4993,41 @@ int security_perf_event_write(struct perf_event *event) #endif /* CONFIG_PERF_EVENTS */ #ifdef CONFIG_IO_URING +/** + * security_uring_override_creds() - Check if overriding creds is allowed + * @new: new credentials + * + * Check if the current task, executing an io_uring operation, is allowed to + * override it's credentials with @new. + * + * Return: Returns 0 if permission is granted. + */ int security_uring_override_creds(const struct cred *new) { return call_int_hook(uring_override_creds, 0, new); } +/** + * security_uring_sqpoll() - Check if IORING_SETUP_SQPOLL is allowed + * + * Check whether the current task is allowed to spawn a io_uring polling thread + * (IORING_SETUP_SQPOLL). + * + * Return: Returns 0 if permission is granted. + */ int security_uring_sqpoll(void) { return call_int_hook(uring_sqpoll, 0); } + +/** + * security_uring_cmd() - Check if a io_uring passthrough command is allowed + * @ioucmd: command + * + * Check whether the file_operations uring_cmd is allowed to run. + * + * Return: Returns 0 if permission is granted. + */ int security_uring_cmd(struct io_uring_cmd *ioucmd) { return call_int_hook(uring_cmd, 0, ioucmd); From e261301c851aee401cfc63179ca4d3facd2f098b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 17:34:14 -0500 Subject: [PATCH 023/291] lsm: move the remaining LSM hook comments to security/security.c This patch relocates the LSM hook function comments to the function definitions, in keeping with the current kernel conventions. This should make the hook descriptions more easily discoverable and easier to maintain. While formatting changes have been done to better fit the kernel-doc style, content changes have been kept to a minimum and limited to text which was obviously incorrect and/or outdated. It is expected the future patches will improve the quality of the function header comments. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 168 --------------------------- security/security.c | 231 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 231 insertions(+), 168 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 8e006df1db56..ddbbe89a7a48 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -29,174 +29,6 @@ #include #include -/** - * union security_list_options - Linux Security Module hook function list - * - * @ptrace_access_check: - * Check permission before allowing the current process to trace the - * @child process. - * Security modules may also want to perform a process tracing check - * during an execve in the set_security or apply_creds hooks of - * tracing check during an execve in the bprm_set_creds hook of - * binprm_security_ops if the process is being traced and its security - * attributes would be changed by the execve. - * @child contains the task_struct structure for the target process. - * @mode contains the PTRACE_MODE flags indicating the form of access. - * Return 0 if permission is granted. - * @ptrace_traceme: - * Check that the @parent process has sufficient permission to trace the - * current process before allowing the current process to present itself - * to the @parent process for tracing. - * @parent contains the task_struct structure for debugger process. - * Return 0 if permission is granted. - * @capget: - * Get the @effective, @inheritable, and @permitted capability sets for - * the @target process. The hook may also perform permission checking to - * determine if the current process is allowed to see the capability sets - * of the @target process. - * @target contains the task_struct structure for target process. - * @effective contains the effective capability set. - * @inheritable contains the inheritable capability set. - * @permitted contains the permitted capability set. - * Return 0 if the capability sets were successfully obtained. - * @capset: - * Set the @effective, @inheritable, and @permitted capability sets for - * the current process. - * @new contains the new credentials structure for target process. - * @old contains the current credentials structure for target process. - * @effective contains the effective capability set. - * @inheritable contains the inheritable capability set. - * @permitted contains the permitted capability set. - * Return 0 and update @new if permission is granted. - * @capable: - * Check whether the @tsk process has the @cap capability in the indicated - * credentials. - * @cred contains the credentials to use. - * @ns contains the user namespace we want the capability in. - * @cap contains the capability . - * @opts contains options for the capable check . - * Return 0 if the capability is granted for @tsk. - * @quotactl: - * Check whether the quotactl syscall is allowed for this @sb. - * Return 0 if permission is granted. - * @quota_on: - * Check whether QUOTAON is allowed for this @dentry. - * Return 0 if permission is granted. - * @syslog: - * Check permission before accessing the kernel message ring or changing - * logging to the console. - * See the syslog(2) manual page for an explanation of the @type values. - * @type contains the SYSLOG_ACTION_* constant from - * . - * Return 0 if permission is granted. - * @settime: - * Check permission to change the system time. - * struct timespec64 is defined in and timezone - * is defined in - * @ts contains new time. - * @tz contains new timezone. - * Return 0 if permission is granted. - * @vm_enough_memory: - * Check permissions for allocating a new virtual mapping. - * @mm contains the mm struct it is being added to. - * @pages contains the number of pages. - * Return 0 if permission is granted by the LSM infrastructure to the - * caller. If all LSMs return a positive value, __vm_enough_memory() will - * be called with cap_sys_admin set. If at least one LSM returns 0 or - * negative, __vm_enough_memory() will be called with cap_sys_admin - * cleared. - * - * @ismaclabel: - * Check if the extended attribute specified by @name - * represents a MAC label. Returns 1 if name is a MAC - * attribute otherwise returns 0. - * @name full extended attribute name to check against - * LSM as a MAC label. - * - * @secid_to_secctx: - * Convert secid to security context. If secdata is NULL the length of - * the result will be returned in seclen, but no secdata will be returned. - * This does mean that the length could change between calls to check the - * length and the next call which actually allocates and returns the - * secdata. - * @secid contains the security ID. - * @secdata contains the pointer that stores the converted security - * context. - * @seclen pointer which contains the length of the data. - * Return 0 on success, error on failure. - * @secctx_to_secid: - * Convert security context to secid. - * @secid contains the pointer to the generated security ID. - * @secdata contains the security context. - * Return 0 on success, error on failure. - * - * @release_secctx: - * Release the security context. - * @secdata contains the security context. - * @seclen contains the length of the security context. - * - * @inode_invalidate_secctx: - * Notify the security module that it must revalidate the security context - * of an inode. - * - * @inode_notifysecctx: - * Notify the security module of what the security context of an inode - * should be. Initializes the incore security context managed by the - * security module for this inode. Example usage: NFS client invokes - * this hook to initialize the security context in its incore inode to the - * value provided by the server for the file when the server returned the - * file's attributes to the client. - * Must be called with inode->i_mutex locked. - * @inode we wish to set the security context of. - * @ctx contains the string which we wish to set in the inode. - * @ctxlen contains the length of @ctx. - * Return 0 on success, error on failure. - * - * @inode_setsecctx: - * Change the security context of an inode. Updates the - * incore security context managed by the security module and invokes the - * fs code as needed (via __vfs_setxattr_noperm) to update any backing - * xattrs that represent the context. Example usage: NFS server invokes - * this hook to change the security context in its incore inode and on the - * backing filesystem to a value provided by the client on a SETATTR - * operation. - * Must be called with inode->i_mutex locked. - * @dentry contains the inode we wish to set the security context of. - * @ctx contains the string which we wish to set in the inode. - * @ctxlen contains the length of @ctx. - * Return 0 on success, error on failure. - * - * @inode_getsecctx: - * On success, returns 0 and fills out @ctx and @ctxlen with the security - * context for the given @inode. - * @inode we wish to get the security context of. - * @ctx is a pointer in which to place the allocated security context. - * @ctxlen points to the place to put the length of @ctx. - * Return 0 on success, error on failure. - * - * Security hooks for the general notification queue: - * - * @post_notification: - * Check to see if a watch notification can be posted to a particular - * queue. - * @w_cred: The credentials of the whoever set the watch. - * @cred: The event-triggerer's credentials. - * @n: The notification being posted. - * Return 0 if permission is granted. - * - * @watch_key: - * Check to see if a process is allowed to watch for event notifications - * from a key or keyring. - * @key: The key to watch. - * Return 0 if permission is granted. - * - * @locked_down: - * Determine whether a kernel feature that potentially enables arbitrary - * code execution in kernel space should be permitted. - * @what: kernel feature being accessed. - * Return 0 if permission is granted. - * - */ union security_list_options { #define LSM_HOOK(RET, DEFAULT, NAME, ...) RET (*NAME)(__VA_ARGS__); #include "lsm_hook_defs.h" diff --git a/security/security.c b/security/security.c index af1db3fa7cd0..190a701fe444 100644 --- a/security/security.c +++ b/security/security.c @@ -838,16 +838,54 @@ int security_binder_transfer_file(const struct cred *from, return call_int_hook(binder_transfer_file, 0, from, to, file); } +/** + * security_ptrace_access_check() - Check if tracing is allowed + * @child: target process + * @mode: PTRACE_MODE flags + * + * Check permission before allowing the current process to trace the @child + * process. Security modules may also want to perform a process tracing check + * during an execve in the set_security or apply_creds hooks of tracing check + * during an execve in the bprm_set_creds hook of binprm_security_ops if the + * process is being traced and its security attributes would be changed by the + * execve. + * + * Return: Returns 0 if permission is granted. + */ int security_ptrace_access_check(struct task_struct *child, unsigned int mode) { return call_int_hook(ptrace_access_check, 0, child, mode); } +/** + * security_ptrace_traceme() - Check if tracing is allowed + * @parent: tracing process + * + * Check that the @parent process has sufficient permission to trace the + * current process before allowing the current process to present itself to the + * @parent process for tracing. + * + * Return: Returns 0 if permission is granted. + */ int security_ptrace_traceme(struct task_struct *parent) { return call_int_hook(ptrace_traceme, 0, parent); } +/** + * security_capget() - Get the capability sets for a process + * @target: target process + * @effective: effective capability set + * @inheritable: inheritable capability set + * @permitted: permitted capability set + * + * Get the @effective, @inheritable, and @permitted capability sets for the + * @target process. The hook may also perform permission checking to determine + * if the current process is allowed to see the capability sets of the @target + * process. + * + * Return: Returns 0 if the capability sets were successfully obtained. + */ int security_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, @@ -857,6 +895,19 @@ int security_capget(struct task_struct *target, effective, inheritable, permitted); } +/** + * security_capset() - Set the capability sets for a process + * @new: new credentials for the target process + * @old: current credentials of the target process + * @effective: effective capability set + * @inheritable: inheritable capability set + * @permitted: permitted capability set + * + * Set the @effective, @inheritable, and @permitted capability sets for the + * current process. + * + * Return: Returns 0 and update @new if permission is granted. + */ int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *effective, const kernel_cap_t *inheritable, @@ -866,6 +917,19 @@ int security_capset(struct cred *new, const struct cred *old, effective, inheritable, permitted); } +/** + * security_capable() - Check if a process has the necessary capability + * @cred: credentials to examine + * @ns: user namespace + * @cap: capability requested + * @opts: capability check options + * + * Check whether the @tsk process has the @cap capability in the indicated + * credentials. @cap contains the capability . + * @opts contains options for the capable check . + * + * Return: Returns 0 if the capability is granted. + */ int security_capable(const struct cred *cred, struct user_namespace *ns, int cap, @@ -874,26 +938,78 @@ int security_capable(const struct cred *cred, return call_int_hook(capable, 0, cred, ns, cap, opts); } +/** + * security_quotactl() - Check if a quotactl() syscall is allowed for this fs + * @cmds: commands + * @type: type + * @id: id + * @sb: filesystem + * + * Check whether the quotactl syscall is allowed for this @sb. + * + * Return: Returns 0 if permission is granted. + */ int security_quotactl(int cmds, int type, int id, struct super_block *sb) { return call_int_hook(quotactl, 0, cmds, type, id, sb); } +/** + * security_quota_on() - Check if QUOTAON is allowed for a dentry + * @dentry: dentry + * + * Check whether QUOTAON is allowed for @dentry. + * + * Return: Returns 0 if permission is granted. + */ int security_quota_on(struct dentry *dentry) { return call_int_hook(quota_on, 0, dentry); } +/** + * security_syslog() - Check if accessing the kernel message ring is allowed + * @type: SYSLOG_ACTION_* type + * + * Check permission before accessing the kernel message ring or changing + * logging to the console. See the syslog(2) manual page for an explanation of + * the @type values. + * + * Return: Return 0 if permission is granted. + */ int security_syslog(int type) { return call_int_hook(syslog, 0, type); } +/** + * security_settime64() - Check if changing the system time is allowed + * @ts: new time + * @tz: timezone + * + * Check permission to change the system time, struct timespec64 is defined in + * and timezone is defined in . + * + * Return: Returns 0 if permission is granted. + */ int security_settime64(const struct timespec64 *ts, const struct timezone *tz) { return call_int_hook(settime, 0, ts, tz); } +/** + * security_vm_enough_memory_mm() - Check if allocating a new mem map is allowed + * @mm: mm struct + * @pages: number of pages + * + * Check permissions for allocating a new virtual mapping. If all LSMs return + * a positive value, __vm_enough_memory() will be called with cap_sys_admin + * set. If at least one LSM returns 0 or negative, __vm_enough_memory() will be + * called with cap_sys_admin cleared. + * + * Return: Returns 0 if permission is granted by the LSM infrastructure to the + * caller. + */ int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) { struct security_hook_list *hp; @@ -3703,12 +3819,33 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb) return call_int_hook(netlink_send, 0, sk, skb); } +/** + * security_ismaclabel() - Check is the named attribute is a MAC label + * @name: full extended attribute name + * + * Check if the extended attribute specified by @name represents a MAC label. + * + * Return: Returns 1 if name is a MAC attribute otherwise returns 0. + */ int security_ismaclabel(const char *name) { return call_int_hook(ismaclabel, 0, name); } EXPORT_SYMBOL(security_ismaclabel); +/** + * security_secid_to_secctx() - Convert a secid to a secctx + * @secid: secid + * @secdata: secctx + * @seclen: secctx length + * + * Convert secid to security context. If @secdata is NULL the length of the + * result will be returned in @seclen, but no @secdata will be returned. This + * does mean that the length could change between calls to check the length and + * the next call which actually allocates and returns the @secdata. + * + * Return: Return 0 on success, error on failure. + */ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) { struct security_hook_list *hp; @@ -3728,6 +3865,16 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) } EXPORT_SYMBOL(security_secid_to_secctx); +/** + * security_secctx_to_secid() - Convert a secctx to a secid + * @secdata: secctx + * @seclen: length of secctx + * @secid: secid + * + * Convert security context to secid. + * + * Return: Returns 0 on success, error on failure. + */ int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) { *secid = 0; @@ -3735,30 +3882,86 @@ int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) } EXPORT_SYMBOL(security_secctx_to_secid); +/** + * security_release_secctx() - Free a secctx buffer + * @secdata: secctx + * @seclen: length of secctx + * + * Release the security context. + */ void security_release_secctx(char *secdata, u32 seclen) { call_void_hook(release_secctx, secdata, seclen); } EXPORT_SYMBOL(security_release_secctx); +/** + * security_inode_invalidate_secctx() - Invalidate an inode's security label + * @inode: inode + * + * Notify the security module that it must revalidate the security context of + * an inode. + */ void security_inode_invalidate_secctx(struct inode *inode) { call_void_hook(inode_invalidate_secctx, inode); } EXPORT_SYMBOL(security_inode_invalidate_secctx); +/** + * security_inode_notifysecctx() - Nofify the LSM of an inode's security label + * @inode: inode + * @ctx: secctx + * @ctxlen: length of secctx + * + * Notify the security module of what the security context of an inode should + * be. Initializes the incore security context managed by the security module + * for this inode. Example usage: NFS client invokes this hook to initialize + * the security context in its incore inode to the value provided by the server + * for the file when the server returned the file's attributes to the client. + * Must be called with inode->i_mutex locked. + * + * Return: Returns 0 on success, error on failure. + */ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) { return call_int_hook(inode_notifysecctx, 0, inode, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_notifysecctx); +/** + * security_inode_setsecctx() - Change the security label of an inode + * @dentry: inode + * @ctx: secctx + * @ctxlen: length of secctx + * + * Change the security context of an inode. Updates the incore security + * context managed by the security module and invokes the fs code as needed + * (via __vfs_setxattr_noperm) to update any backing xattrs that represent the + * context. Example usage: NFS server invokes this hook to change the security + * context in its incore inode and on the backing filesystem to a value + * provided by the client on a SETATTR operation. Must be called with + * inode->i_mutex locked. + * + * Return: Returns 0 on success, error on failure. + */ int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen) { return call_int_hook(inode_setsecctx, 0, dentry, ctx, ctxlen); } EXPORT_SYMBOL(security_inode_setsecctx); +/** + * security_inode_getsecctx() - Get the security label of an inode + * @inode: inode + * @ctx: secctx + * @ctxlen: length of secctx + * + * On success, returns 0 and fills out @ctx and @ctxlen with the security + * context for the given @inode. + * + * Return: Returns 0 on success, error on failure. + */ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) { return call_int_hook(inode_getsecctx, -EOPNOTSUPP, inode, ctx, ctxlen); @@ -3766,6 +3969,16 @@ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) EXPORT_SYMBOL(security_inode_getsecctx); #ifdef CONFIG_WATCH_QUEUE +/** + * security_post_notification() - Check if a watch notification can be posted + * @w_cred: credentials of the task that set the watch + * @cred: credentials of the task which triggered the watch + * @n: the notification + * + * Check to see if a watch notification can be posted to a particular queue. + * + * Return: Returns 0 if permission is granted. + */ int security_post_notification(const struct cred *w_cred, const struct cred *cred, struct watch_notification *n) @@ -3775,6 +3988,15 @@ int security_post_notification(const struct cred *w_cred, #endif /* CONFIG_WATCH_QUEUE */ #ifdef CONFIG_KEY_NOTIFICATIONS +/** + * security_watch_key() - Check if a task is allowed to watch for key events + * @key: the key to watch + * + * Check to see if a process is allowed to watch for event notifications from + * a key or keyring. + * + * Return: Returns 0 if permission is granted. + */ int security_watch_key(struct key *key) { return call_int_hook(watch_key, 0, key); @@ -4920,6 +5142,15 @@ void security_bpf_prog_free(struct bpf_prog_aux *aux) } #endif /* CONFIG_BPF_SYSCALL */ +/** + * security_locked_down() - Check if a kernel feature is allowed + * @what: requested kernel feature + * + * Determine whether a kernel feature that potentially enables arbitrary code + * execution in kernel space should be permitted. + * + * Return: Returns 0 if permission is granted. + */ int security_locked_down(enum lockdown_reason what) { return call_int_hook(locked_down, 0, what); From 63c1845bf1a4de21b9cb5a609c96d09e7cf6663b Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Thu, 16 Feb 2023 21:33:20 -0500 Subject: [PATCH 024/291] lsm: styling fixes to security/security.c As we were already making massive changes to security/security.c by moving all of the function header comments above the function definitions, let's take the opportunity to fix various style crimes. Acked-by: Casey Schaufler Signed-off-by: Paul Moore --- security/security.c | 182 ++++++++++++++++++++++++-------------------- 1 file changed, 98 insertions(+), 84 deletions(-) diff --git a/security/security.c b/security/security.c index 190a701fe444..f6482fd7b4b9 100644 --- a/security/security.c +++ b/security/security.c @@ -42,7 +42,7 @@ * all security modules to use the same descriptions for auditing * purposes. */ -const char *const lockdown_reasons[LOCKDOWN_CONFIDENTIALITY_MAX+1] = { +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", @@ -88,7 +88,7 @@ static struct lsm_blob_sizes blob_sizes __lsm_ro_after_init; static __initdata const char *chosen_lsm_order; static __initdata const char *chosen_major_lsm; -static __initconst const char * const builtin_lsm_order = CONFIG_LSM; +static __initconst const char *const builtin_lsm_order = CONFIG_LSM; /* Ordered list of LSMs to initialize. */ static __initdata struct lsm_info **ordered_lsms; @@ -332,7 +332,8 @@ static void __init report_lsm_order(void) pr_info("initializing lsm="); /* Report each enabled LSM name, comma separated. */ - for (early = __start_early_lsm_info; early < __end_early_lsm_info; early++) + for (early = __start_early_lsm_info; + early < __end_early_lsm_info; early++) if (is_enabled(early)) pr_cont("%s%s", first++ == 0 ? "" : ",", early->name); for (lsm = ordered_lsms; *lsm; lsm++) @@ -347,7 +348,7 @@ static void __init ordered_lsm_init(void) struct lsm_info **lsm; ordered_lsms = kcalloc(LSM_COUNT + 1, sizeof(*ordered_lsms), - GFP_KERNEL); + GFP_KERNEL); if (chosen_lsm_order) { if (chosen_major_lsm) { @@ -420,9 +421,9 @@ int __init security_init(void) { struct lsm_info *lsm; - init_debug("legacy security=%s\n", chosen_major_lsm ?: " *unspecified*"); + init_debug("legacy security=%s\n", chosen_major_lsm ? : " *unspecified*"); init_debug(" CONFIG_LSM=%s\n", builtin_lsm_order); - init_debug("boot arg lsm=%s\n", chosen_lsm_order ?: " *unspecified*"); + init_debug("boot arg lsm=%s\n", chosen_lsm_order ? : " *unspecified*"); /* * Append the names of the early LSM modules now that kmalloc() is @@ -510,7 +511,7 @@ static int lsm_append(const char *new, char **result) * Each LSM has to register its hooks with the infrastructure. */ void __init security_add_hooks(struct security_hook_list *hooks, int count, - const char *lsm) + const char *lsm) { int i; @@ -887,12 +888,12 @@ int security_ptrace_traceme(struct task_struct *parent) * Return: Returns 0 if the capability sets were successfully obtained. */ int security_capget(struct task_struct *target, - kernel_cap_t *effective, - kernel_cap_t *inheritable, - kernel_cap_t *permitted) + kernel_cap_t *effective, + kernel_cap_t *inheritable, + kernel_cap_t *permitted) { return call_int_hook(capget, 0, target, - effective, inheritable, permitted); + effective, inheritable, permitted); } /** @@ -914,7 +915,7 @@ int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *permitted) { return call_int_hook(capset, 0, new, old, - effective, inheritable, permitted); + effective, inheritable, permitted); } /** @@ -1348,7 +1349,7 @@ int security_sb_statfs(struct dentry *dentry) * Return: Returns 0 if permission is granted. */ int security_sb_mount(const char *dev_name, const struct path *path, - const char *type, unsigned long flags, void *data) + const char *type, unsigned long flags, void *data) { return call_int_hook(sb_mount, 0, dev_name, path, type, flags, data); } @@ -1376,7 +1377,8 @@ int security_sb_umount(struct vfsmount *mnt, int flags) * * Return: Returns 0 if permission is granted. */ -int security_sb_pivotroot(const struct path *old_path, const struct path *new_path) +int security_sb_pivotroot(const struct path *old_path, + const struct path *new_path) { return call_int_hook(sb_pivotroot, 0, old_path, new_path); } @@ -1393,13 +1395,13 @@ int security_sb_pivotroot(const struct path *old_path, const struct path *new_pa * Return: Returns 0 on success, error on failure. */ int security_sb_set_mnt_opts(struct super_block *sb, - void *mnt_opts, - unsigned long kern_flags, - unsigned long *set_kern_flags) + void *mnt_opts, + unsigned long kern_flags, + unsigned long *set_kern_flags) { return call_int_hook(sb_set_mnt_opts, - mnt_opts ? -EOPNOTSUPP : 0, sb, - mnt_opts, kern_flags, set_kern_flags); + mnt_opts ? -EOPNOTSUPP : 0, sb, + mnt_opts, kern_flags, set_kern_flags); } EXPORT_SYMBOL(security_sb_set_mnt_opts); @@ -1415,12 +1417,12 @@ EXPORT_SYMBOL(security_sb_set_mnt_opts); * Return: Returns 0 on success, error on failure. */ int security_sb_clone_mnt_opts(const struct super_block *oldsb, - struct super_block *newsb, - unsigned long kern_flags, - unsigned long *set_kern_flags) + struct super_block *newsb, + unsigned long kern_flags, + unsigned long *set_kern_flags) { return call_int_hook(sb_clone_mnt_opts, 0, oldsb, newsb, - kern_flags, set_kern_flags); + kern_flags, set_kern_flags); } EXPORT_SYMBOL(security_sb_clone_mnt_opts); @@ -1433,7 +1435,8 @@ EXPORT_SYMBOL(security_sb_clone_mnt_opts); * * Return: Returns 0 if permission is granted. */ -int security_move_mount(const struct path *from_path, const struct path *to_path) +int security_move_mount(const struct path *from_path, + const struct path *to_path) { return call_int_hook(move_mount, 0, from_path, to_path); } @@ -1450,7 +1453,7 @@ int security_move_mount(const struct path *from_path, const struct path *to_path * Return: Returns 0 if permission is granted. */ int security_path_notify(const struct path *path, u64 mask, - unsigned int obj_type) + unsigned int obj_type) { return call_int_hook(path_notify, 0, path, mask, obj_type); } @@ -1506,7 +1509,7 @@ void security_inode_free(struct inode *inode) */ if (inode->i_security) call_rcu((struct rcu_head *)inode->i_security, - inode_free_by_rcu); + inode_free_by_rcu); } /** @@ -1535,7 +1538,8 @@ int security_dentry_init_security(struct dentry *dentry, int mode, /* * Only one module will provide a security context. */ - hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security, list) { + hlist_for_each_entry(hp, &security_hook_heads.dentry_init_security, + list) { rc = hp->hook.dentry_init_security(dentry, mode, name, xattr_name, ctx, ctxlen); if (rc != LSM_RET_DEFAULT(dentry_init_security)) @@ -1565,7 +1569,7 @@ int security_dentry_create_files_as(struct dentry *dentry, int mode, const struct cred *old, struct cred *new) { return call_int_hook(dentry_create_files_as, 0, dentry, mode, - name, old, new); + name, old, new); } EXPORT_SYMBOL(security_dentry_create_files_as); @@ -1607,9 +1611,9 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, memset(new_xattrs, 0, sizeof(new_xattrs)); lsm_xattr = new_xattrs; ret = call_int_hook(inode_init_security, -EOPNOTSUPP, inode, dir, qstr, - &lsm_xattr->name, - &lsm_xattr->value, - &lsm_xattr->value_len); + &lsm_xattr->name, + &lsm_xattr->value, + &lsm_xattr->value_len); if (ret) goto out; @@ -1669,8 +1673,8 @@ EXPORT_SYMBOL(security_old_inode_init_security); * * Return: Returns 0 if permission is granted. */ -int security_path_mknod(const struct path *dir, struct dentry *dentry, umode_t mode, - unsigned int dev) +int security_path_mknod(const struct path *dir, struct dentry *dentry, + umode_t mode, unsigned int dev) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; @@ -1688,7 +1692,8 @@ EXPORT_SYMBOL(security_path_mknod); * * Return: Returns 0 if permission is granted. */ -int security_path_mkdir(const struct path *dir, struct dentry *dentry, umode_t mode) +int security_path_mkdir(const struct path *dir, struct dentry *dentry, + umode_t mode) { if (unlikely(IS_PRIVATE(d_backing_inode(dir->dentry)))) return 0; @@ -1782,11 +1787,12 @@ int security_path_rename(const struct path *old_dir, struct dentry *old_dentry, unsigned int flags) { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) || - (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry))))) + (d_is_positive(new_dentry) && + IS_PRIVATE(d_backing_inode(new_dentry))))) return 0; return call_int_hook(path_rename, 0, old_dir, old_dentry, new_dir, - new_dentry, flags); + new_dentry, flags); } EXPORT_SYMBOL(security_path_rename); @@ -1854,7 +1860,7 @@ int security_path_chroot(const struct path *path) { return call_int_hook(path_chroot, 0, path); } -#endif +#endif /* CONFIG_SECURITY_PATH */ /** * security_inode_create() - Check if creating a file is allowed @@ -1866,7 +1872,8 @@ int security_path_chroot(const struct path *path) * * Return: Returns 0 if permission is granted. */ -int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode) +int security_inode_create(struct inode *dir, struct dentry *dentry, + umode_t mode) { if (unlikely(IS_PRIVATE(dir))) return 0; @@ -1885,7 +1892,7 @@ EXPORT_SYMBOL_GPL(security_inode_create); * Return: Returns 0 if permission is granted. */ int security_inode_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *new_dentry) + struct dentry *new_dentry) { if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)))) return 0; @@ -1919,7 +1926,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) * Return: Returns 0 if permission is granted. */ int security_inode_symlink(struct inode *dir, struct dentry *dentry, - const char *old_name) + const char *old_name) { if (unlikely(IS_PRIVATE(dir))) return 0; @@ -1975,7 +1982,8 @@ int security_inode_rmdir(struct inode *dir, struct dentry *dentry) * * Return: Returns 0 if permission is granted. */ -int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev) +int security_inode_mknod(struct inode *dir, struct dentry *dentry, + umode_t mode, dev_t dev) { if (unlikely(IS_PRIVATE(dir))) return 0; @@ -1995,22 +2003,23 @@ int security_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, * Return: Returns 0 if permission is granted. */ int security_inode_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry, - unsigned int flags) + struct inode *new_dir, struct dentry *new_dentry, + unsigned int flags) { - if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) || - (d_is_positive(new_dentry) && IS_PRIVATE(d_backing_inode(new_dentry))))) + if (unlikely(IS_PRIVATE(d_backing_inode(old_dentry)) || + (d_is_positive(new_dentry) && + IS_PRIVATE(d_backing_inode(new_dentry))))) return 0; if (flags & RENAME_EXCHANGE) { int err = call_int_hook(inode_rename, 0, new_dir, new_dentry, - old_dir, old_dentry); + old_dir, old_dentry); if (err) return err; } return call_int_hook(inode_rename, 0, old_dir, old_dentry, - new_dir, new_dentry); + new_dir, new_dentry); } /** @@ -2370,7 +2379,8 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, * Only one module will provide an attribute with a given name. */ hlist_for_each_entry(hp, &security_hook_heads.inode_getsecurity, list) { - rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer, alloc); + rc = hp->hook.inode_getsecurity(idmap, inode, name, buffer, + alloc); if (rc != LSM_RET_DEFAULT(inode_getsecurity)) return rc; } @@ -2392,7 +2402,8 @@ int security_inode_getsecurity(struct mnt_idmap *idmap, * * Return: Returns 0 on success. */ -int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) +int security_inode_setsecurity(struct inode *inode, const char *name, + const void *value, size_t size, int flags) { struct security_hook_list *hp; int rc; @@ -2404,7 +2415,7 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void */ hlist_for_each_entry(hp, &security_hook_heads.inode_setsecurity, list) { rc = hp->hook.inode_setsecurity(inode, name, value, size, - flags); + flags); if (rc != LSM_RET_DEFAULT(inode_setsecurity)) return rc; } @@ -2424,7 +2435,8 @@ int security_inode_setsecurity(struct inode *inode, const char *name, const void * * Return: Returns number of bytes used/required on success. */ -int security_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size) +int security_inode_listsecurity(struct inode *inode, + char *buffer, size_t buffer_size) { if (unlikely(IS_PRIVATE(inode))) return 0; @@ -2486,7 +2498,7 @@ int security_inode_copy_up_xattr(const char *name) * any other error code incase of an error. */ hlist_for_each_entry(hp, - &security_hook_heads.inode_copy_up_xattr, list) { + &security_hook_heads.inode_copy_up_xattr, list) { rc = hp->hook.inode_copy_up_xattr(name); if (rc != LSM_RET_DEFAULT(inode_copy_up_xattr)) return rc; @@ -2646,7 +2658,7 @@ static inline unsigned long mmap_prot(struct file *file, unsigned long prot) * Return: Returns 0 if permission is granted. */ int security_mmap_file(struct file *file, unsigned long prot, - unsigned long flags) + unsigned long flags) { unsigned long prot_adj = mmap_prot(file, prot); int ret; @@ -2681,7 +2693,7 @@ int security_mmap_addr(unsigned long addr) * Return: Returns 0 if permission is granted. */ int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, - unsigned long prot) + unsigned long prot) { int ret; @@ -2754,7 +2766,7 @@ void security_file_set_fowner(struct file *file) * Return: Returns 0 if permission is granted. */ int security_file_send_sigiotask(struct task_struct *tsk, - struct fown_struct *fown, int sig) + struct fown_struct *fown, int sig) { return call_int_hook(file_send_sigiotask, 0, tsk, fown, sig); } @@ -3118,7 +3130,7 @@ int security_task_fix_setuid(struct cred *new, const struct cred *old, * Return: Returns 0 on success. */ int security_task_fix_setgid(struct cred *new, const struct cred *old, - int flags) + int flags) { return call_int_hook(task_fix_setgid, 0, new, old, flags); } @@ -3282,7 +3294,7 @@ int security_task_prlimit(const struct cred *cred, const struct cred *tcred, * Return: Returns 0 if permission is granted. */ int security_task_setrlimit(struct task_struct *p, unsigned int resource, - struct rlimit *new_rlim) + struct rlimit *new_rlim) { return call_int_hook(task_setrlimit, 0, p, resource, new_rlim); } @@ -3343,7 +3355,7 @@ int security_task_movememory(struct task_struct *p) * Return: Returns 0 if permission is granted. */ int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, - int sig, const struct cred *cred) + int sig, const struct cred *cred) { return call_int_hook(task_kill, 0, p, info, sig, cred); } @@ -3363,7 +3375,7 @@ int security_task_kill(struct task_struct *p, struct kernel_siginfo *info, * to cause prctl() to return immediately with that value. */ int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, - unsigned long arg4, unsigned long arg5) + unsigned long arg4, unsigned long arg5) { int thisrc; int rc = LSM_RET_DEFAULT(task_prctl); @@ -3545,7 +3557,7 @@ int security_msg_queue_msgctl(struct kern_ipc_perm *msq, int cmd) * Return: Returns 0 if permission is granted. */ int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, - struct msg_msg *msg, int msqflg) + struct msg_msg *msg, int msqflg) { return call_int_hook(msg_queue_msgsnd, 0, msq, msg, msqflg); } @@ -3566,7 +3578,7 @@ int security_msg_queue_msgsnd(struct kern_ipc_perm *msq, * Return: Returns 0 if permission is granted. */ int security_msg_queue_msgrcv(struct kern_ipc_perm *msq, struct msg_msg *msg, - struct task_struct *target, long type, int mode) + struct task_struct *target, long type, int mode) { return call_int_hook(msg_queue_msgrcv, 0, msq, msg, target, type, mode); } @@ -3649,7 +3661,8 @@ int security_shm_shmctl(struct kern_ipc_perm *shp, int cmd) * * Return: Returns 0 if permission is granted. */ -int security_shm_shmat(struct kern_ipc_perm *shp, char __user *shmaddr, int shmflg) +int security_shm_shmat(struct kern_ipc_perm *shp, + char __user *shmaddr, int shmflg) { return call_int_hook(shm_shmat, 0, shp, shmaddr, shmflg); } @@ -3732,7 +3745,7 @@ int security_sem_semctl(struct kern_ipc_perm *sma, int cmd) * Return: Returns 0 if permission is granted. */ int security_sem_semop(struct kern_ipc_perm *sma, struct sembuf *sops, - unsigned nsops, int alter) + unsigned nsops, int alter) { return call_int_hook(sem_semop, 0, sma, sops, nsops, alter); } @@ -4001,7 +4014,7 @@ int security_watch_key(struct key *key) { return call_int_hook(watch_key, 0, key); } -#endif +#endif /* CONFIG_KEY_NOTIFICATIONS */ #ifdef CONFIG_SECURITY_NETWORK /** @@ -4025,7 +4038,8 @@ int security_watch_key(struct key *key) * * Return: Returns 0 if permission is granted. */ -int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) +int security_unix_stream_connect(struct sock *sock, struct sock *other, + struct sock *newsk) { return call_int_hook(unix_stream_connect, 0, sock, other, newsk); } @@ -4095,7 +4109,7 @@ int security_socket_post_create(struct socket *sock, int family, int type, int protocol, int kern) { return call_int_hook(socket_post_create, 0, sock, family, type, - protocol, kern); + protocol, kern); } /** @@ -4126,7 +4140,8 @@ EXPORT_SYMBOL(security_socket_socketpair); * * Return: Returns 0 if permission is granted. */ -int security_socket_bind(struct socket *sock, struct sockaddr *address, int addrlen) +int security_socket_bind(struct socket *sock, + struct sockaddr *address, int addrlen) { return call_int_hook(socket_bind, 0, sock, address, addrlen); } @@ -4142,7 +4157,8 @@ int security_socket_bind(struct socket *sock, struct sockaddr *address, int addr * * Return: Returns 0 if permission is granted. */ -int security_socket_connect(struct socket *sock, struct sockaddr *address, int addrlen) +int security_socket_connect(struct socket *sock, + struct sockaddr *address, int addrlen) { return call_int_hook(socket_connect, 0, sock, address, addrlen); } @@ -4336,7 +4352,8 @@ int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval, * * Return: Returns 0 on success, error on failure. */ -int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid) +int security_socket_getpeersec_dgram(struct socket *sock, + struct sk_buff *skb, u32 *secid) { return call_int_hook(socket_getpeersec_dgram, -ENOPROTOOPT, sock, skb, secid); @@ -4428,7 +4445,7 @@ EXPORT_SYMBOL(security_sock_graft); * Return: Returns 0 if permission is granted. */ int security_inet_conn_request(const struct sock *sk, - struct sk_buff *skb, struct request_sock *req) + struct sk_buff *skb, struct request_sock *req) { return call_int_hook(inet_conn_request, 0, sk, skb, req); } @@ -4442,7 +4459,7 @@ EXPORT_SYMBOL(security_inet_conn_request); * Set that LSM state of @sock using the LSM state from @req. */ void security_inet_csk_clone(struct sock *newsk, - const struct request_sock *req) + const struct request_sock *req) { call_void_hook(inet_csk_clone, newsk, req); } @@ -4455,7 +4472,7 @@ void security_inet_csk_clone(struct sock *newsk, * Update @sock's LSM state to represent a new connection from @skb. */ void security_inet_conn_established(struct sock *sk, - struct sk_buff *skb) + struct sk_buff *skb) { call_void_hook(inet_conn_established, sk, skb); } @@ -4591,7 +4608,8 @@ EXPORT_SYMBOL(security_tun_dev_open); * * Return: Returns 0 on success, error on failure. */ -int security_sctp_assoc_request(struct sctp_association *asoc, struct sk_buff *skb) +int security_sctp_assoc_request(struct sctp_association *asoc, + struct sk_buff *skb) { return call_int_hook(sctp_assoc_request, 0, asoc, skb); } @@ -4656,7 +4674,6 @@ EXPORT_SYMBOL(security_sctp_assoc_established); #endif /* CONFIG_SECURITY_NETWORK */ #ifdef CONFIG_SECURITY_INFINIBAND - /** * security_ib_pkey_access() - Check if access to an IB pkey is allowed * @sec: LSM blob @@ -4683,9 +4700,11 @@ EXPORT_SYMBOL(security_ib_pkey_access); * * Return: Returns 0 if permission is granted. */ -int security_ib_endport_manage_subnet(void *sec, const char *dev_name, u8 port_num) +int security_ib_endport_manage_subnet(void *sec, + const char *dev_name, u8 port_num) { - return call_int_hook(ib_endport_manage_subnet, 0, sec, dev_name, port_num); + return call_int_hook(ib_endport_manage_subnet, 0, sec, + dev_name, port_num); } EXPORT_SYMBOL(security_ib_endport_manage_subnet); @@ -4717,7 +4736,6 @@ EXPORT_SYMBOL(security_ib_free_security); #endif /* CONFIG_SECURITY_INFINIBAND */ #ifdef CONFIG_SECURITY_NETWORK_XFRM - /** * security_xfrm_policy_alloc() - Allocate a xfrm policy LSM blob * @ctxp: xfrm security context being added to the SPD @@ -4748,7 +4766,7 @@ EXPORT_SYMBOL(security_xfrm_policy_alloc); * Return: Return 0 if operation was successful. */ int security_xfrm_policy_clone(struct xfrm_sec_ctx *old_ctx, - struct xfrm_sec_ctx **new_ctxp) + struct xfrm_sec_ctx **new_ctxp) { return call_int_hook(xfrm_policy_clone_security, 0, old_ctx, new_ctxp); } @@ -4883,7 +4901,7 @@ int security_xfrm_state_pol_flow_match(struct xfrm_state *x, * using the macro */ hlist_for_each_entry(hp, &security_hook_heads.xfrm_state_pol_flow_match, - list) { + list) { rc = hp->hook.xfrm_state_pol_flow_match(x, xp, flic); break; } @@ -4907,16 +4925,14 @@ int security_xfrm_decode_session(struct sk_buff *skb, u32 *secid) void security_skb_classify_flow(struct sk_buff *skb, struct flowi_common *flic) { int rc = call_int_hook(xfrm_decode_session, 0, skb, &flic->flowic_secid, - 0); + 0); BUG_ON(rc); } EXPORT_SYMBOL(security_skb_classify_flow); - #endif /* CONFIG_SECURITY_NETWORK_XFRM */ #ifdef CONFIG_KEYS - /** * security_key_alloc() - Allocate and initialize a kernel key LSM blob * @key: key @@ -4979,11 +4995,9 @@ int security_key_getsecurity(struct key *key, char **_buffer) *_buffer = NULL; return call_int_hook(key_getsecurity, 0, key, _buffer); } - #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT - /** * security_audit_rule_init() - Allocate and init an LSM audit rule struct * @field: audit action From 60684c2bd35064043360e6f716d1b7c20e967b7d Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Mon, 27 Feb 2023 12:12:45 +0100 Subject: [PATCH 025/291] kunit: tool: Add support for m68k under QEMU Add basic support to run m68k under QEMU via kunit_tool. Signed-off-by: Geert Uytterhoeven Reviewed-by: David Gow Signed-off-by: Shuah Khan --- tools/testing/kunit/qemu_configs/m68k.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tools/testing/kunit/qemu_configs/m68k.py diff --git a/tools/testing/kunit/qemu_configs/m68k.py b/tools/testing/kunit/qemu_configs/m68k.py new file mode 100644 index 000000000000..287fc386f8a7 --- /dev/null +++ b/tools/testing/kunit/qemu_configs/m68k.py @@ -0,0 +1,10 @@ +# SPDX-License-Identifier: GPL-2.0-only +from ..qemu_config import QemuArchParams + +QEMU_ARCH = QemuArchParams(linux_arch='m68k', + kconfig=''' +CONFIG_VIRT=y''', + qemu_arch='m68k', + kernel_path='vmlinux', + kernel_command_line='console=hvc0', + extra_qemu_params=['-machine', 'virt']) From e1e17d7debf486fd3b757df9e009b8d109e4be43 Mon Sep 17 00:00:00 2001 From: Sukrut Bellary Date: Sun, 26 Feb 2023 16:21:55 -0800 Subject: [PATCH 026/291] kselftest: amd-pstate: Fix spelling mistakes Fix spelling mistakes in run.sh "drvier" => "driver" and in gitsource.sh "senconds" => "seconds". Signed-off-by: Sukrut Bellary Signed-off-by: Shuah Khan --- tools/testing/selftests/amd-pstate/gitsource.sh | 4 ++-- tools/testing/selftests/amd-pstate/run.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/testing/selftests/amd-pstate/gitsource.sh b/tools/testing/selftests/amd-pstate/gitsource.sh index dbc1fe45599d..5f2171f0116d 100755 --- a/tools/testing/selftests/amd-pstate/gitsource.sh +++ b/tools/testing/selftests/amd-pstate/gitsource.sh @@ -117,7 +117,7 @@ parse_gitsource() printf "Gitsource-$1-#$2 power consumption(J): $en_sum\n" | tee -a $OUTFILE_GIT.result # Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t - # senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), + # seconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), # and t is time measured in seconds(s). This means that performance per watt becomes # 1/t 1/t 1 # ----- = ----- = --- @@ -175,7 +175,7 @@ gather_gitsource() printf "Gitsource-$1 avg power consumption(J): $avg_en\n" | tee -a $OUTFILE_GIT.result # Permance is the number of run gitsource per second, denoted 1/t, where 1 is the number of run gitsource in t - # senconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), + # seconds. It is well known that P=E/t, where P is power measured in watts(W), E is energy measured in joules(J), # and t is time measured in seconds(s). This means that performance per watt becomes # 1/t 1/t 1 # ----- = ----- = --- diff --git a/tools/testing/selftests/amd-pstate/run.sh b/tools/testing/selftests/amd-pstate/run.sh index 57cad57e59c0..de4d8e9c9565 100755 --- a/tools/testing/selftests/amd-pstate/run.sh +++ b/tools/testing/selftests/amd-pstate/run.sh @@ -244,7 +244,7 @@ prerequisite() if [ "$scaling_driver" != "$CURRENT_TEST" ]; then echo "$0 # Skipped: Test can only run on $CURRENT_TEST driver or run comparative test." echo "$0 # Please set X86_AMD_PSTATE enabled or run comparative test." - echo "$0 # Current cpufreq scaling drvier is $scaling_driver." + echo "$0 # Current cpufreq scaling driver is $scaling_driver." exit $ksft_skip fi else @@ -252,7 +252,7 @@ prerequisite() "tbench" | "gitsource") if [ "$scaling_driver" != "$COMPARATIVE_TEST" ]; then echo "$0 # Skipped: Comparison test can only run on $COMPARISON_TEST driver." - echo "$0 # Current cpufreq scaling drvier is $scaling_driver." + echo "$0 # Current cpufreq scaling driver is $scaling_driver." exit $ksft_skip fi ;; From d70e2ecbc726a0ee794b72365730a8dbc9866080 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Sun, 26 Feb 2023 17:17:00 -0800 Subject: [PATCH 027/291] instrumented.h: Fix all kernel-doc format warnings Fix 26 kernel-doc notation warnings by converting the function documentation to kernel-doc format. Warning example: instrumented.h:155: warning: Function parameter or member 'to' not described in 'instrument_copy_from_user_after' instrumented.h:155: warning: Function parameter or member 'from' not described in 'instrument_copy_from_user_after' instrumented.h:155: warning: Function parameter or member 'n' not described in 'instrument_copy_from_user_after' instrumented.h:155: warning: Function parameter or member 'left' not described in 'instrument_copy_from_user_after' Fixes: 36e4d4dd4fc4 ("include/linux: Add instrumented.h infrastructure") Fixes: 00047c2e6d7c ("instrumented.h: Introduce read-write instrumentation hooks") Fixes: 33b75c1d884e ("instrumented.h: allow instrumenting both sides of copy_from_user()") Fixes: 888f84a6da4d ("x86: asm: instrument usercopy in get_user() and put_user()") Signed-off-by: Randy Dunlap Cc: Arnd Bergmann Cc: Marco Elver Cc: Alexander Potapenko Cc: Andrew Morton Cc: Dmitry Vyukov Cc: Paul E. McKenney Cc: Ingo Molnar Reviewed-by: Marco Elver Signed-off-by: Paul E. McKenney --- include/linux/instrumented.h | 63 +++++++++++++++--------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/include/linux/instrumented.h b/include/linux/instrumented.h index 501fa8486749..1b608e00290a 100644 --- a/include/linux/instrumented.h +++ b/include/linux/instrumented.h @@ -15,12 +15,11 @@ /** * instrument_read - instrument regular read access + * @v: address of access + * @size: size of access * * Instrument a regular read access. The instrumentation should be inserted * before the actual read happens. - * - * @ptr address of access - * @size size of access */ static __always_inline void instrument_read(const volatile void *v, size_t size) { @@ -30,12 +29,11 @@ static __always_inline void instrument_read(const volatile void *v, size_t size) /** * instrument_write - instrument regular write access + * @v: address of access + * @size: size of access * * Instrument a regular write access. The instrumentation should be inserted * before the actual write happens. - * - * @ptr address of access - * @size size of access */ static __always_inline void instrument_write(const volatile void *v, size_t size) { @@ -45,12 +43,11 @@ static __always_inline void instrument_write(const volatile void *v, size_t size /** * instrument_read_write - instrument regular read-write access + * @v: address of access + * @size: size of access * * Instrument a regular write access. The instrumentation should be inserted * before the actual write happens. - * - * @ptr address of access - * @size size of access */ static __always_inline void instrument_read_write(const volatile void *v, size_t size) { @@ -60,12 +57,11 @@ static __always_inline void instrument_read_write(const volatile void *v, size_t /** * instrument_atomic_read - instrument atomic read access + * @v: address of access + * @size: size of access * * Instrument an atomic read access. The instrumentation should be inserted * before the actual read happens. - * - * @ptr address of access - * @size size of access */ static __always_inline void instrument_atomic_read(const volatile void *v, size_t size) { @@ -75,12 +71,11 @@ static __always_inline void instrument_atomic_read(const volatile void *v, size_ /** * instrument_atomic_write - instrument atomic write access + * @v: address of access + * @size: size of access * * Instrument an atomic write access. The instrumentation should be inserted * before the actual write happens. - * - * @ptr address of access - * @size size of access */ static __always_inline void instrument_atomic_write(const volatile void *v, size_t size) { @@ -90,12 +85,11 @@ static __always_inline void instrument_atomic_write(const volatile void *v, size /** * instrument_atomic_read_write - instrument atomic read-write access + * @v: address of access + * @size: size of access * * Instrument an atomic read-write access. The instrumentation should be * inserted before the actual write happens. - * - * @ptr address of access - * @size size of access */ static __always_inline void instrument_atomic_read_write(const volatile void *v, size_t size) { @@ -105,13 +99,12 @@ static __always_inline void instrument_atomic_read_write(const volatile void *v, /** * instrument_copy_to_user - instrument reads of copy_to_user + * @to: destination address + * @from: source address + * @n: number of bytes to copy * * Instrument reads from kernel memory, that are due to copy_to_user (and * variants). The instrumentation must be inserted before the accesses. - * - * @to destination address - * @from source address - * @n number of bytes to copy */ static __always_inline void instrument_copy_to_user(void __user *to, const void *from, unsigned long n) @@ -123,13 +116,12 @@ instrument_copy_to_user(void __user *to, const void *from, unsigned long n) /** * instrument_copy_from_user_before - add instrumentation before copy_from_user + * @to: destination address + * @from: source address + * @n: number of bytes to copy * * Instrument writes to kernel memory, that are due to copy_from_user (and * variants). The instrumentation should be inserted before the accesses. - * - * @to destination address - * @from source address - * @n number of bytes to copy */ static __always_inline void instrument_copy_from_user_before(const void *to, const void __user *from, unsigned long n) @@ -140,14 +132,13 @@ instrument_copy_from_user_before(const void *to, const void __user *from, unsign /** * instrument_copy_from_user_after - add instrumentation after copy_from_user + * @to: destination address + * @from: source address + * @n: number of bytes to copy + * @left: number of bytes not copied (as returned by copy_from_user) * * Instrument writes to kernel memory, that are due to copy_from_user (and * variants). The instrumentation should be inserted after the accesses. - * - * @to destination address - * @from source address - * @n number of bytes to copy - * @left number of bytes not copied (as returned by copy_from_user) */ static __always_inline void instrument_copy_from_user_after(const void *to, const void __user *from, @@ -158,12 +149,11 @@ instrument_copy_from_user_after(const void *to, const void __user *from, /** * instrument_get_user() - add instrumentation to get_user()-like macros + * @to: destination variable, may not be address-taken * * get_user() and friends are fragile, so it may depend on the implementation * whether the instrumentation happens before or after the data is copied from * the userspace. - * - * @to destination variable, may not be address-taken */ #define instrument_get_user(to) \ ({ \ @@ -175,14 +165,13 @@ instrument_copy_from_user_after(const void *to, const void __user *from, /** * instrument_put_user() - add instrumentation to put_user()-like macros + * @from: source address + * @ptr: userspace pointer to copy to + * @size: number of bytes to copy * * put_user() and friends are fragile, so it may depend on the implementation * whether the instrumentation happens before or after the data is copied from * the userspace. - * - * @from source address - * @ptr userspace pointer to copy to - * @size number of bytes to copy */ #define instrument_put_user(from, ptr, size) \ ({ \ From b63343207da21179d82df933f42a1725a53b9a63 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 Feb 2023 19:02:35 +0000 Subject: [PATCH 028/291] locktorture: Add nested_[un]lock() hooks and nlocks parameter In order to extend locktorture to support lock nesting, add nested_lock() and nested_unlock() hooks to the torture ops. These take a 32bit lockset mask which is generated at random, so some number of locks will be taken before the main lock is taken and released afterwards. Additionally, add nested_locks module parameter to allow specifying the number of nested locks to be used. This has been helpful to uncover issues in the proxy-exec series development. This was inspired by locktorture extensions originally implemented by Connor O'Brien, for stress testing the proxy-execution series: https://lore.kernel.org/lkml/20221003214501.2050087-12-connoro@google.com/ Cc: Davidlohr Bueso Cc: "Paul E. McKenney" Cc: Josh Triplett Cc: Joel Fernandes Cc: Juri Lelli Cc: Valentin Schneider Cc: Dietmar Eggemann Cc: kernel-team@android.com Reviewed-by: Davidlohr Bueso Co-developed-by: Connor O'Brien Signed-off-by: Connor O'Brien Signed-off-by: John Stultz Signed-off-by: Paul E. McKenney --- kernel/locking/locktorture.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index f04b1978899d..a8519af25ece 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -51,6 +51,9 @@ torture_param(int, rt_boost, 2, torture_param(int, rt_boost_factor, 50, "A factor determining how often rt-boost happens."); torture_param(int, verbose, 1, "Enable verbose debugging printk()s"); +torture_param(int, nested_locks, 0, "Number of nested locks (max = 8)"); +/* Going much higher trips "BUG: MAX_LOCKDEP_CHAIN_HLOCKS too low!" errors */ +#define MAX_NESTED_LOCKS 8 static char *torture_type = "spin_lock"; module_param(torture_type, charp, 0444); @@ -79,10 +82,12 @@ static void lock_torture_cleanup(void); struct lock_torture_ops { void (*init)(void); void (*exit)(void); + int (*nested_lock)(int tid, u32 lockset); int (*writelock)(int tid); void (*write_delay)(struct torture_random_state *trsp); void (*task_boost)(struct torture_random_state *trsp); void (*writeunlock)(int tid); + void (*nested_unlock)(int tid, u32 lockset); int (*readlock)(int tid); void (*read_delay)(struct torture_random_state *trsp); void (*readunlock)(int tid); @@ -684,6 +689,7 @@ static int lock_torture_writer(void *arg) struct lock_stress_stats *lwsp = arg; int tid = lwsp - cxt.lwsa; DEFINE_TORTURE_RANDOM(rand); + u32 lockset_mask; VERBOSE_TOROUT_STRING("lock_torture_writer task started"); set_user_nice(current, MAX_NICE); @@ -692,7 +698,10 @@ static int lock_torture_writer(void *arg) if ((torture_random(&rand) & 0xfffff) == 0) schedule_timeout_uninterruptible(1); + lockset_mask = torture_random(&rand); cxt.cur_ops->task_boost(&rand); + if (cxt.cur_ops->nested_lock) + cxt.cur_ops->nested_lock(tid, lockset_mask); cxt.cur_ops->writelock(tid); if (WARN_ON_ONCE(lock_is_write_held)) lwsp->n_lock_fail++; @@ -705,6 +714,8 @@ static int lock_torture_writer(void *arg) lock_is_write_held = false; WRITE_ONCE(last_lock_release, jiffies); cxt.cur_ops->writeunlock(tid); + if (cxt.cur_ops->nested_unlock) + cxt.cur_ops->nested_unlock(tid, lockset_mask); stutter_wait("lock_torture_writer"); } while (!torture_must_stop()); @@ -845,11 +856,11 @@ lock_torture_print_module_parms(struct lock_torture_ops *cur_ops, const char *tag) { pr_alert("%s" TORTURE_FLAG - "--- %s%s: nwriters_stress=%d nreaders_stress=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n", + "--- %s%s: nwriters_stress=%d nreaders_stress=%d nested_locks=%d stat_interval=%d verbose=%d shuffle_interval=%d stutter=%d shutdown_secs=%d onoff_interval=%d onoff_holdoff=%d\n", torture_type, tag, cxt.debug_lock ? " [debug]": "", - cxt.nrealwriters_stress, cxt.nrealreaders_stress, stat_interval, - verbose, shuffle_interval, stutter, shutdown_secs, - onoff_interval, onoff_holdoff); + cxt.nrealwriters_stress, cxt.nrealreaders_stress, + nested_locks, stat_interval, verbose, shuffle_interval, + stutter, shutdown_secs, onoff_interval, onoff_holdoff); } static void lock_torture_cleanup(void) @@ -1068,6 +1079,10 @@ static int __init lock_torture_init(void) } } + /* cap nested_locks to MAX_NESTED_LOCKS */ + if (nested_locks > MAX_NESTED_LOCKS) + nested_locks = MAX_NESTED_LOCKS; + if (cxt.cur_ops->readlock) { reader_tasks = kcalloc(cxt.nrealreaders_stress, sizeof(reader_tasks[0]), From 3e5aeaf53422bdd79fecf89aa160f048114e013c Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 Feb 2023 19:02:36 +0000 Subject: [PATCH 029/291] locktorture: Add nested locking to mutex torture tests This patch adds randomized nested locking to the mutex torture tests, as well as new LOCK08 config files for testing mutexes with nested locking Cc: Davidlohr Bueso Cc: "Paul E. McKenney" Cc: Josh Triplett Cc: Joel Fernandes Cc: Juri Lelli Cc: Valentin Schneider Cc: Dietmar Eggemann Cc: kernel-team@android.com Reviewed-by: Davidlohr Bueso Co-developed-by: Connor O'Brien Signed-off-by: Connor O'Brien Signed-off-by: John Stultz Signed-off-by: Paul E. McKenney --- kernel/locking/locktorture.c | 35 +++++++++++++++++++ .../selftests/rcutorture/configs/lock/CFLIST | 1 + .../selftests/rcutorture/configs/lock/LOCK08 | 6 ++++ .../rcutorture/configs/lock/LOCK08.boot | 1 + 4 files changed, 43 insertions(+) create mode 100644 tools/testing/selftests/rcutorture/configs/lock/LOCK08 create mode 100644 tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index a8519af25ece..a4d15a9a9d7f 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -370,6 +370,28 @@ static struct lock_torture_ops rw_lock_irq_ops = { }; static DEFINE_MUTEX(torture_mutex); +static struct mutex torture_nested_mutexes[MAX_NESTED_LOCKS]; +static struct lock_class_key nested_mutex_keys[MAX_NESTED_LOCKS]; + +static void torture_mutex_init(void) +{ + int i; + + for (i = 0; i < MAX_NESTED_LOCKS; i++) + __mutex_init(&torture_nested_mutexes[i], __func__, + &nested_mutex_keys[i]); +} + +static int torture_mutex_nested_lock(int tid __maybe_unused, + u32 lockset) +{ + int i; + + for (i = 0; i < nested_locks; i++) + if (lockset & (1 << i)) + mutex_lock(&torture_nested_mutexes[i]); + return 0; +} static int torture_mutex_lock(int tid __maybe_unused) __acquires(torture_mutex) @@ -398,11 +420,24 @@ __releases(torture_mutex) mutex_unlock(&torture_mutex); } +static void torture_mutex_nested_unlock(int tid __maybe_unused, + u32 lockset) +{ + int i; + + for (i = nested_locks - 1; i >= 0; i--) + if (lockset & (1 << i)) + mutex_unlock(&torture_nested_mutexes[i]); +} + static struct lock_torture_ops mutex_lock_ops = { + .init = torture_mutex_init, + .nested_lock = torture_mutex_nested_lock, .writelock = torture_mutex_lock, .write_delay = torture_mutex_delay, .task_boost = torture_rt_boost, .writeunlock = torture_mutex_unlock, + .nested_unlock = torture_mutex_nested_unlock, .readlock = NULL, .read_delay = NULL, .readunlock = NULL, diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST index 41bae5824339..a48bba0d35a6 100644 --- a/tools/testing/selftests/rcutorture/configs/lock/CFLIST +++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST @@ -5,3 +5,4 @@ LOCK04 LOCK05 LOCK06 LOCK07 +LOCK08 diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK08 b/tools/testing/selftests/rcutorture/configs/lock/LOCK08 new file mode 100644 index 000000000000..1d1da1477fc3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK08 @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot new file mode 100644 index 000000000000..b8b6caebb89e --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK08.boot @@ -0,0 +1 @@ +locktorture.torture_type=mutex_lock locktorture.nested_locks=8 From ae4823e427954d30ab393888a334f9d1fd8cd597 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 Feb 2023 19:02:37 +0000 Subject: [PATCH 030/291] locktorture: Add nested locking to rtmutex torture tests This patch adds randomized nested locking to the rtmutex torture tests. Additionally it adds LOCK09 config files for testing rtmutexes with nested locking. Cc: Davidlohr Bueso Cc: "Paul E. McKenney" Cc: Josh Triplett Cc: Joel Fernandes Cc: Juri Lelli Cc: Valentin Schneider Cc: Dietmar Eggemann Cc: kernel-team@android.com Reviewed-by: Davidlohr Bueso Co-developed-by: Connor O'Brien Signed-off-by: Connor O'Brien Signed-off-by: John Stultz Signed-off-by: Paul E. McKenney --- kernel/locking/locktorture.c | 35 +++++++++++++++++++ .../selftests/rcutorture/configs/lock/CFLIST | 1 + .../selftests/rcutorture/configs/lock/LOCK09 | 6 ++++ .../rcutorture/configs/lock/LOCK09.boot | 1 + 4 files changed, 43 insertions(+) create mode 100644 tools/testing/selftests/rcutorture/configs/lock/LOCK09 create mode 100644 tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index a4d15a9a9d7f..c7f264aed5b7 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -544,6 +544,28 @@ static struct lock_torture_ops ww_mutex_lock_ops = { #ifdef CONFIG_RT_MUTEXES static DEFINE_RT_MUTEX(torture_rtmutex); +static struct rt_mutex torture_nested_rtmutexes[MAX_NESTED_LOCKS]; +static struct lock_class_key nested_rtmutex_keys[MAX_NESTED_LOCKS]; + +static void torture_rtmutex_init(void) +{ + int i; + + for (i = 0; i < MAX_NESTED_LOCKS; i++) + __rt_mutex_init(&torture_nested_rtmutexes[i], __func__, + &nested_rtmutex_keys[i]); +} + +static int torture_rtmutex_nested_lock(int tid __maybe_unused, + u32 lockset) +{ + int i; + + for (i = 0; i < nested_locks; i++) + if (lockset & (1 << i)) + rt_mutex_lock(&torture_nested_rtmutexes[i]); + return 0; +} static int torture_rtmutex_lock(int tid __maybe_unused) __acquires(torture_rtmutex) @@ -585,11 +607,24 @@ static void torture_rt_boost_rtmutex(struct torture_random_state *trsp) __torture_rt_boost(trsp); } +static void torture_rtmutex_nested_unlock(int tid __maybe_unused, + u32 lockset) +{ + int i; + + for (i = nested_locks - 1; i >= 0; i--) + if (lockset & (1 << i)) + rt_mutex_unlock(&torture_nested_rtmutexes[i]); +} + static struct lock_torture_ops rtmutex_lock_ops = { + .init = torture_rtmutex_init, + .nested_lock = torture_rtmutex_nested_lock, .writelock = torture_rtmutex_lock, .write_delay = torture_rtmutex_delay, .task_boost = torture_rt_boost_rtmutex, .writeunlock = torture_rtmutex_unlock, + .nested_unlock = torture_rtmutex_nested_unlock, .readlock = NULL, .read_delay = NULL, .readunlock = NULL, diff --git a/tools/testing/selftests/rcutorture/configs/lock/CFLIST b/tools/testing/selftests/rcutorture/configs/lock/CFLIST index a48bba0d35a6..28e23d05d5a5 100644 --- a/tools/testing/selftests/rcutorture/configs/lock/CFLIST +++ b/tools/testing/selftests/rcutorture/configs/lock/CFLIST @@ -6,3 +6,4 @@ LOCK05 LOCK06 LOCK07 LOCK08 +LOCK09 diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK09 b/tools/testing/selftests/rcutorture/configs/lock/LOCK09 new file mode 100644 index 000000000000..1d1da1477fc3 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK09 @@ -0,0 +1,6 @@ +CONFIG_SMP=y +CONFIG_NR_CPUS=4 +CONFIG_HOTPLUG_CPU=y +CONFIG_PREEMPT_NONE=n +CONFIG_PREEMPT_VOLUNTARY=n +CONFIG_PREEMPT=y diff --git a/tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot b/tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot new file mode 100644 index 000000000000..fd5eff148a93 --- /dev/null +++ b/tools/testing/selftests/rcutorture/configs/lock/LOCK09.boot @@ -0,0 +1 @@ +locktorture.torture_type=rtmutex_lock locktorture.nested_locks=8 From 45bcf0bd8cbe163c5aec18570b6befd2193f1a57 Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 21 Feb 2023 19:02:38 +0000 Subject: [PATCH 031/291] locktorture: With nested locks, occasionally skip main lock If we're using nested locking to stress things, occasionally skip taking the main lock, so that we can get some different contention patterns between the writers (to hopefully get two disjoint blocked trees) Cc: Davidlohr Bueso Cc: "Paul E. McKenney" Cc: Josh Triplett Cc: Joel Fernandes Cc: Juri Lelli Cc: Valentin Schneider Cc: Dietmar Eggemann Cc: kernel-team@android.com Co-developed-by: Connor O'Brien Signed-off-by: Connor O'Brien Signed-off-by: John Stultz Signed-off-by: Paul E. McKenney --- kernel/locking/locktorture.c | 37 ++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index c7f264aed5b7..9425aff08936 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -760,6 +760,7 @@ static int lock_torture_writer(void *arg) int tid = lwsp - cxt.lwsa; DEFINE_TORTURE_RANDOM(rand); u32 lockset_mask; + bool skip_main_lock; VERBOSE_TOROUT_STRING("lock_torture_writer task started"); set_user_nice(current, MAX_NICE); @@ -769,21 +770,37 @@ static int lock_torture_writer(void *arg) schedule_timeout_uninterruptible(1); lockset_mask = torture_random(&rand); + /* + * When using nested_locks, we want to occasionally + * skip the main lock so we can avoid always serializing + * the lock chains on that central lock. By skipping the + * main lock occasionally, we can create different + * contention patterns (allowing for multiple disjoint + * blocked trees) + */ + skip_main_lock = (nested_locks && + !(torture_random(&rand) % 100)); + cxt.cur_ops->task_boost(&rand); if (cxt.cur_ops->nested_lock) cxt.cur_ops->nested_lock(tid, lockset_mask); - cxt.cur_ops->writelock(tid); - if (WARN_ON_ONCE(lock_is_write_held)) - lwsp->n_lock_fail++; - lock_is_write_held = true; - if (WARN_ON_ONCE(atomic_read(&lock_is_read_held))) - lwsp->n_lock_fail++; /* rare, but... */ - lwsp->n_lock_acquired++; + if (!skip_main_lock) { + cxt.cur_ops->writelock(tid); + if (WARN_ON_ONCE(lock_is_write_held)) + lwsp->n_lock_fail++; + lock_is_write_held = true; + if (WARN_ON_ONCE(atomic_read(&lock_is_read_held))) + lwsp->n_lock_fail++; /* rare, but... */ + + lwsp->n_lock_acquired++; + } cxt.cur_ops->write_delay(&rand); - lock_is_write_held = false; - WRITE_ONCE(last_lock_release, jiffies); - cxt.cur_ops->writeunlock(tid); + if (!skip_main_lock) { + lock_is_write_held = false; + WRITE_ONCE(last_lock_release, jiffies); + cxt.cur_ops->writeunlock(tid); + } if (cxt.cur_ops->nested_unlock) cxt.cur_ops->nested_unlock(tid, lockset_mask); From 5d65cf6ae6aea1a8d533d4499201a13d0068a0dc Mon Sep 17 00:00:00 2001 From: Zqiang Date: Fri, 24 Feb 2023 09:20:35 +0800 Subject: [PATCH 032/291] locktorture: Add raw_spinlock* torture tests for PREEMPT_RT kernels In PREEMPT_RT kernels, both spin_lock() and spin_lock_irq() are converted to sleepable rt_spin_lock(). This means that the interrupt related suffixes for spin_lock/unlock(_irq, irqsave/irqrestore) do not affect the CPU's interrupt state. This commit therefore adds raw spin-lock torture tests. This in turn permits pure spin locks to be tested in PREEMPT_RT kernels. Suggested-by: Paul E. McKenney Suggested-by: Davidlohr Bueso Signed-off-by: Zqiang Reviewed-by: Davidlohr Bueso Signed-off-by: Paul E. McKenney --- kernel/locking/locktorture.c | 56 +++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/kernel/locking/locktorture.c b/kernel/locking/locktorture.c index 9425aff08936..153ddc4c47ef 100644 --- a/kernel/locking/locktorture.c +++ b/kernel/locking/locktorture.c @@ -55,7 +55,7 @@ torture_param(int, nested_locks, 0, "Number of nested locks (max = 8)"); /* Going much higher trips "BUG: MAX_LOCKDEP_CHAIN_HLOCKS too low!" errors */ #define MAX_NESTED_LOCKS 8 -static char *torture_type = "spin_lock"; +static char *torture_type = IS_ENABLED(CONFIG_PREEMPT_RT) ? "raw_spin_lock" : "spin_lock"; module_param(torture_type, charp, 0444); MODULE_PARM_DESC(torture_type, "Type of lock to torture (spin_lock, spin_lock_irq, mutex_lock, ...)"); @@ -257,6 +257,59 @@ static struct lock_torture_ops spin_lock_irq_ops = { .name = "spin_lock_irq" }; +static DEFINE_RAW_SPINLOCK(torture_raw_spinlock); + +static int torture_raw_spin_lock_write_lock(int tid __maybe_unused) +__acquires(torture_raw_spinlock) +{ + raw_spin_lock(&torture_raw_spinlock); + return 0; +} + +static void torture_raw_spin_lock_write_unlock(int tid __maybe_unused) +__releases(torture_raw_spinlock) +{ + raw_spin_unlock(&torture_raw_spinlock); +} + +static struct lock_torture_ops raw_spin_lock_ops = { + .writelock = torture_raw_spin_lock_write_lock, + .write_delay = torture_spin_lock_write_delay, + .task_boost = torture_rt_boost, + .writeunlock = torture_raw_spin_lock_write_unlock, + .readlock = NULL, + .read_delay = NULL, + .readunlock = NULL, + .name = "raw_spin_lock" +}; + +static int torture_raw_spin_lock_write_lock_irq(int tid __maybe_unused) +__acquires(torture_raw_spinlock) +{ + unsigned long flags; + + raw_spin_lock_irqsave(&torture_raw_spinlock, flags); + cxt.cur_ops->flags = flags; + return 0; +} + +static void torture_raw_spin_lock_write_unlock_irq(int tid __maybe_unused) +__releases(torture_raw_spinlock) +{ + raw_spin_unlock_irqrestore(&torture_raw_spinlock, cxt.cur_ops->flags); +} + +static struct lock_torture_ops raw_spin_lock_irq_ops = { + .writelock = torture_raw_spin_lock_write_lock_irq, + .write_delay = torture_spin_lock_write_delay, + .task_boost = torture_rt_boost, + .writeunlock = torture_raw_spin_lock_write_unlock_irq, + .readlock = NULL, + .read_delay = NULL, + .readunlock = NULL, + .name = "raw_spin_lock_irq" +}; + static DEFINE_RWLOCK(torture_rwlock); static int torture_rwlock_write_lock(int tid __maybe_unused) @@ -1017,6 +1070,7 @@ static int __init lock_torture_init(void) static struct lock_torture_ops *torture_ops[] = { &lock_busted_ops, &spin_lock_ops, &spin_lock_irq_ops, + &raw_spin_lock_ops, &raw_spin_lock_irq_ops, &rw_lock_ops, &rw_lock_irq_ops, &mutex_lock_ops, &ww_mutex_lock_ops, From 502a29b04d857c28aa36f8829a5c673b9b8864a6 Mon Sep 17 00:00:00 2001 From: XU pengfei Date: Wed, 26 Oct 2022 16:29:24 +0800 Subject: [PATCH 033/291] smack_lsm: remove unnecessary type casting Remove unnecessary type casting. The type of inode variable is struct inode *, so no type casting required. Signed-off-by: XU pengfei Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index cfcbb748da25..24ade96e17b3 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1477,7 +1477,7 @@ static int smack_inode_getsecurity(struct mnt_idmap *idmap, struct socket_smack *ssp; struct socket *sock; struct super_block *sbp; - struct inode *ip = (struct inode *)inode; + struct inode *ip = inode; struct smack_known *isp; if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) From 1e2523d745cff3c5c066e66299d3cf179baa3cbc Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 8 Mar 2023 12:31:03 -0500 Subject: [PATCH 034/291] lsm: fix doc warnings in the LSM hook comments Signed-off-by: Paul Moore --- security/security.c | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/security/security.c b/security/security.c index f6482fd7b4b9..4c39cfe313bf 100644 --- a/security/security.c +++ b/security/security.c @@ -1228,7 +1228,7 @@ void security_sb_free(struct super_block *sb) /** * security_free_mnt_opts() - Free memory associated with mount options - * @mnt_ops: LSM processed mount options + * @mnt_opts: LSM processed mount options * * Free memory associated with @mnt_ops. */ @@ -1244,7 +1244,7 @@ EXPORT_SYMBOL(security_free_mnt_opts); /** * security_sb_eat_lsm_opts() - Consume LSM mount options * @options: mount options - * @mnt_ops: LSM processed mount options + * @mnt_opts: LSM processed mount options * * Eat (scan @options) and save them in @mnt_opts. * @@ -1407,8 +1407,8 @@ EXPORT_SYMBOL(security_sb_set_mnt_opts); /** * security_sb_clone_mnt_opts() - Duplicate superblock mount options - * @olddb: source superblock - * @newdb: destination superblock + * @oldsb: source superblock + * @newsb: destination superblock * @kern_flags: kernel flags (in) * @set_kern_flags: kernel flags (out) * @@ -1916,7 +1916,7 @@ int security_inode_unlink(struct inode *dir, struct dentry *dentry) } /** - * security_inode_symlink() Check if creating a symbolic link is allowed + * security_inode_symlink() - Check if creating a symbolic link is allowed * @dir: parent directory * @dentry: symbolic link * @old_name: existing filename @@ -2125,6 +2125,7 @@ int security_inode_getattr(const struct path *path) * @dentry: file * @name: xattr name * @value: xattr value + * @size: size of xattr value * @flags: flags * * Check permission before setting the extended attributes. @@ -2686,7 +2687,7 @@ int security_mmap_addr(unsigned long addr) * security_file_mprotect() - Check if changing memory protections is allowed * @vma: memory region * @reqprot: application requested protection - * @prog: protection applied by the kernel + * @prot: protection applied by the kernel * * Check permissions before changing memory access permissions. * @@ -3421,7 +3422,7 @@ int security_create_user_ns(const struct cred *cred) /** * security_ipc_permission() - Check if sysv ipc access is allowed * @ipcp: ipc permission structure - * @flags: requested permissions + * @flag: requested permissions * * Check permissions for access to IPC. * @@ -3718,7 +3719,7 @@ int security_sem_associate(struct kern_ipc_perm *sma, int semflg) } /** - * security_sem_ctl() - Check if a sysv semaphore operation is allowed + * security_sem_semctl() - Check if a sysv semaphore operation is allowed * @sma: sysv ipc permission structure * @cmd: operation * @@ -4088,7 +4089,7 @@ int security_socket_create(int family, int type, int protocol, int kern) } /** - * security_socket_create() - Initialize a newly created socket + * security_socket_post_create() - Initialize a newly created socket * @sock: socket * @family: protocol family * @type: communications type @@ -4364,7 +4365,7 @@ EXPORT_SYMBOL(security_socket_getpeersec_dgram); * security_sk_alloc() - Allocate and initialize a sock's LSM blob * @sk: sock * @family: protocol family - * @priotity: gfp flags + * @priority: gfp flags * * Allocate and attach a security structure to the sk->sk_security field, which * is used to copy security attributes between local stream sockets. @@ -4423,10 +4424,10 @@ EXPORT_SYMBOL(security_req_classify_flow); /** * security_sock_graft() - Reconcile LSM state when grafting a sock on a socket * @sk: sock being grafted - * @sock: target socket + * @parent: target parent socket * - * Sets @sock's inode secid to @sk's secid and update @sk with any necessary - * LSM state from @sock. + * Sets @parent's inode secid to @sk's secid and update @sk with any necessary + * LSM state from @parent. */ void security_sock_graft(struct sock *sk, struct socket *parent) { @@ -4877,7 +4878,7 @@ int security_xfrm_policy_lookup(struct xfrm_sec_ctx *ctx, u32 fl_secid) /** * security_xfrm_state_pol_flow_match() - Check for a xfrm match * @x: xfrm state to match - * @xp xfrm policy to check for a match + * @xp: xfrm policy to check for a match * @flic: flow to check for a match. * * Check @xp and @flic for a match with @x. @@ -4980,13 +4981,13 @@ int security_key_permission(key_ref_t key_ref, const struct cred *cred, /** * security_key_getsecurity() - Get the key's security label * @key: key - * @buffer: security label buffer + * @_buffer: security label buffer * * Get a textual representation of the security context attached to a key for * the purposes of honouring KEYCTL_GETSECURITY. This function allocates the * storage for the NUL-terminated string and the caller should free it. * - * Return: Returns the length of @buffer (including terminating NUL) or -ve if + * Return: Returns the length of @_buffer (including terminating NUL) or -ve if * an error occurs. May also return 0 (and a NULL buffer pointer) if * there is no security label assigned to the key. */ From b3816cf8138b6814375ec65673bcba91d368ee9f Mon Sep 17 00:00:00 2001 From: Paul Moore Date: Wed, 8 Mar 2023 13:28:18 -0500 Subject: [PATCH 035/291] lsm: fix a badly named parameter in security_get_getsecurity() There is no good reason for why the "_buffer" parameter needs an underscore, get rid of it. Signed-off-by: Paul Moore --- include/linux/lsm_hook_defs.h | 2 +- security/security.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h index 094b76dc7164..6bb55e61e8e8 100644 --- a/include/linux/lsm_hook_defs.h +++ b/include/linux/lsm_hook_defs.h @@ -381,7 +381,7 @@ LSM_HOOK(int, 0, key_alloc, struct key *key, const struct cred *cred, LSM_HOOK(void, LSM_RET_VOID, key_free, struct key *key) LSM_HOOK(int, 0, key_permission, key_ref_t key_ref, const struct cred *cred, enum key_need_perm need_perm) -LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **_buffer) +LSM_HOOK(int, 0, key_getsecurity, struct key *key, char **buffer) #endif /* CONFIG_KEYS */ #ifdef CONFIG_AUDIT diff --git a/security/security.c b/security/security.c index 4c39cfe313bf..e6c275fff001 100644 --- a/security/security.c +++ b/security/security.c @@ -4981,20 +4981,20 @@ int security_key_permission(key_ref_t key_ref, const struct cred *cred, /** * security_key_getsecurity() - Get the key's security label * @key: key - * @_buffer: security label buffer + * @buffer: security label buffer * * Get a textual representation of the security context attached to a key for * the purposes of honouring KEYCTL_GETSECURITY. This function allocates the * storage for the NUL-terminated string and the caller should free it. * - * Return: Returns the length of @_buffer (including terminating NUL) or -ve if + * Return: Returns the length of @buffer (including terminating NUL) or -ve if * an error occurs. May also return 0 (and a NULL buffer pointer) if * there is no security label assigned to the key. */ -int security_key_getsecurity(struct key *key, char **_buffer) +int security_key_getsecurity(struct key *key, char **buffer) { - *_buffer = NULL; - return call_int_hook(key_getsecurity, 0, key, _buffer); + *buffer = NULL; + return call_int_hook(key_getsecurity, 0, key, buffer); } #endif /* CONFIG_KEYS */ From f89f8e1661e6bef87073ad4934e1eede5f69f4b7 Mon Sep 17 00:00:00 2001 From: Kamalesh Babulal Date: Sat, 4 Mar 2023 12:59:23 +0530 Subject: [PATCH 036/291] device_cgroup: Fix typo in devcgroup_css_alloc description Fix the stale cgroup.c path in the devcgroup_css_alloc() description. Signed-off-by: Kamalesh Babulal Signed-off-by: Paul Moore --- security/device_cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/device_cgroup.c b/security/device_cgroup.c index bef2b9285fb3..7507d14eacc7 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c @@ -216,7 +216,7 @@ static void devcgroup_offline(struct cgroup_subsys_state *css) } /* - * called from kernel/cgroup.c with cgroup_lock() held. + * called from kernel/cgroup/cgroup.c with cgroup_lock() held. */ static struct cgroup_subsys_state * devcgroup_css_alloc(struct cgroup_subsys_state *parent_css) From 887d85a0736ff346cbfe5efaf51cf20c7ca195a3 Mon Sep 17 00:00:00 2001 From: Rae Moar Date: Wed, 8 Mar 2023 20:39:50 +0000 Subject: [PATCH 037/291] kunit: fix bug in debugfs logs of parameterized tests Fix bug in debugfs logs that causes individual parameterized results to not appear because the log is reinitialized (cleared) when each parameter is run. Ensure these results appear in the debugfs logs, increase log size to allow for the size of parameterized results. As a result, append lines to the log directly rather than using an intermediate variable that can cause stack size warnings due to the increased log size. Here is the debugfs log of ext4_inode_test which uses parameterized tests before the fix: KTAP version 1 # Subtest: ext4_inode_test 1..1 # Totals: pass:16 fail:0 skip:0 total:16 ok 1 ext4_inode_test As you can see, this log does not include any of the individual parametrized results. After (in combination with the next two fixes to remove extra empty line and ensure KTAP valid format): KTAP version 1 1..1 KTAP version 1 # Subtest: ext4_inode_test 1..1 KTAP version 1 # Subtest: inode_test_xtimestamp_decoding ok 1 1901-12-13 Lower bound of 32bit < 0 timestamp, no extra bits ... (the rest of the individual parameterized tests) ok 16 2446-05-10 Upper bound of 32bit >=0 timestamp. All extra # inode_test_xtimestamp_decoding: pass:16 fail:0 skip:0 total:16 ok 1 inode_test_xtimestamp_decoding # Totals: pass:16 fail:0 skip:0 total:16 ok 1 ext4_inode_test Signed-off-by: Rae Moar Reviewed-by: David Gow Signed-off-by: Shuah Khan --- include/kunit/test.h | 2 +- lib/kunit/test.c | 18 ++++++++++++------ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/kunit/test.h b/include/kunit/test.h index 08d3559dd703..0668d29f3453 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -34,7 +34,7 @@ DECLARE_STATIC_KEY_FALSE(kunit_running); struct kunit; /* Size of log associated with test. */ -#define KUNIT_LOG_SIZE 512 +#define KUNIT_LOG_SIZE 1500 /* Maximum size of parameter description string. */ #define KUNIT_PARAM_DESC_SIZE 128 diff --git a/lib/kunit/test.c b/lib/kunit/test.c index c9e15bb60058..c4d6304edd61 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -114,22 +114,27 @@ static void kunit_print_test_stats(struct kunit *test, */ void kunit_log_append(char *log, const char *fmt, ...) { - char line[KUNIT_LOG_SIZE]; va_list args; - int len_left; + int len, log_len, len_left; if (!log) return; - len_left = KUNIT_LOG_SIZE - strlen(log) - 1; + log_len = strlen(log); + len_left = KUNIT_LOG_SIZE - log_len - 1; if (len_left <= 0) return; + /* Evaluate length of line to add to log */ va_start(args, fmt); - vsnprintf(line, sizeof(line), fmt, args); + len = vsnprintf(NULL, 0, fmt, args) + 1; + va_end(args); + + /* Print formatted line to the log */ + va_start(args, fmt); + vsnprintf(log + log_len, min(len, len_left), fmt, args); va_end(args); - strncat(log, line, len_left); } EXPORT_SYMBOL_GPL(kunit_log_append); @@ -437,7 +442,6 @@ static void kunit_run_case_catch_errors(struct kunit_suite *suite, struct kunit_try_catch_context context; struct kunit_try_catch *try_catch; - kunit_init_test(test, test_case->name, test_case->log); try_catch = &test->try_catch; kunit_try_catch_init(try_catch, @@ -533,6 +537,8 @@ int kunit_run_tests(struct kunit_suite *suite) struct kunit_result_stats param_stats = { 0 }; test_case->status = KUNIT_SKIPPED; + kunit_init_test(&test, test_case->name, test_case->log); + if (!test_case->generate_params) { /* Non-parameterised test. */ kunit_run_case_catch_errors(suite, test_case, &test); From f9a301c3317daa921375da0aec82462ddf019928 Mon Sep 17 00:00:00 2001 From: Rae Moar Date: Wed, 8 Mar 2023 20:39:51 +0000 Subject: [PATCH 038/291] kunit: fix bug in the order of lines in debugfs logs Fix bug in debugfs logs that causes an incorrect order of lines in the debugfs log. Currently, the test counts lines that show the number of tests passed, failed, and skipped, as well as any suite diagnostic lines, appear prior to the individual results, which is a bug. Ensure the order of printing for the debugfs log is correct. Additionally, add a KTAP header to so the debugfs logs can be valid KTAP. This is an example of a log prior to these fixes: KTAP version 1 # Subtest: kunit_status 1..2 # kunit_status: pass:2 fail:0 skip:0 total:2 # Totals: pass:2 fail:0 skip:0 total:2 ok 1 kunit_status_set_failure_test ok 2 kunit_status_mark_skipped_test ok 1 kunit_status Note the two lines with stats are out of order. This is the same debugfs log after the fixes (in combination with the third patch to remove the extra line): KTAP version 1 1..1 KTAP version 1 # Subtest: kunit_status 1..2 ok 1 kunit_status_set_failure_test ok 2 kunit_status_mark_skipped_test # kunit_status: pass:2 fail:0 skip:0 total:2 # Totals: pass:2 fail:0 skip:0 total:2 ok 1 kunit_status Signed-off-by: Rae Moar Reviewed-by: David Gow Signed-off-by: Shuah Khan --- lib/kunit/debugfs.c | 14 ++++++++++++-- lib/kunit/test.c | 21 ++++++++++++++------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/kunit/debugfs.c b/lib/kunit/debugfs.c index de0ee2e03ed6..b08bb1fba106 100644 --- a/lib/kunit/debugfs.c +++ b/lib/kunit/debugfs.c @@ -55,14 +55,24 @@ static int debugfs_print_results(struct seq_file *seq, void *v) enum kunit_status success = kunit_suite_has_succeeded(suite); struct kunit_case *test_case; - if (!suite || !suite->log) + if (!suite) return 0; - seq_printf(seq, "%s", suite->log); + /* Print KTAP header so the debugfs log can be parsed as valid KTAP. */ + seq_puts(seq, "KTAP version 1\n"); + seq_puts(seq, "1..1\n"); + + /* Print suite header because it is not stored in the test logs. */ + seq_puts(seq, KUNIT_SUBTEST_INDENT "KTAP version 1\n"); + seq_printf(seq, KUNIT_SUBTEST_INDENT "# Subtest: %s\n", suite->name); + seq_printf(seq, KUNIT_SUBTEST_INDENT "1..%zd\n", kunit_suite_num_test_cases(suite)); kunit_suite_for_each_test_case(suite, test_case) debugfs_print_result(seq, suite, test_case); + if (suite->log) + seq_printf(seq, "%s", suite->log); + seq_printf(seq, "%s %d %s\n", kunit_status_to_ok_not_ok(success), 1, suite->name); return 0; diff --git a/lib/kunit/test.c b/lib/kunit/test.c index c4d6304edd61..811fcc376d2f 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -152,10 +152,18 @@ EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases); static void kunit_print_suite_start(struct kunit_suite *suite) { - kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "KTAP version 1\n"); - kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s", + /* + * We do not log the test suite header as doing so would + * mean debugfs display would consist of the test suite + * header prior to individual test results. + * Hence directly printk the suite status, and we will + * separately seq_printf() the suite header for the debugfs + * representation. + */ + pr_info(KUNIT_SUBTEST_INDENT "KTAP version 1\n"); + pr_info(KUNIT_SUBTEST_INDENT "# Subtest: %s\n", suite->name); - kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd", + pr_info(KUNIT_SUBTEST_INDENT "1..%zd\n", kunit_suite_num_test_cases(suite)); } @@ -172,10 +180,9 @@ static void kunit_print_ok_not_ok(void *test_or_suite, /* * We do not log the test suite results as doing so would - * mean debugfs display would consist of the test suite - * description and status prior to individual test results. - * Hence directly printk the suite status, and we will - * separately seq_printf() the suite status for the debugfs + * mean debugfs display would consist of an incorrect test + * number. Hence directly printk the suite result, and we will + * separately seq_printf() the suite results for the debugfs * representation. */ if (suite) From 2c6a96dad5797e57b4cf04101d6c8d5c7a571603 Mon Sep 17 00:00:00 2001 From: Rae Moar Date: Wed, 8 Mar 2023 20:39:52 +0000 Subject: [PATCH 039/291] kunit: fix bug of extra newline characters in debugfs logs Fix bug of the extra newline characters in debugfs logs. When a line is added to debugfs with a newline character at the end, an extra line appears in the debugfs log. This is due to a discrepancy between how the lines are printed and how they are added to the logs. Remove this discrepancy by checking if a newline character is present before adding a newline character. This should closely match the printk behavior. Add kunit_log_newline_test to provide test coverage for this issue. (Also, move kunit_log_test above suite definition to remove the unnecessary declaration prior to the suite definition) As an example, say we add these two lines to the log: kunit_log(..., "KTAP version 1\n"); kunit_log(..., "1..1"); The debugfs log before this fix: KTAP version 1 1..1 The debugfs log after this fix: KTAP version 1 1..1 Signed-off-by: Rae Moar Reviewed-by: David Gow Signed-off-by: Shuah Khan --- include/kunit/test.h | 2 +- lib/kunit/kunit-test.c | 35 +++++++++++++++++++++++------------ lib/kunit/test.c | 18 ++++++++++++++++++ 3 files changed, 42 insertions(+), 13 deletions(-) diff --git a/include/kunit/test.h b/include/kunit/test.h index 0668d29f3453..9721584027d8 100644 --- a/include/kunit/test.h +++ b/include/kunit/test.h @@ -420,7 +420,7 @@ void __printf(2, 3) kunit_log_append(char *log, const char *fmt, ...); #define kunit_log(lvl, test_or_suite, fmt, ...) \ do { \ printk(lvl fmt, ##__VA_ARGS__); \ - kunit_log_append((test_or_suite)->log, fmt "\n", \ + kunit_log_append((test_or_suite)->log, fmt, \ ##__VA_ARGS__); \ } while (0) diff --git a/lib/kunit/kunit-test.c b/lib/kunit/kunit-test.c index 4df0335d0d06..b63595d3e241 100644 --- a/lib/kunit/kunit-test.c +++ b/lib/kunit/kunit-test.c @@ -443,18 +443,6 @@ static struct kunit_suite kunit_resource_test_suite = { .test_cases = kunit_resource_test_cases, }; -static void kunit_log_test(struct kunit *test); - -static struct kunit_case kunit_log_test_cases[] = { - KUNIT_CASE(kunit_log_test), - {} -}; - -static struct kunit_suite kunit_log_test_suite = { - .name = "kunit-log-test", - .test_cases = kunit_log_test_cases, -}; - static void kunit_log_test(struct kunit *test) { struct kunit_suite suite; @@ -481,6 +469,29 @@ static void kunit_log_test(struct kunit *test) #endif } +static void kunit_log_newline_test(struct kunit *test) +{ + kunit_info(test, "Add newline\n"); + if (test->log) { + KUNIT_ASSERT_NOT_NULL_MSG(test, strstr(test->log, "Add newline\n"), + "Missing log line, full log:\n%s", test->log); + KUNIT_EXPECT_NULL(test, strstr(test->log, "Add newline\n\n")); + } else { + kunit_skip(test, "only useful when debugfs is enabled"); + } +} + +static struct kunit_case kunit_log_test_cases[] = { + KUNIT_CASE(kunit_log_test), + KUNIT_CASE(kunit_log_newline_test), + {} +}; + +static struct kunit_suite kunit_log_test_suite = { + .name = "kunit-log-test", + .test_cases = kunit_log_test_cases, +}; + static void kunit_status_set_failure_test(struct kunit *test) { struct kunit fake; diff --git a/lib/kunit/test.c b/lib/kunit/test.c index 811fcc376d2f..e2910b261112 100644 --- a/lib/kunit/test.c +++ b/lib/kunit/test.c @@ -108,6 +108,22 @@ static void kunit_print_test_stats(struct kunit *test, stats.total); } +/** + * kunit_log_newline() - Add newline to the end of log if one is not + * already present. + * @log: The log to add the newline to. + */ +static void kunit_log_newline(char *log) +{ + int log_len, len_left; + + log_len = strlen(log); + len_left = KUNIT_LOG_SIZE - log_len - 1; + + if (log_len > 0 && log[log_len - 1] != '\n') + strncat(log, "\n", len_left); +} + /* * Append formatted message to log, size of which is limited to * KUNIT_LOG_SIZE bytes (including null terminating byte). @@ -135,6 +151,8 @@ void kunit_log_append(char *log, const char *fmt, ...) vsnprintf(log + log_len, min(len, len_left), fmt, args); va_end(args); + /* Add newline to end of log if not already present. */ + kunit_log_newline(log); } EXPORT_SYMBOL_GPL(kunit_log_append); From 42994ee3cd7298b27698daa6848ed7168e72d056 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Fri, 10 Mar 2023 09:53:59 +0100 Subject: [PATCH 040/291] security: Introduce LSM_ORDER_LAST and set it for the integrity LSM Introduce LSM_ORDER_LAST, to satisfy the requirement of LSMs needing to be last, e.g. the 'integrity' LSM, without changing the kernel command line or configuration. Also, set this order for the 'integrity' LSM. While not enforced, this is the only LSM expected to use it. Similarly to LSM_ORDER_FIRST, LSMs with LSM_ORDER_LAST are always enabled and put at the end of the LSM list, if selected in the kernel configuration. Setting one of these orders alone, does not cause the LSMs to be selected and compiled built-in in the kernel. Finally, for LSM_ORDER_MUTABLE LSMs, set the found variable to true if an LSM is found, regardless of its order. In this way, the kernel would not wrongly report that the LSM is not built-in in the kernel if its order is LSM_ORDER_LAST. Fixes: 79f7865d844c ("LSM: Introduce "lsm=" for boottime LSM selection") Signed-off-by: Roberto Sassu Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- include/linux/lsm_hooks.h | 1 + security/integrity/iint.c | 1 + security/security.c | 12 +++++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index ddbbe89a7a48..c2be66c669ae 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -92,6 +92,7 @@ extern void security_add_hooks(struct security_hook_list *hooks, int count, enum lsm_order { LSM_ORDER_FIRST = -1, /* This is only for capabilities. */ LSM_ORDER_MUTABLE = 0, + LSM_ORDER_LAST = 1, /* This is only for integrity. */ }; struct lsm_info { diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 8638976f7990..b97eb59e0e32 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -182,6 +182,7 @@ static int __init integrity_iintcache_init(void) DEFINE_LSM(integrity) = { .name = "integrity", .init = integrity_iintcache_init, + .order = LSM_ORDER_LAST, }; diff --git a/security/security.c b/security/security.c index e6c275fff001..b808e1b86551 100644 --- a/security/security.c +++ b/security/security.c @@ -285,9 +285,9 @@ static void __init ordered_lsm_parse(const char *order, const char *origin) bool found = false; for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { - if (lsm->order == LSM_ORDER_MUTABLE && - strcmp(lsm->name, name) == 0) { - append_ordered_lsm(lsm, origin); + if (strcmp(lsm->name, name) == 0) { + if (lsm->order == LSM_ORDER_MUTABLE) + append_ordered_lsm(lsm, origin); found = true; } } @@ -307,6 +307,12 @@ static void __init ordered_lsm_parse(const char *order, const char *origin) } } + /* LSM_ORDER_LAST is always last. */ + for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { + if (lsm->order == LSM_ORDER_LAST) + append_ordered_lsm(lsm, " last"); + } + /* Disable all LSMs not in the ordered list. */ for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) { if (exists_ordered_lsm(lsm)) From b7c1ae4bcc5b7e737b46d469959446afc76d3165 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Fri, 10 Mar 2023 09:54:00 +0100 Subject: [PATCH 041/291] Revert "integrity: double check iint_cache was initialized" With the recent introduction of LSM_ORDER_LAST, the 'integrity' LSM is always initialized (if selected in the kernel configuration) and the iint_cache is always created (the kernel panics on error). Thus, the additional check of iint_cache in integrity_inode_get() is no longer necessary. If the 'integrity' LSM is not selected in the kernel configuration, integrity_inode_get() just returns NULL. This reverts commit 92063f3ca73aab794bd5408d3361fd5b5ea33079. Signed-off-by: Roberto Sassu Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/integrity/iint.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/security/integrity/iint.c b/security/integrity/iint.c index b97eb59e0e32..c73858e8c6d5 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -98,14 +98,6 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode) struct rb_node *node, *parent = NULL; struct integrity_iint_cache *iint, *test_iint; - /* - * The integrity's "iint_cache" is initialized at security_init(), - * unless it is not included in the ordered list of LSMs enabled - * on the boot command line. - */ - if (!iint_cache) - panic("%s: lsm=integrity required.\n", __func__); - iint = integrity_iint_find(inode); if (iint) return iint; From b9b8701b43146f5ebd7fe13d89103cfc545cda34 Mon Sep 17 00:00:00 2001 From: Roberto Sassu Date: Fri, 10 Mar 2023 09:54:01 +0100 Subject: [PATCH 042/291] security: Remove integrity from the LSM list in Kconfig Remove 'integrity' from the list of LSMs in Kconfig, as it is no longer necessary. Since the recent change (set order to LSM_ORDER_LAST), the 'integrity' LSM is always enabled (if selected in the kernel configuration). Signed-off-by: Roberto Sassu Acked-by: Mimi Zohar Signed-off-by: Paul Moore --- security/Kconfig | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/security/Kconfig b/security/Kconfig index e6db09a779b7..1699dda68216 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -246,15 +246,17 @@ endchoice config LSM string "Ordered list of enabled LSMs" - default "landlock,lockdown,yama,loadpin,safesetid,integrity,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK - default "landlock,lockdown,yama,loadpin,safesetid,integrity,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR - default "landlock,lockdown,yama,loadpin,safesetid,integrity,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO - default "landlock,lockdown,yama,loadpin,safesetid,integrity,bpf" if DEFAULT_SECURITY_DAC - default "landlock,lockdown,yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor,bpf" + default "landlock,lockdown,yama,loadpin,safesetid,smack,selinux,tomoyo,apparmor,bpf" if DEFAULT_SECURITY_SMACK + default "landlock,lockdown,yama,loadpin,safesetid,apparmor,selinux,smack,tomoyo,bpf" if DEFAULT_SECURITY_APPARMOR + default "landlock,lockdown,yama,loadpin,safesetid,tomoyo,bpf" if DEFAULT_SECURITY_TOMOYO + default "landlock,lockdown,yama,loadpin,safesetid,bpf" if DEFAULT_SECURITY_DAC + default "landlock,lockdown,yama,loadpin,safesetid,selinux,smack,tomoyo,apparmor,bpf" help A comma-separated list of LSMs, in initialization order. - Any LSMs left off this list will be ignored. This can be - controlled at boot with the "lsm=" parameter. + Any LSMs left off this list, except for those with order + LSM_ORDER_FIRST and LSM_ORDER_LAST, which are always enabled + if selected in the kernel configuration, will be ignored. + This can be controlled at boot with the "lsm=" parameter. If unsure, leave this as the default. From 8dec88070d964bfeb4198f34cb5956d89dd1f557 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Thu, 9 Mar 2023 11:17:52 +0100 Subject: [PATCH 043/291] kcsan: Avoid READ_ONCE() in read_instrumented_memory() Haibo Li reported: | Unable to handle kernel paging request at virtual address | ffffff802a0d8d7171 | Mem abort info:o: | ESR = 0x9600002121 | EC = 0x25: DABT (current EL), IL = 32 bitsts | SET = 0, FnV = 0 0 | EA = 0, S1PTW = 0 0 | FSC = 0x21: alignment fault | Data abort info:o: | ISV = 0, ISS = 0x0000002121 | CM = 0, WnR = 0 0 | swapper pgtable: 4k pages, 39-bit VAs, pgdp=000000002835200000 | [ffffff802a0d8d71] pgd=180000005fbf9003, p4d=180000005fbf9003, | pud=180000005fbf9003, pmd=180000005fbe8003, pte=006800002a0d8707 | Internal error: Oops: 96000021 [#1] PREEMPT SMP | Modules linked in: | CPU: 2 PID: 45 Comm: kworker/u8:2 Not tainted | 5.15.78-android13-8-g63561175bbda-dirty #1 | ... | pc : kcsan_setup_watchpoint+0x26c/0x6bc | lr : kcsan_setup_watchpoint+0x88/0x6bc | sp : ffffffc00ab4b7f0 | x29: ffffffc00ab4b800 x28: ffffff80294fe588 x27: 0000000000000001 | x26: 0000000000000019 x25: 0000000000000001 x24: ffffff80294fdb80 | x23: 0000000000000000 x22: ffffffc00a70fb68 x21: ffffff802a0d8d71 | x20: 0000000000000002 x19: 0000000000000000 x18: ffffffc00a9bd060 | x17: 0000000000000001 x16: 0000000000000000 x15: ffffffc00a59f000 | x14: 0000000000000001 x13: 0000000000000000 x12: ffffffc00a70faa0 | x11: 00000000aaaaaaab x10: 0000000000000054 x9 : ffffffc00839adf8 | x8 : ffffffc009b4cf00 x7 : 0000000000000000 x6 : 0000000000000007 | x5 : 0000000000000000 x4 : 0000000000000000 x3 : ffffffc00a70fb70 | x2 : 0005ff802a0d8d71 x1 : 0000000000000000 x0 : 0000000000000000 | Call trace: | kcsan_setup_watchpoint+0x26c/0x6bc | __tsan_read2+0x1f0/0x234 | inflate_fast+0x498/0x750 | zlib_inflate+0x1304/0x2384 | __gunzip+0x3a0/0x45c | gunzip+0x20/0x30 | unpack_to_rootfs+0x2a8/0x3fc | do_populate_rootfs+0xe8/0x11c | async_run_entry_fn+0x58/0x1bc | process_one_work+0x3ec/0x738 | worker_thread+0x4c4/0x838 | kthread+0x20c/0x258 | ret_from_fork+0x10/0x20 | Code: b8bfc2a8 2a0803f7 14000007 d503249f (78bfc2a8) ) | ---[ end trace 613a943cb0a572b6 ]----- The reason for this is that on certain arm64 configuration since e35123d83ee3 ("arm64: lto: Strengthen READ_ONCE() to acquire when CONFIG_LTO=y"), READ_ONCE() may be promoted to a full atomic acquire instruction which cannot be used on unaligned addresses. Fix it by avoiding READ_ONCE() in read_instrumented_memory(), and simply forcing the compiler to do the required access by casting to the appropriate volatile type. In terms of generated code this currently only affects architectures that do not use the default READ_ONCE() implementation. The only downside is that we are not guaranteed atomicity of the access itself, although on most architectures a plain load up to machine word size should still be atomic (a fact the default READ_ONCE() still relies on itself). Reported-by: Haibo Li Tested-by: Haibo Li Cc: # 5.17+ Signed-off-by: Marco Elver Signed-off-by: Paul E. McKenney --- kernel/kcsan/core.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/kernel/kcsan/core.c b/kernel/kcsan/core.c index 54d077e1a2dc..5a60cc52adc0 100644 --- a/kernel/kcsan/core.c +++ b/kernel/kcsan/core.c @@ -337,11 +337,20 @@ static void delay_access(int type) */ static __always_inline u64 read_instrumented_memory(const volatile void *ptr, size_t size) { + /* + * In the below we don't necessarily need the read of the location to + * be atomic, and we don't use READ_ONCE(), since all we need for race + * detection is to observe 2 different values. + * + * Furthermore, on certain architectures (such as arm64), READ_ONCE() + * may turn into more complex instructions than a plain load that cannot + * do unaligned accesses. + */ switch (size) { - case 1: return READ_ONCE(*(const u8 *)ptr); - case 2: return READ_ONCE(*(const u16 *)ptr); - case 4: return READ_ONCE(*(const u32 *)ptr); - case 8: return READ_ONCE(*(const u64 *)ptr); + case 1: return *(const volatile u8 *)ptr; + case 2: return *(const volatile u16 *)ptr; + case 4: return *(const volatile u32 *)ptr; + case 8: return *(const volatile u64 *)ptr; default: return 0; /* Ignore; we do not diff the values. */ } } From 808a9d675969382c855acc304c288dfa713d3f9e Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 19 Dec 2022 11:21:09 -0800 Subject: [PATCH 044/291] rcutorture: Add test_nmis module parameter This commit adds a test_nmis module parameter to generate the specified number of NMI stack backtraces 15 seconds apart. This module parameter can be used to test NMI delivery and accompanying diagnostics. Note that this parameter is ignored when rcutorture is a module rather than built into the kernel. This could be changed with the addition of an EXPORT_SYMBOL_GPL(). [ paulmck: Apply kernel test robot feedback. ] Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- kernel/rcu/rcutorture.c | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 8e6c023212cb..480bba142e3a 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -119,6 +119,7 @@ torture_param(int, stutter, 5, "Number of seconds to run/halt test"); torture_param(int, test_boost, 1, "Test RCU prio boost: 0=no, 1=maybe, 2=yes."); torture_param(int, test_boost_duration, 4, "Duration of each boost test, seconds."); torture_param(int, test_boost_interval, 7, "Interval between boost tests, seconds."); +torture_param(int, test_nmis, 0, "End-test NMI tests, 0 to disable."); torture_param(bool, test_no_idle_hz, true, "Test support for tickless idle CPUs"); torture_param(int, verbose, 1, "Enable verbose debugging printk()s"); @@ -2358,7 +2359,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag) "n_barrier_cbs=%d " "onoff_interval=%d onoff_holdoff=%d " "read_exit_delay=%d read_exit_burst=%d " - "nocbs_nthreads=%d nocbs_toggle=%d\n", + "nocbs_nthreads=%d nocbs_toggle=%d " + "test_nmis=%d\n", torture_type, tag, nrealreaders, nfakewriters, stat_interval, verbose, test_no_idle_hz, shuffle_interval, stutter, irqreader, fqs_duration, fqs_holdoff, fqs_stutter, @@ -2369,7 +2371,8 @@ rcu_torture_print_module_parms(struct rcu_torture_ops *cur_ops, const char *tag) n_barrier_cbs, onoff_interval, onoff_holdoff, read_exit_delay, read_exit_burst, - nocbs_nthreads, nocbs_toggle); + nocbs_nthreads, nocbs_toggle, + test_nmis); } static int rcutorture_booster_cleanup(unsigned int cpu) @@ -3273,6 +3276,29 @@ static void rcu_torture_read_exit_cleanup(void) torture_stop_kthread(rcutorture_read_exit, read_exit_task); } +static void rcutorture_test_nmis(int n) +{ +#if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST) + int cpu; + int dumpcpu; + int i; + + for (i = 0; i < n; i++) { + preempt_disable(); + cpu = smp_processor_id(); + dumpcpu = cpu + 1; + if (dumpcpu >= nr_cpu_ids) + dumpcpu = 0; + pr_alert("%s: CPU %d invoking dump_cpu_task(%d)\n", __func__, cpu, dumpcpu); + dump_cpu_task(dumpcpu); + preempt_enable(); + schedule_timeout_uninterruptible(15 * HZ); + } +#else // #if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST) + WARN_ONCE(n, "Non-zero rcutorture.test_nmis=%d permitted only when rcutorture is built in.\n", test_nmis); +#endif // #else // #if IS_BUILTIN(CONFIG_RCU_TORTURE_TEST) +} + static enum cpuhp_state rcutor_hp; static void @@ -3297,6 +3323,8 @@ rcu_torture_cleanup(void) return; } + rcutorture_test_nmis(test_nmis); + if (cur_ops->gp_kthread_dbg) cur_ops->gp_kthread_dbg(); rcu_torture_read_exit_cleanup(); From 7ff0b54491791bdb99659e73c9851ac398c81416 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 9 Jan 2023 21:01:12 -0800 Subject: [PATCH 045/291] rcutorture: Set CONFIG_BOOTPARAM_HOTPLUG_CPU0 to offline CPU 0 There is now a BOOTPARAM_HOTPLUG_CPU0 Kconfig option that allows CPU 0 to be offlined on x86 systems. This commit therefore sets this option in the TREE01 rcutorture scenario in order to regularly test this capability. Reported-by: "Zhang, Qiang1" Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- tools/testing/selftests/rcutorture/configs/rcu/TREE01 | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 index 8ae41d5f81a3..04831ef1f9b5 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE01 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE01 @@ -15,3 +15,4 @@ CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_RCU_BOOST=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y +CONFIG_BOOTPARAM_HOTPLUG_CPU0=y From 7c3a8b48dc5452ec639293fd7796402d02213f58 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Mon, 9 Jan 2023 21:26:11 -0800 Subject: [PATCH 046/291] rcutorture: Make scenario TREE04 enable lazy call_rcu() This commit enables the RCU_LAZY Kconfig option in scenario TREE04 in order to provide some ongoing testing of this configuration. Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- tools/testing/selftests/rcutorture/configs/rcu/TREE04 | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 index ae395981b5e5..dc4985064b3a 100644 --- a/tools/testing/selftests/rcutorture/configs/rcu/TREE04 +++ b/tools/testing/selftests/rcutorture/configs/rcu/TREE04 @@ -15,3 +15,4 @@ CONFIG_DEBUG_LOCK_ALLOC=n CONFIG_DEBUG_OBJECTS_RCU_HEAD=n CONFIG_RCU_EXPERT=y CONFIG_RCU_EQS_DEBUG=y +CONFIG_RCU_LAZY=y From 236bdb881d9656194a2d9c78ee11dba39329a3b1 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Tue, 10 Jan 2023 16:46:34 +0530 Subject: [PATCH 047/291] tools: rcu: Add usage function and check for argument This commit converts extract-stall.sh script's header comment to a usage() function, and adds an argument check. While in the area, make this script be executable. [ paulmck: Strength argument check, remove extraneous comment. ] Signed-off-by: Bhaskar Chowdhury Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- tools/rcu/extract-stall.sh | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) mode change 100644 => 100755 tools/rcu/extract-stall.sh diff --git a/tools/rcu/extract-stall.sh b/tools/rcu/extract-stall.sh old mode 100644 new mode 100755 index e565697c9f90..08a39ad44320 --- a/tools/rcu/extract-stall.sh +++ b/tools/rcu/extract-stall.sh @@ -1,11 +1,25 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0+ -# -# Extract any RCU CPU stall warnings present in specified file. -# Filter out clocksource lines. Note that preceding-lines excludes the -# initial line of the stall warning but trailing-lines includes it. -# -# Usage: extract-stall.sh dmesg-file [ preceding-lines [ trailing-lines ] ] + +usage() { + echo Extract any RCU CPU stall warnings present in specified file. + echo Filter out clocksource lines. Note that preceding-lines excludes the + echo initial line of the stall warning but trailing-lines includes it. + echo + echo Usage: $(basename $0) dmesg-file [ preceding-lines [ trailing-lines ] ] + echo + echo Error: $1 +} + +# Terminate the script, if the argument is missing + +if test -f "$1" && test -r "$1" +then + : +else + usage "Console log file \"$1\" missing or unreadable." + exit 1 +fi echo $1 preceding_lines="${2-3}" From 995495846f7403cd871b22b03b40bd7e24be07a3 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Fri, 13 Jan 2023 21:23:46 -0800 Subject: [PATCH 048/291] torture: Permit kvm-again.sh --duration to default to previous run Currently, invoking kvm-again.sh without a --duration argument results in a bash error message. This commit therefore adds quotes around the $dur argument to kvm-transform.sh to allow a default duration to be taken from the earlier run. Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- tools/testing/selftests/rcutorture/bin/kvm-again.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/testing/selftests/rcutorture/bin/kvm-again.sh b/tools/testing/selftests/rcutorture/bin/kvm-again.sh index 8a968fbda02c..88ca4e368489 100755 --- a/tools/testing/selftests/rcutorture/bin/kvm-again.sh +++ b/tools/testing/selftests/rcutorture/bin/kvm-again.sh @@ -193,7 +193,7 @@ do qemu_cmd_dir="`dirname "$i"`" kernel_dir="`echo $qemu_cmd_dir | sed -e 's/\.[0-9]\+$//'`" jitter_dir="`dirname "$kernel_dir"`" - kvm-transform.sh "$kernel_dir/bzImage" "$qemu_cmd_dir/console.log" "$jitter_dir" $dur "$bootargs" < $T/qemu-cmd > $i + kvm-transform.sh "$kernel_dir/bzImage" "$qemu_cmd_dir/console.log" "$jitter_dir" "$dur" "$bootargs" < $T/qemu-cmd > $i if test -n "$arg_remote" then echo "# TORTURE_KCONFIG_GDB_ARG=''" >> $i From fdcf87a3dfbe19361ff128806a218a28da7689ad Mon Sep 17 00:00:00 2001 From: Yue Hu Date: Tue, 17 Jan 2023 13:53:10 +0800 Subject: [PATCH 049/291] rcutorture: Eliminate variable n_rcu_torture_boost_rterror After commit 8b700983de82 ("sched: Remove sched_set_*() return value"), this variable is not used anymore. So eliminate it entirely. Signed-off-by: Yue Hu Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- kernel/rcu/rcutorture.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/kernel/rcu/rcutorture.c b/kernel/rcu/rcutorture.c index 480bba142e3a..c0b2fd687bbb 100644 --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -180,7 +180,6 @@ static atomic_t n_rcu_torture_mbchk_tries; static atomic_t n_rcu_torture_error; static long n_rcu_torture_barrier_error; static long n_rcu_torture_boost_ktrerror; -static long n_rcu_torture_boost_rterror; static long n_rcu_torture_boost_failure; static long n_rcu_torture_boosts; static atomic_long_t n_rcu_torture_timers; @@ -2195,12 +2194,11 @@ rcu_torture_stats_print(void) atomic_read(&n_rcu_torture_alloc), atomic_read(&n_rcu_torture_alloc_fail), atomic_read(&n_rcu_torture_free)); - pr_cont("rtmbe: %d rtmbkf: %d/%d rtbe: %ld rtbke: %ld rtbre: %ld ", + pr_cont("rtmbe: %d rtmbkf: %d/%d rtbe: %ld rtbke: %ld ", atomic_read(&n_rcu_torture_mberror), atomic_read(&n_rcu_torture_mbchk_fail), atomic_read(&n_rcu_torture_mbchk_tries), n_rcu_torture_barrier_error, - n_rcu_torture_boost_ktrerror, - n_rcu_torture_boost_rterror); + n_rcu_torture_boost_ktrerror); pr_cont("rtbf: %ld rtb: %ld nt: %ld ", n_rcu_torture_boost_failure, n_rcu_torture_boosts, @@ -2218,15 +2216,13 @@ rcu_torture_stats_print(void) if (atomic_read(&n_rcu_torture_mberror) || atomic_read(&n_rcu_torture_mbchk_fail) || n_rcu_torture_barrier_error || n_rcu_torture_boost_ktrerror || - n_rcu_torture_boost_rterror || n_rcu_torture_boost_failure || - i > 1) { + n_rcu_torture_boost_failure || i > 1) { pr_cont("%s", "!!! "); atomic_inc(&n_rcu_torture_error); WARN_ON_ONCE(atomic_read(&n_rcu_torture_mberror)); WARN_ON_ONCE(atomic_read(&n_rcu_torture_mbchk_fail)); WARN_ON_ONCE(n_rcu_torture_barrier_error); // rcu_barrier() WARN_ON_ONCE(n_rcu_torture_boost_ktrerror); // no boost kthread - WARN_ON_ONCE(n_rcu_torture_boost_rterror); // can't set RT prio WARN_ON_ONCE(n_rcu_torture_boost_failure); // boost failed (TIMER_SOFTIRQ RT prio?) WARN_ON_ONCE(i > 1); // Too-short grace period } @@ -3568,7 +3564,6 @@ rcu_torture_init(void) atomic_set(&n_rcu_torture_error, 0); n_rcu_torture_barrier_error = 0; n_rcu_torture_boost_ktrerror = 0; - n_rcu_torture_boost_rterror = 0; n_rcu_torture_boost_failure = 0; n_rcu_torture_boosts = 0; for (i = 0; i < RCU_TORTURE_PIPE_LEN + 1; i++) From 877a0e83c57fa5e2a7fd628ec2e1733ed70c8792 Mon Sep 17 00:00:00 2001 From: "Paul E. McKenney" Date: Thu, 2 Feb 2023 17:04:09 -0800 Subject: [PATCH 050/291] torture: Enable clocksource watchdog with "tsc=watchdog" This commit tests the "tsc=watchdog" kernel boot parameter when running the clocksourcewd torture tests. Signed-off-by: Paul E. McKenney Signed-off-by: Boqun Feng --- tools/testing/selftests/rcutorture/bin/torture.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/rcutorture/bin/torture.sh b/tools/testing/selftests/rcutorture/bin/torture.sh index 130d0de4c3bb..5a2ae2264403 100755 --- a/tools/testing/selftests/rcutorture/bin/torture.sh +++ b/tools/testing/selftests/rcutorture/bin/torture.sh @@ -497,16 +497,16 @@ fi if test "$do_clocksourcewd" = "yes" then - torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000" + torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 tsc=watchdog" torture_set "clocksourcewd-1" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --kconfig "CONFIG_TEST_CLOCKSOURCE_WATCHDOG=y" --trust-make - torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 clocksource.max_cswd_read_retries=1" + torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 clocksource.max_cswd_read_retries=1 tsc=watchdog" torture_set "clocksourcewd-2" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --kconfig "CONFIG_TEST_CLOCKSOURCE_WATCHDOG=y" --trust-make # In case our work is already done... if test "$do_rcutorture" != "yes" then - torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000" + torture_bootargs="rcupdate.rcu_cpu_stall_suppress_at_boot=1 torture.disable_onoff_at_boot rcupdate.rcu_task_stall_timeout=30000 tsc=watchdog" torture_set "clocksourcewd-3" tools/testing/selftests/rcutorture/bin/kvm.sh --allcpus --duration 45s --configs TREE03 --trust-make fi fi From d2ea66a69fa908047f75a91f3728769bbd713849 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 13 Mar 2023 23:03:47 -0700 Subject: [PATCH 051/291] Documentation: fs/proc: corrections and update Update URL for the latest online version of this document. Correct "files" to "fields" in a few places. Update /proc/scsi, /proc/stat, and /proc/fs/ext4 information. Drop /usr/src/ from the location of the kernel source tree. Signed-off-by: Randy Dunlap Cc: Jonathan Corbet Cc: linux-doc@vger.kernel.org Cc: linux-fsdevel@vger.kernel.org Reviewed-by: Christian Brauner Link: https://lore.kernel.org/r/20230314060347.605-1-rdunlap@infradead.org Signed-off-by: Jonathan Corbet --- Documentation/filesystems/proc.rst | 44 ++++++++++++++++-------------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/Documentation/filesystems/proc.rst b/Documentation/filesystems/proc.rst index 9d5fd9424e8b..59db0bed35e1 100644 --- a/Documentation/filesystems/proc.rst +++ b/Documentation/filesystems/proc.rst @@ -85,7 +85,7 @@ contact Bodo Bauer at bb@ricochet.net. We'll be happy to add them to this document. The latest version of this document is available online at -http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/proc.html +https://www.kernel.org/doc/html/latest/filesystems/proc.html If the above direction does not works for you, you could try the kernel mailing list at linux-kernel@vger.kernel.org and/or try to reach me at @@ -232,7 +232,7 @@ asynchronous manner and the value may not be very precise. To see a precise snapshot of a moment, you can see /proc//smaps file and scan page table. It's slow but very precise. -.. table:: Table 1-2: Contents of the status files (as of 4.19) +.. table:: Table 1-2: Contents of the status fields (as of 4.19) ========================== =================================================== Field Content @@ -305,7 +305,7 @@ It's slow but very precise. ========================== =================================================== -.. table:: Table 1-3: Contents of the statm files (as of 2.6.8-rc3) +.. table:: Table 1-3: Contents of the statm fields (as of 2.6.8-rc3) ======== =============================== ============================== Field Content @@ -323,7 +323,7 @@ It's slow but very precise. ======== =============================== ============================== -.. table:: Table 1-4: Contents of the stat files (as of 2.6.30-rc7) +.. table:: Table 1-4: Contents of the stat fields (as of 2.6.30-rc7) ============= =============================================================== Field Content @@ -1321,9 +1321,9 @@ many times the slaves link has failed. 1.4 SCSI info ------------- -If you have a SCSI host adapter in your system, you'll find a subdirectory -named after the driver for this adapter in /proc/scsi. You'll also see a list -of all recognized SCSI devices in /proc/scsi:: +If you have a SCSI or ATA host adapter in your system, you'll find a +subdirectory named after the driver for this adapter in /proc/scsi. +You'll also see a list of all recognized SCSI devices in /proc/scsi:: >cat /proc/scsi/scsi Attached devices: @@ -1449,16 +1449,18 @@ Various pieces of information about kernel activity are available in the since the system first booted. For a quick look, simply cat the file:: > cat /proc/stat - cpu 2255 34 2290 22625563 6290 127 456 0 0 0 - cpu0 1132 34 1441 11311718 3675 127 438 0 0 0 - cpu1 1123 0 849 11313845 2614 0 18 0 0 0 - intr 114930548 113199788 3 0 5 263 0 4 [... lots more numbers ...] - ctxt 1990473 - btime 1062191376 - processes 2915 - procs_running 1 + cpu 237902850 368826709 106375398 1873517540 1135548 0 14507935 0 0 0 + cpu0 60045249 91891769 26331539 468411416 495718 0 5739640 0 0 0 + cpu1 59746288 91759249 26609887 468860630 312281 0 4384817 0 0 0 + cpu2 59489247 92985423 26904446 467808813 171668 0 2268998 0 0 0 + cpu3 58622065 92190267 26529524 468436680 155879 0 2114478 0 0 0 + intr 8688370575 8 3373 0 0 0 0 0 0 1 40791 0 0 353317 0 0 0 0 224789828 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 190974333 41958554 123983334 43 0 224593 0 0 0 + ctxt 22848221062 + btime 1605316999 + processes 746787147 + procs_running 2 procs_blocked 0 - softirq 183433 0 21755 12 39 1137 231 21459 2263 + softirq 12121874454 100099120 3938138295 127375644 2795979 187870761 0 173808342 3072582055 52608 224184354 The very first "cpu" line aggregates the numbers in all of the other "cpuN" lines. These numbers identify the amount of time the CPU has spent performing @@ -1520,8 +1522,8 @@ softirq. Information about mounted ext4 file systems can be found in /proc/fs/ext4. Each mounted filesystem will have a directory in /proc/fs/ext4 based on its device name (i.e., /proc/fs/ext4/hdc or -/proc/fs/ext4/dm-0). The files in each per-device directory are shown -in Table 1-12, below. +/proc/fs/ext4/sda9 or /proc/fs/ext4/dm-0). The files in each per-device +directory are shown in Table 1-12, below. .. table:: Table 1-12: Files in /proc/fs/ext4/ @@ -1601,12 +1603,12 @@ can inadvertently disrupt your system, it is advisable to read both documentation and source before actually making adjustments. In any case, be very careful when writing to any of these files. The entries in /proc may change slightly between the 2.1.* and the 2.2 kernel, so if there is any doubt -review the kernel documentation in the directory /usr/src/linux/Documentation. +review the kernel documentation in the directory linux/Documentation. This chapter is heavily based on the documentation included in the pre 2.2 kernels, and became part of it in version 2.2.1 of the Linux kernel. -Please see: Documentation/admin-guide/sysctl/ directory for descriptions of these -entries. +Please see: Documentation/admin-guide/sysctl/ directory for descriptions of +these entries. Summary ------- From 85bf9a0ee2dd3bf6e506e531f4630fd50ecf1bfe Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Mon, 13 Mar 2023 14:07:17 +0100 Subject: [PATCH 052/291] docs: filesystems: vfs: actualize struct file_system_type description Added descriptions for: - fscontext API ('init_fs_context' method, 'parameters' field) - 'fs_supers' field Cc: Eric Biggers Cc: Miklos Szeredi Cc: Al Viro Cc: Christian Brauner Cc: linux-fsdevel@vger.kernel.org Cc: linux-doc@vger.kernel.org Signed-off-by: Alexander Mikhalitsyn Reviewed-by: Christian Brauner Link: https://lore.kernel.org/r/20230313130718.253708-2-aleksandr.mikhalitsyn@canonical.com Signed-off-by: Jonathan Corbet --- Documentation/filesystems/vfs.rst | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index f3b344f0c0a4..120c42804689 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -107,7 +107,7 @@ file /proc/filesystems. struct file_system_type ----------------------- -This describes the filesystem. As of kernel 2.6.39, the following +This describes the filesystem. The following members are defined: .. code-block:: c @@ -115,14 +115,24 @@ members are defined: struct file_system_type { const char *name; int fs_flags; + int (*init_fs_context)(struct fs_context *); + const struct fs_parameter_spec *parameters; struct dentry *(*mount) (struct file_system_type *, int, - const char *, void *); + const char *, void *); void (*kill_sb) (struct super_block *); struct module *owner; struct file_system_type * next; - struct list_head fs_supers; + struct hlist_head fs_supers; + struct lock_class_key s_lock_key; struct lock_class_key s_umount_key; + struct lock_class_key s_vfs_rename_key; + struct lock_class_key s_writers_key[SB_FREEZE_LEVELS]; + + struct lock_class_key i_lock_key; + struct lock_class_key i_mutex_key; + struct lock_class_key invalidate_lock_key; + struct lock_class_key i_mutex_dir_key; }; ``name`` @@ -132,6 +142,15 @@ members are defined: ``fs_flags`` various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.) +``init_fs_context`` + Initializes 'struct fs_context' ->ops and ->fs_private fields with + filesystem-specific data. + +``parameters`` + Pointer to the array of filesystem parameters descriptors + 'struct fs_parameter_spec'. + More info in Documentation/filesystems/mount_api.rst. + ``mount`` the method to call when a new instance of this filesystem should be mounted @@ -148,7 +167,11 @@ members are defined: ``next`` for internal VFS use: you should initialize this to NULL - s_lock_key, s_umount_key: lockdep-specific +``fs_supers`` + for internal VFS use: hlist of filesystem instances (superblocks) + + s_lock_key, s_umount_key, s_vfs_rename_key, s_writers_key, + i_lock_key, i_mutex_key, invalidate_lock_key, i_mutex_dir_key: lockdep-specific The mount() method has the following arguments: From 592d80727f28472316ceabf22d91a1b5d27adb7e Mon Sep 17 00:00:00 2001 From: Alexander Mikhalitsyn Date: Mon, 13 Mar 2023 14:07:18 +0100 Subject: [PATCH 053/291] docs: filesystems: vfs: actualize struct super_operations description Added/updated descriptions for super_operations: - free_inode method - evict_inode method - freeze_super/thaw_super method - show_{devname,path,stats} procfs-related methods - get_dquots method Cc: Eric Biggers Cc: Miklos Szeredi Cc: Al Viro Cc: Christian Brauner Cc: linux-fsdevel@vger.kernel.org Cc: linux-doc@vger.kernel.org Signed-off-by: Alexander Mikhalitsyn Reviewed-by: Christian Brauner Link: https://lore.kernel.org/r/20230313130718.253708-3-aleksandr.mikhalitsyn@canonical.com Signed-off-by: Jonathan Corbet --- Documentation/filesystems/vfs.rst | 74 ++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/Documentation/filesystems/vfs.rst b/Documentation/filesystems/vfs.rst index 120c42804689..769be5230210 100644 --- a/Documentation/filesystems/vfs.rst +++ b/Documentation/filesystems/vfs.rst @@ -245,33 +245,42 @@ struct super_operations ----------------------- This describes how the VFS can manipulate the superblock of your -filesystem. As of kernel 2.6.22, the following members are defined: +filesystem. The following members are defined: .. code-block:: c struct super_operations { struct inode *(*alloc_inode)(struct super_block *sb); void (*destroy_inode)(struct inode *); + void (*free_inode)(struct inode *); void (*dirty_inode) (struct inode *, int flags); - int (*write_inode) (struct inode *, int); - void (*drop_inode) (struct inode *); - void (*delete_inode) (struct inode *); + int (*write_inode) (struct inode *, struct writeback_control *wbc); + int (*drop_inode) (struct inode *); + void (*evict_inode) (struct inode *); void (*put_super) (struct super_block *); int (*sync_fs)(struct super_block *sb, int wait); + int (*freeze_super) (struct super_block *); int (*freeze_fs) (struct super_block *); + int (*thaw_super) (struct super_block *); int (*unfreeze_fs) (struct super_block *); int (*statfs) (struct dentry *, struct kstatfs *); int (*remount_fs) (struct super_block *, int *, char *); - void (*clear_inode) (struct inode *); void (*umount_begin) (struct super_block *); int (*show_options)(struct seq_file *, struct dentry *); + int (*show_devname)(struct seq_file *, struct dentry *); + int (*show_path)(struct seq_file *, struct dentry *); + int (*show_stats)(struct seq_file *, struct dentry *); ssize_t (*quota_read)(struct super_block *, int, char *, size_t, loff_t); ssize_t (*quota_write)(struct super_block *, int, const char *, size_t, loff_t); - int (*nr_cached_objects)(struct super_block *); - void (*free_cached_objects)(struct super_block *, int); + struct dquot **(*get_dquots)(struct inode *); + + long (*nr_cached_objects)(struct super_block *, + struct shrink_control *); + long (*free_cached_objects)(struct super_block *, + struct shrink_control *); }; All methods are called without any locks being held, unless otherwise @@ -292,6 +301,11 @@ or bottom half). ->alloc_inode was defined and simply undoes anything done by ->alloc_inode. +``free_inode`` + this method is called from RCU callback. If you use call_rcu() + in ->destroy_inode to free 'struct inode' memory, then it's + better to release memory in this method. + ``dirty_inode`` this method is called by the VFS when an inode is marked dirty. This is specifically for the inode itself being marked dirty, @@ -319,8 +333,12 @@ or bottom half). practice of using "force_delete" in the put_inode() case, but does not have the races that the "force_delete()" approach had. -``delete_inode`` - called when the VFS wants to delete an inode +``evict_inode`` + called when the VFS wants to evict an inode. Caller does + *not* evict the pagecache or inode-associated metadata buffers; + the method has to use truncate_inode_pages_final() to get rid + of those. Caller makes sure async writeback cannot be running for + the inode while (or after) ->evict_inode() is called. Optional. ``put_super`` called when the VFS wishes to free the superblock @@ -331,14 +349,25 @@ or bottom half). superblock. The second parameter indicates whether the method should wait until the write out has been completed. Optional. +``freeze_super`` + Called instead of ->freeze_fs callback if provided. + Main difference is that ->freeze_super is called without taking + down_write(&sb->s_umount). If filesystem implements it and wants + ->freeze_fs to be called too, then it has to call ->freeze_fs + explicitly from this callback. Optional. + ``freeze_fs`` called when VFS is locking a filesystem and forcing it into a consistent state. This method is currently used by the Logical - Volume Manager (LVM). + Volume Manager (LVM) and ioctl(FIFREEZE). Optional. + +``thaw_super`` + called when VFS is unlocking a filesystem and making it writable + again after ->freeze_super. Optional. ``unfreeze_fs`` called when VFS is unlocking a filesystem and making it writable - again. + again after ->freeze_fs. Optional. ``statfs`` called when the VFS needs to get filesystem statistics. @@ -347,22 +376,37 @@ or bottom half). called when the filesystem is remounted. This is called with the kernel lock held -``clear_inode`` - called then the VFS clears the inode. Optional - ``umount_begin`` called when the VFS is unmounting a filesystem. ``show_options`` - called by the VFS to show mount options for /proc//mounts. + called by the VFS to show mount options for /proc//mounts + and /proc//mountinfo. (see "Mount Options" section) +``show_devname`` + Optional. Called by the VFS to show device name for + /proc//{mounts,mountinfo,mountstats}. If not provided then + '(struct mount).mnt_devname' will be used. + +``show_path`` + Optional. Called by the VFS (for /proc//mountinfo) to show + the mount root dentry path relative to the filesystem root. + +``show_stats`` + Optional. Called by the VFS (for /proc//mountstats) to show + filesystem-specific mount statistics. + ``quota_read`` called by the VFS to read from filesystem quota file. ``quota_write`` called by the VFS to write to filesystem quota file. +``get_dquots`` + called by quota to get 'struct dquot' array for a particular inode. + Optional. + ``nr_cached_objects`` called by the sb cache shrinking function for the filesystem to return the number of freeable cached objects it contains. From 456ef6b08364de29b0f2c851577f1ec87815c8e2 Mon Sep 17 00:00:00 2001 From: Carlos Bilbao Date: Fri, 10 Mar 2023 10:36:51 -0600 Subject: [PATCH 054/291] docs/sp_SP: Add translation of process/deprecated Translate Documentation/process/deprecated.rst into Spanish. Co-developed-by: Sergio Gonzalez Signed-off-by: Sergio Gonzalez Signed-off-by: Carlos Bilbao Link: https://lore.kernel.org/r/20230310163651.2500175-1-carlos.bilbao@amd.com Signed-off-by: Jonathan Corbet --- .../translations/sp_SP/process/deprecated.rst | 381 ++++++++++++++++++ .../translations/sp_SP/process/index.rst | 1 + 2 files changed, 382 insertions(+) create mode 100644 Documentation/translations/sp_SP/process/deprecated.rst diff --git a/Documentation/translations/sp_SP/process/deprecated.rst b/Documentation/translations/sp_SP/process/deprecated.rst new file mode 100644 index 000000000000..d52120e0d753 --- /dev/null +++ b/Documentation/translations/sp_SP/process/deprecated.rst @@ -0,0 +1,381 @@ +.. include:: ../disclaimer-sp.rst + +:Original: :ref:`Documentation/process/deprecated.rst ` +:Translator: Sergio Gonzalez + +.. _sp_deprecated: + +============================================================================ +Interfaces obsoletos, Características del lenguaje, Atributos y Convenciones +============================================================================ + +En un mundo perfecto, sería posible convertir todas las instancias de +alguna API obsoleta en una nueva API y quitar la API anterior en un +único ciclo de desarrollo. Desafortunadamente, debido al tamaño del kernel, +la jerarquía de mantenimiento, y el tiempo, no siempre es posible hacer +estos cambios de una única vez. Esto significa que las nuevas instancias +han de ir creándose en el kernel, mientras que las antiguas se quitan, +haciendo que la cantidad de trabajo para limpiar las APIs crezca. Para +informar a los desarrolladores sobre qué ha sido declarado obsoleto y por +qué, ha sido creada esta lista como un lugar donde indicar cuando los usos +obsoletos son propuestos para incluir en el kernel. + +__deprecated +------------ +Mientras que este atributo señala visualmente que un interface ha sido +declarado obsoleto, este `no produce más avisos durante las compilaciones +`_ +porque uno de los objetivos del kernel es que compile sin avisos, y +nadie ha hecho nada para quitar estos interfaces obsoletos. Mientras +que usar `__deprecated` es sencillo para anotar una API obsoleta en +un archivo de cabecera, no es la solución completa. Dichos interfaces +deben o bien ser quitados por completo, o añadidos a este archivo para +desanimar a otros a usarla en el futuro. + +BUG() y BUG_ON() +---------------- +Use WARN() y WARN_ON() en su lugar, y gestione las condiciones de error +"imposibles" tan elegantemente como se pueda. Mientras que la familia de +funciones BUG() fueron originalmente diseñadas para actuar como una +"situación imposible", confirmar y disponer de un hilo del kernel de forma +"segura", estas funciones han resultado ser demasiado arriesgadas. (e.g. +"¿en qué orden se necesitan liberar los locks? ¿Se han restaurado sus +estados?). La popular función BUG() desestabilizará el sistema o lo romperá +totalmente, lo cual hace imposible depurarlo o incluso generar reportes de +crash. Linus tiene una `opinión muy fuerte +`_ +y sentimientos `sobre esto +`_. + +Nótese que la familia de funciones WARN() únicamente debería ser usada +en situaciones que se "esperan no sean alcanzables". Si se quiere +avisar sobre situaciones "alcanzables pero no deseadas", úsese la familia +de funciones pr_warn(). Los responsables del sistema pueden haber definido +*panic_on_warn* sysctl para asegurarse que sus sistemas no continúan +ejecutándose en presencia del condiciones "no alcanzables". (Por ejemplo, +véase commits como `este +`_.) + +Operaciones aritméticas en los argumentos de reserva de memoria +--------------------------------------------------------------- +Los cálculos dinámicos de tamaño (especialmente multiplicaciones) no +deberían realizarse en los argumentos de reserva de memoria (o similares) +debido al riesgo de desbordamiento. Esto puede llevar a valores rotando y +que se realicen reservas de memoria menores que las que se esperaban. El +uso de esas reservas puede llevar a desbordamientos en el 'heap' de memoria +y otros funcionamientos incorrectos. (Una excepción a esto son los valores +literales donde el compilador si puede avisar si estos puede desbordarse. +De todos modos, el método recomendado en estos caso es reescribir el código +como se sugiere a continuación para evitar las operaciones aritméticas en +la reserva de memoria.) + +Por ejemplo, no utilice `count * size`` como argumento, como en:: + + foo = kmalloc(count * size, GFP_KERNEL); + +En vez de eso, utilice la reserva con dos argumentos:: + + foo = kmalloc_array(count, size, GFP_KERNEL); + +Específicamente, kmalloc() puede ser sustituido con kmalloc_array(), +kzalloc() puede ser sustituido con kcalloc(). + +Si no existen funciones con dos argumentos, utilice las funciones que se +saturan, en caso de desbordamiento:: + + bar = vmalloc(array_size(count, size)); + +Otro caso común a evitar es calcular el tamaño de una estructura com +la suma de otras estructuras, como en:: + + header = kzalloc(sizeof(*header) + count * sizeof(*header->item), + GFP_KERNEL); + +En vez de eso emplee:: + + header = kzalloc(struct_size(header, item, count), GFP_KERNEL); + +.. note:: Si se usa struct_size() en una estructura que contiene un elemento + de longitud cero o un array de un único elemento como un array miembro, + por favor reescribir ese uso y cambiar a un `miembro array flexible + <#zero-length-and-one-element-arrays>`_ + + +Para otros cálculos, por favor use las funciones de ayuda: size_mul(), +size_add(), and size_sub(). Por ejemplo, en el caso de:: + + foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); + +Re-escríbase, como:: + + foo = krealloc(size_add(current_size, + size_mul(chunk_size, + size_sub(count, 3))), GFP_KERNEL); + +Para más detalles, mire también array3_size() y flex_array_size(), +como también la familia de funciones relacionadas check_mul_overflow(), +check_add_overflow(), check_sub_overflow(), y check_shl_overflow(). + + +simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() +---------------------------------------------------------------------- +Las funciones: simple_strtol(), simple_strtoll(), simple_strtoul(), y +simple_strtoull() explícitamente ignoran los desbordamientos, lo que puede +llevar a resultados inesperados por las funciones que las llaman. Las +funciones respectivas kstrtol(), kstrtoll(), kstrtoul(), y kstrtoull() +tienden a ser reemplazos correctos, aunque nótese que necesitarán que la +cadena de caracteres termine en NUL o en el carácter de línea nueva. + + +strcpy() +-------- +strcpy() no realiza verificaciones de los límites del buffer de destino. +Esto puede resultar en desbordamientos lineals más allá del fin del buffer, +causando todo tipo de errores. Mientras `CONFIG_FORTIFY_SOURCE=y` otras +varias opciones de compilación reducen el riesgo de usar esta función, no +hay ninguna buena razón para añadir nuevos usos de esta. El remplazo seguro +es la función strscpy(), aunque se ha de tener cuidado con cualquier caso +en el el valor retornado por strcpy() sea usado, ya que strscpy() no +devuelve un puntero a el destino, sino el número de caracteres no nulos +compilados (o el valor negativo de errno cuando se trunca la cadena de +caracteres). + +strncpy() en cadenas de caracteres terminadas en NUL +---------------------------------------------------- +El uso de strncpy() no garantiza que el buffer de destino esté terminado en +NUL. Esto puede causar varios errores de desbordamiento en lectura y otros +tipos de funcionamiento erróneo debido a que falta la terminación en NUL. +Esta función también termina la cadena de caracteres en NUL en el buffer de +destino si la cadena de origen es más corta que el buffer de destino, lo +cual puede ser una penalización innecesaria para funciones usen esta +función con cadenas de caracteres que sí están terminadas en NUL. + +Cuando se necesita que la cadena de destino sea terminada en NUL, +el mejor reemplazo es usar la función strscpy(), aunque se ha de tener +cuidado en los casos en los que el valor de strncpy() fuera usado, ya que +strscpy() no devuelve un puntero al destino, sino el número de +caracteres no nulos copiados (o el valor negativo de errno cuando se trunca +la cadena de caracteres). Cualquier caso restante que necesitase todavía +ser terminado en el caracter nulo, debería usar strscpy_pad(). + +Si una función usa cadenas de caracteres que no necesitan terminar en NUL, +debería usarse strtomem(), y el destino debería señalarse con el atributo +`__nonstring +`_ +para evitar avisos futuros en el compilador. Para casos que todavía +necesitan cadenas de caracteres que se rellenen al final con el +caracter NUL, usar strtomem_pad(). + +strlcpy() +--------- +strlcpy() primero lee por completo el buffer de origen (ya que el valor +devuelto intenta ser el mismo que el de strlen()). Esta lectura puede +sobrepasar el límite de tamaño del destino. Esto ineficiente y puede causar +desbordamientos de lectura si la cadena de origen no está terminada en el +carácter NUL. El reemplazo seguro de esta función es strscpy(), pero se ha +de tener cuidado que en los casos en lso que se usase el valor devuelto de +strlcpy(), ya que strscpy() devolverá valores negativos de erno cuando se +produzcan truncados. + +Especificación de formato %p +---------------------------- +Tradicionalmente,el uso de "%p" en el formato de cadenas de caracteres +resultaría en exponer esas direcciones en dmesg, proc, sysfs, etc. En vez +de dejar que sean una vulnerabilidad, todos los "%p" que se usan en el +kernel se imprimen como un hash, haciéndolos efectivamente inutilizables +para usarlos como direcciones de memoria. Nuevos usos de "%p" no deberían +ser añadidos al kernel. Para textos de direcciones, usar "%pS" es +mejor, ya que resulta en el nombre del símbolo. Para prácticamente el +resto de casos, mejor no usar "%p" en absoluto. + +Parafraseando las actuales `direcciones de Linus `_: + +- Si el valor "hasheado" "%p" no tienen ninguna finalidad, preguntarse si el + puntero es realmente importante. ¿Quizás se podría quitar totalmente? +- Si realmente se piensa que el valor del puntero es importante, ¿porqué + algún estado del sistema o nivel de privilegio de usuario es considerado + "especial"? Si piensa que puede justificarse (en comentarios y mensajes + del commit), de forma suficiente como para pasar el escrutinio de Linux, + quizás pueda usar el "%p", a la vez que se asegura que tiene los permisos + correspondientes. + +Si está depurando algo donde el "%p" hasheado está causando problemas, +se puede arrancar temporalmente con la opción de depuración "`no_hash_pointers +`_". + + +Arrays de longitud variable (VLAs) +---------------------------------- +Usando VLA en la pila (stack) produce un código mucho peor que los arrays +de tamaño estático. Mientras que estos errores no triviales de `rendimiento +`_ son razón suficiente +para no usar VLAs, esto además son un riesgo de seguridad. El crecimiento +dinámico del array en la pila, puede exceder la memoria restante en +el segmento de la pila. Esto podría llevara a un fallo, posible sobre-escritura +de contenido al final de la pila (cuando se construye sin +`CONFIG_THREAD_INFO_IN_TASK=y`), o sobre-escritura de la memoria adyacente +a la pila (cuando se construye sin `CONFIG_VMAP_STACK=y`). + + +Switch case fall-through implícito +---------------------------------- +El lenguaje C permite a las sentencias 'switch' saltar de un caso al +siguiente caso cuando la sentencia de ruptura "break" no aparece al final +del caso. Esto, introduce ambigüedad en el código, ya que no siempre está +claro si el 'break' que falta es intencionado o un olvido. Por ejemplo, no +es obvio solamente mirando al código si `STATE_ONE` está escrito para +intencionadamente saltar en `STATE_TWO`:: + + switch (value) { + case STATE_ONE: + do_something(); + case STATE_TWO: + do_other(); + break; + default: + WARN("unknown state"); + } + +Ya que ha habido una larga lista de defectos `debidos a declaraciones de "break" +que faltan `_, no se +permiten 'fall-through' implícitos. Para identificar 'fall-through' +intencionados, se ha adoptado la pseudo-palabra-clave macro "falltrhrough", +que expande las extensiones de gcc `__attribute__((__fallthrough__)) +`_. +(Cuando la sintaxis de C17/c18 `[[fallthrough]]` sea más comúnmente +soportadas por los compiladores de C, analizadores estáticos, e IDEs, +se puede cambiar a usar esa sintaxis para esa pseudo-palabra-clave. + +Todos los bloques switch/case deben acabar en uno de: + +* break; +* fallthrough; +* continue; +* goto