summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 20:47:48 +0300
committerLinus Torvalds <torvalds@linux-foundation.org>2022-12-13 20:47:48 +0300
commitc76ff350bd57682ae12bea6383dd8baf4824ac96 (patch)
tree35b5e26c81e0ea1bed8c68696c5878c353923cb6
parent57888f7b952d3f2696f82a701f1b3d9de7e346d3 (diff)
parent577cc1434e4cc1342c3df6d6a3c85136ab335c81 (diff)
downloadlinux-c76ff350bd57682ae12bea6383dd8baf4824ac96.tar.xz
Merge tag 'lsm-pr-20221212' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
Pull lsm updates from Paul Moore: - Improve the error handling in the device cgroup such that memory allocation failures when updating the access policy do not potentially alter the policy. - Some minor fixes to reiserfs to ensure that it properly releases LSM-related xattr values. - Update the security_socket_getpeersec_stream() LSM hook to take sockptr_t values. Previously the net/BPF folks updated the getsockopt code in the network stack to leverage the sockptr_t type to make it easier to pass both kernel and __user pointers, but unfortunately when they did so they didn't convert the LSM hook. While there was/is no immediate risk by not converting the LSM hook, it seems like this is a mistake waiting to happen so this patch proactively does the LSM hook conversion. - Convert vfs_getxattr_alloc() to return an int instead of a ssize_t and cleanup the callers. Internally the function was never going to return anything larger than an int and the callers were doing some very odd things casting the return value; this patch fixes all that and helps bring a bit of sanity to vfs_getxattr_alloc() and its callers. - More verbose, and helpful, LSM debug output when the system is booted with "lsm.debug" on the command line. There are examples in the commit description, but the quick summary is that this patch provides better information about which LSMs are enabled and the ordering in which they are processed. - General comment and kernel-doc fixes and cleanups. * tag 'lsm-pr-20221212' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm: lsm: Fix description of fs_context_parse_param lsm: Add/fix return values in lsm_hooks.h and fix formatting lsm: Clarify documentation of vm_enough_memory hook reiserfs: Add missing calls to reiserfs_security_free() lsm,fs: fix vfs_getxattr_alloc() return type and caller error paths device_cgroup: Roll back to original exceptions after copy failure LSM: Better reporting of actual LSMs at boot lsm: make security_socket_getpeersec_stream() sockptr_t safe audit: Fix some kernel-doc warnings lsm: remove obsoleted comments for security hooks fs: edit a comment made in bad taste
-rw-r--r--fs/reiserfs/namei.c4
-rw-r--r--fs/reiserfs/xattr_security.c2
-rw-r--r--fs/xattr.c5
-rw-r--r--include/linux/fs_context.h2
-rw-r--r--include/linux/lsm_hook_defs.h2
-rw-r--r--include/linux/lsm_hooks.h241
-rw-r--r--include/linux/security.h11
-rw-r--r--include/linux/xattr.h6
-rw-r--r--net/core/sock.c3
-rw-r--r--security/apparmor/domain.c3
-rw-r--r--security/apparmor/lsm.c29
-rw-r--r--security/commoncap.c22
-rw-r--r--security/device_cgroup.c33
-rw-r--r--security/integrity/evm/evm_crypto.c5
-rw-r--r--security/integrity/evm/evm_main.c7
-rw-r--r--security/integrity/ima/ima.h5
-rw-r--r--security/integrity/ima/ima_appraise.c6
-rw-r--r--security/integrity/ima/ima_main.c6
-rw-r--r--security/integrity/ima/ima_template_lib.c11
-rw-r--r--security/lsm_audit.c1
-rw-r--r--security/security.c51
-rw-r--r--security/selinux/hooks.c13
-rw-r--r--security/smack/smack_lsm.c19
23 files changed, 295 insertions, 192 deletions
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c
index 4d428e8704bc..0b8aa99749f1 100644
--- a/fs/reiserfs/namei.c
+++ b/fs/reiserfs/namei.c
@@ -696,6 +696,7 @@ static int reiserfs_create(struct user_namespace *mnt_userns, struct inode *dir,
out_failed:
reiserfs_write_unlock(dir->i_sb);
+ reiserfs_security_free(&security);
return retval;
}
@@ -779,6 +780,7 @@ static int reiserfs_mknod(struct user_namespace *mnt_userns, struct inode *dir,
out_failed:
reiserfs_write_unlock(dir->i_sb);
+ reiserfs_security_free(&security);
return retval;
}
@@ -878,6 +880,7 @@ static int reiserfs_mkdir(struct user_namespace *mnt_userns, struct inode *dir,
retval = journal_end(&th);
out_failed:
reiserfs_write_unlock(dir->i_sb);
+ reiserfs_security_free(&security);
return retval;
}
@@ -1194,6 +1197,7 @@ static int reiserfs_symlink(struct user_namespace *mnt_userns,
retval = journal_end(&th);
out_failed:
reiserfs_write_unlock(parent_dir->i_sb);
+ reiserfs_security_free(&security);
return retval;
}
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index 8965c8e5e172..857a65b05726 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -50,6 +50,7 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
int error;
sec->name = NULL;
+ sec->value = NULL;
/* Don't add selinux attributes on xattrs - they'll never get used */
if (IS_PRIVATE(dir))
@@ -95,7 +96,6 @@ int reiserfs_security_write(struct reiserfs_transaction_handle *th,
void reiserfs_security_free(struct reiserfs_security_handle *sec)
{
- kfree(sec->name);
kfree(sec->value);
sec->name = NULL;
sec->value = NULL;
diff --git a/fs/xattr.c b/fs/xattr.c
index 86668d2ce268..28f61fcb8f69 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -368,11 +368,12 @@ out_noalloc:
* vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
*
* Allocate memory, if not already allocated, or re-allocate correct size,
- * before retrieving the extended attribute.
+ * before retrieving the extended attribute. The xattr value buffer should
+ * always be freed by the caller, even on error.
*
* Returns the result of alloc, if failed, or the getxattr operation.
*/
-ssize_t
+int
vfs_getxattr_alloc(struct user_namespace *mnt_userns, struct dentry *dentry,
const char *name, char **xattr_value, size_t xattr_size,
gfp_t flags)
diff --git a/include/linux/fs_context.h b/include/linux/fs_context.h
index 87a34f2fa68d..5469ffee21c7 100644
--- a/include/linux/fs_context.h
+++ b/include/linux/fs_context.h
@@ -99,7 +99,7 @@ struct fs_context {
const struct cred *cred; /* The mounter's credentials */
struct p_log log; /* Logging buffer */
const char *source; /* The source name (eg. dev path) */
- void *security; /* Linux S&M options */
+ void *security; /* LSM options */
void *s_fs_info; /* Proposed s_fs_info */
unsigned int sb_flags; /* Proposed superblock flags (SB_*) */
unsigned int sb_flags_mask; /* Superblock flags that were changed */
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 3c984cadb88e..ed6cb2ac55fa 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -309,7 +309,7 @@ LSM_HOOK(int, 0, socket_setsockopt, struct socket *sock, int level, int optname)
LSM_HOOK(int, 0, socket_shutdown, struct socket *sock, int how)
LSM_HOOK(int, 0, socket_sock_rcv_skb, struct sock *sk, struct sk_buff *skb)
LSM_HOOK(int, 0, socket_getpeersec_stream, struct socket *sock,
- char __user *optval, int __user *optlen, unsigned len)
+ sockptr_t optval, sockptr_t optlen, unsigned int len)
LSM_HOOK(int, 0, socket_getpeersec_dgram, struct socket *sock,
struct sk_buff *skb, u32 *secid)
LSM_HOOK(int, 0, sk_alloc_security, struct sock *sk, int family, gfp_t priority)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index dfba3923c76b..0a5ba81f7367 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -92,13 +92,14 @@
* 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
+ * @param The parameter.
*
* Security hooks for filesystem operations.
*
@@ -118,6 +119,7 @@
* 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.
@@ -136,31 +138,24 @@
* @flags contains the mount flags.
* @data contains the filesystem-specific data.
* Return 0 if permission is granted.
- * @sb_copy_data:
- * Allow mount option data to be copied prior to parsing by the filesystem,
- * so that the security module can extract security-specific mount
- * options cleanly (a filesystem may modify the data e.g. with strsep()).
- * This also allows the original mount data to be stripped of security-
- * specific options to avoid having to make filesystems aware of them.
- * @orig the original mount data copied from userspace.
- * @copy copied data which will be passed to the security module.
- * Returns 0 if the copy was successful.
* @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
+ * @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
+ * @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.
+ * 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.
@@ -174,31 +169,31 @@
* 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
+ * @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
- * @sb_parse_opts_str:
- * Parse a string of security data filling in the opts structure
- * @options string containing all mount options known by the LSM
- * @opts binary data structure usable by the LSM
+ * @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
+ * @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
@@ -206,9 +201,10 @@
* 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
+ * @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.
@@ -236,7 +232,7 @@
* 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
+ * @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.
@@ -247,9 +243,9 @@
* 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
+ * @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:
@@ -365,7 +361,7 @@
* 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 <include/uapi/linux/stat.h>
+ * constants from <include/uapi/linux/stat.h>.
* Return 0 if permission is granted.
* @path_chown:
* Check for permission to change owner/group of a file or directory.
@@ -380,6 +376,7 @@
* @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.
@@ -387,7 +384,7 @@
* @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
+ * @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:
@@ -453,9 +450,9 @@
* 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 of the call should return a
- * value via the buffer or just the value length Return size of buffer on
- * success.
+ * 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
@@ -478,7 +475,7 @@
* @inode_killpriv:
* The setuid bit is being removed. Remove similar security labels.
* Called with the dentry->d_inode->i_mutex held.
- * @mnt_userns: user namespace of the mount
+ * @mnt_userns: user namespace 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.
@@ -505,20 +502,22 @@
* 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.
+ * Fill in @inode security information for a @dentry if allowed.
* @getprocattr:
- * Read attribute @name for process @p and store it into @value if allowed.
+ * 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.
+ * 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:
* 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
+ * @kn_dir the parent kernfs node.
+ * @kn the new child kernfs node.
+ * Return 0 if permission is granted.
*
* Security hooks for file operations
*
@@ -557,11 +556,11 @@
* 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 :
+ * @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 :
+ * @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).
@@ -622,6 +621,7 @@
* 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.
*
@@ -639,6 +639,7 @@
* @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.
@@ -647,6 +648,7 @@
* @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.
@@ -658,7 +660,7 @@
* @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
+ * @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:
@@ -671,19 +673,19 @@
* @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
+ * @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
+ * @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
+ * @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.
@@ -691,7 +693,7 @@
* 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
+ * @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:
@@ -700,7 +702,7 @@
* by the kernel.
* @buf pointer to buffer containing the file contents.
* @size length of the file contents.
- * @id kernel read file identifier
+ * @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.
@@ -710,7 +712,7 @@
* 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 replaces
+ * @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:
@@ -762,7 +764,7 @@
* @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
+ * @ioprio contains the new ioprio value.
* Return 0 if permission is granted.
* @task_getioprio:
* Check permission before getting the ioprio value of @p.
@@ -893,6 +895,7 @@
* @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.
@@ -976,14 +979,15 @@
* 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 userspace memory where the security state is to be copied.
- * @optlen userspace int where the module should copy the actual length
+ * @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.
@@ -1003,6 +1007,7 @@
* @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:
@@ -1015,17 +1020,19 @@
* @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
+ * 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
+ * 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
+ * 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:
@@ -1036,21 +1043,25 @@
* @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
+ * @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
*
@@ -1083,6 +1094,7 @@
* 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
*
@@ -1091,15 +1103,17 @@
* @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
+ * Returns 0 on success, non-zero on failure.
* @ib_free_security:
* Deallocate an Infiniband security structure.
* @sec contains the security structure to be freed.
@@ -1111,10 +1125,11 @@
* 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)
- * @gfp is to specify the context for the allocation
+ * 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.
@@ -1122,11 +1137,12 @@
* 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
+ * @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.
@@ -1152,6 +1168,7 @@
* @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.
@@ -1180,7 +1197,7 @@
* 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
+ * @flags is the allocation flags.
* Return 0 if permission is granted, -ve error otherwise.
* @key_free:
* Notification of destruction; free security data.
@@ -1210,8 +1227,8 @@
*
* @ipc_permission:
* Check permissions for access to IPC
- * @ipcp contains the kernel IPC permission structure
- * @flag contains the desired (requested) permission set
+ * @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.
@@ -1356,15 +1373,18 @@
* 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
@@ -1406,32 +1426,39 @@
* 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
+ * @ns contains the user namespace we want the capability in.
* @cap contains the capability <include/linux/capability.h>.
- * @opts contains options for the capable check <include/linux/security.h>
+ * @opts contains options for the capable check <include/linux/security.h>.
* Return 0 if the capability is granted for @tsk.
* @quotactl:
- * Check whether the quotactl syscall is allowed for this @sb.
+ * 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.
+ * 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 <include/linux/syslog.h>
+ * @type contains the SYSLOG_ACTION_* constant from
+ * <include/linux/syslog.h>.
* Return 0 if permission is granted.
* @settime:
* Check permission to change the system time.
* struct timespec64 is defined in <include/linux/time64.h> and timezone
* is defined in <include/linux/time.h>
- * @ts contains new time
- * @tz contains new timezone
+ * @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.
+ * 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
@@ -1449,11 +1476,13 @@
* @secid contains the security ID.
* @secdata contains the pointer that stores the converted security
* context.
- * @seclen pointer which contains the length of the data
+ * @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.
@@ -1490,7 +1519,7 @@
* @audit_rule_free:
* Deallocate the LSM audit rule structure previously allocated by
* audit_rule_init.
- * @lsmrule contains the allocated rule
+ * @lsmrule contains the allocated rule.
*
* @inode_invalidate_secctx:
* Notify the security module that it must revalidate the security context
@@ -1507,6 +1536,7 @@
* @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
@@ -1520,6 +1550,7 @@
* @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
@@ -1527,6 +1558,7 @@
* @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:
*
@@ -1534,13 +1566,15 @@
* 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
+ * @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.
*
* Security hooks for using the eBPF maps and programs functionalities through
* eBPF syscalls.
@@ -1549,65 +1583,74 @@
* 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
+ * @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.
- *
- * @what: kernel feature being accessed
+ * 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.
*
* Security hooks for perf events
*
* @perf_event_open:
- * Check whether the @type of perf_event_open syscall is allowed.
+ * 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.
+ * Allocate and save perf_event security info.
+ * Return 0 on success, error on failure.
* @perf_event_free:
- * Release (free) perf_event security info.
+ * Release (free) perf_event security info.
* @perf_event_read:
- * Read perf_event security info if allowed.
+ * Read perf_event security info if allowed.
+ * Return 0 if permission is granted.
* @perf_event_write:
- * Write perf_event security info if allowed.
+ * Write perf_event security info if allowed.
+ * 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
+ * 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).
+ * 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.
+ * Check whether the file_operations uring_cmd is allowed to run.
+ * Return 0 if permission is granted.
*
*/
union security_list_options {
diff --git a/include/linux/security.h b/include/linux/security.h
index 316f42716105..5b67f208f7de 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -31,6 +31,7 @@
#include <linux/err.h>
#include <linux/string.h>
#include <linux/mm.h>
+#include <linux/sockptr.h>
struct linux_binprm;
struct cred;
@@ -1446,8 +1447,8 @@ int security_socket_getsockopt(struct socket *sock, int level, int optname);
int security_socket_setsockopt(struct socket *sock, int level, int optname);
int security_socket_shutdown(struct socket *sock, int how);
int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb);
-int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len);
+int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval,
+ sockptr_t optlen, unsigned int len);
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid);
int security_sk_alloc(struct sock *sk, int family, gfp_t priority);
void security_sk_free(struct sock *sk);
@@ -1583,8 +1584,10 @@ static inline int security_sock_rcv_skb(struct sock *sk,
return 0;
}
-static inline int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len)
+static inline int security_socket_getpeersec_stream(struct socket *sock,
+ sockptr_t optval,
+ sockptr_t optlen,
+ unsigned int len)
{
return -ENOPROTOOPT;
}
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index c5238744bab9..707374bab4c4 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -74,9 +74,9 @@ int __vfs_removexattr_locked(struct user_namespace *, struct dentry *,
int vfs_removexattr(struct user_namespace *, struct dentry *, const char *);
ssize_t generic_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size);
-ssize_t vfs_getxattr_alloc(struct user_namespace *mnt_userns,
- struct dentry *dentry, const char *name,
- char **xattr_value, size_t size, gfp_t flags);
+int vfs_getxattr_alloc(struct user_namespace *mnt_userns,
+ struct dentry *dentry, const char *name,
+ char **xattr_value, size_t size, gfp_t flags);
int xattr_supported_namespace(struct inode *inode, const char *prefix);
diff --git a/net/core/sock.c b/net/core/sock.c
index a3ba0358c77c..c9c6af85d9c0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1793,7 +1793,8 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
break;
case SO_PEERSEC:
- return security_socket_getpeersec_stream(sock, optval.user, optlen.user, len);
+ return security_socket_getpeersec_stream(sock,
+ optval, optlen, len);
case SO_MARK:
v.val = sk->sk_mark;
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 7bafb4c4767c..00dc0ec066de 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -311,10 +311,9 @@ static int aa_xattrs_match(const struct linux_binprm *bprm,
struct aa_profile *profile, unsigned int state)
{
int i;
- ssize_t size;
struct dentry *d;
char *value = NULL;
- int value_size = 0, ret = profile->xattr_count;
+ int size, value_size = 0, ret = profile->xattr_count;
if (!bprm || !profile->xattr_count)
return 0;
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index b751d6253977..ff14fe0ffca2 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -1117,11 +1117,10 @@ static struct aa_label *sk_peer_label(struct sock *sk)
* Note: for tcp only valid if using ipsec or cipso on lan
*/
static int apparmor_socket_getpeersec_stream(struct socket *sock,
- char __user *optval,
- int __user *optlen,
+ sockptr_t optval, sockptr_t optlen,
unsigned int len)
{
- char *name;
+ char *name = NULL;
int slen, error = 0;
struct aa_label *label;
struct aa_label *peer;
@@ -1138,23 +1137,21 @@ static int apparmor_socket_getpeersec_stream(struct socket *sock,
/* don't include terminating \0 in slen, it breaks some apps */
if (slen < 0) {
error = -ENOMEM;
- } else {
- if (slen > len) {
- error = -ERANGE;
- } else if (copy_to_user(optval, name, slen)) {
- error = -EFAULT;
- goto out;
- }
- if (put_user(slen, optlen))
- error = -EFAULT;
-out:
- kfree(name);
-
+ goto done;
+ }
+ if (slen > len) {
+ error = -ERANGE;
+ goto done_len;
}
+ if (copy_to_sockptr(optval, name, slen))
+ error = -EFAULT;
+done_len:
+ if (copy_to_sockptr(optlen, &slen, sizeof(slen)))
+ error = -EFAULT;
done:
end_current_label_crit_section(label);
-
+ kfree(name);
return error;
}
diff --git a/security/commoncap.c b/security/commoncap.c
index 5d9570f54a1c..1164278b97fd 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -352,14 +352,14 @@ static __u32 sansflags(__u32 m)
return m & ~VFS_CAP_FLAGS_EFFECTIVE;
}
-static bool is_v2header(size_t size, const struct vfs_cap_data *cap)
+static bool is_v2header(int size, const struct vfs_cap_data *cap)
{
if (size != XATTR_CAPS_SZ_2)
return false;
return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2;
}
-static bool is_v3header(size_t size, const struct vfs_cap_data *cap)
+static bool is_v3header(int size, const struct vfs_cap_data *cap)
{
if (size != XATTR_CAPS_SZ_3)
return false;
@@ -381,7 +381,7 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
struct inode *inode, const char *name, void **buffer,
bool alloc)
{
- int size, ret;
+ int size;
kuid_t kroot;
vfsuid_t vfsroot;
u32 nsmagic, magic;
@@ -398,22 +398,18 @@ int cap_inode_getsecurity(struct user_namespace *mnt_userns,
dentry = d_find_any_alias(inode);
if (!dentry)
return -EINVAL;
-
- size = sizeof(struct vfs_ns_cap_data);
- ret = (int)vfs_getxattr_alloc(mnt_userns, dentry, XATTR_NAME_CAPS,
- &tmpbuf, size, GFP_NOFS);
+ size = vfs_getxattr_alloc(mnt_userns, dentry, XATTR_NAME_CAPS, &tmpbuf,
+ sizeof(struct vfs_ns_cap_data), GFP_NOFS);
dput(dentry);
-
- if (ret < 0 || !tmpbuf) {
- size = ret;
+ /* gcc11 complains if we don't check for !tmpbuf */
+ if (size < 0 || !tmpbuf)
goto out_free;
- }
fs_ns = inode->i_sb->s_user_ns;
cap = (struct vfs_cap_data *) tmpbuf;
- if (is_v2header((size_t) ret, cap)) {
+ if (is_v2header(size, cap)) {
root = 0;
- } else if (is_v3header((size_t) ret, cap)) {
+ } else if (is_v3header(size, cap)) {
nscap = (struct vfs_ns_cap_data *) tmpbuf;
root = le32_to_cpu(nscap->rootid);
} else {
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index a9f8c63a96d1..bef2b9285fb3 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -82,6 +82,17 @@ free_and_exit:
return -ENOMEM;
}
+static void dev_exceptions_move(struct list_head *dest, struct list_head *orig)
+{
+ struct dev_exception_item *ex, *tmp;
+
+ lockdep_assert_held(&devcgroup_mutex);
+
+ list_for_each_entry_safe(ex, tmp, orig, list) {
+ list_move_tail(&ex->list, dest);
+ }
+}
+
/*
* called under devcgroup_mutex
*/
@@ -604,11 +615,13 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
int count, rc = 0;
struct dev_exception_item ex;
struct dev_cgroup *parent = css_to_devcgroup(devcgroup->css.parent);
+ struct dev_cgroup tmp_devcgrp;
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
memset(&ex, 0, sizeof(ex));
+ memset(&tmp_devcgrp, 0, sizeof(tmp_devcgrp));
b = buffer;
switch (*b) {
@@ -620,15 +633,27 @@ static int devcgroup_update_access(struct dev_cgroup *devcgroup,
if (!may_allow_all(parent))
return -EPERM;
- dev_exception_clean(devcgroup);
- devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
- if (!parent)
+ if (!parent) {
+ devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
+ dev_exception_clean(devcgroup);
break;
+ }
+ INIT_LIST_HEAD(&tmp_devcgrp.exceptions);
+ rc = dev_exceptions_copy(&tmp_devcgrp.exceptions,
+ &devcgroup->exceptions);
+ if (rc)
+ return rc;
+ dev_exception_clean(devcgroup);
rc = dev_exceptions_copy(&devcgroup->exceptions,
&parent->exceptions);
- if (rc)
+ if (rc) {
+ dev_exceptions_move(&devcgroup->exceptions,
+ &tmp_devcgrp.exceptions);
return rc;
+ }
+ devcgroup->behavior = DEVCG_DEFAULT_ALLOW;
+ dev_exception_clean(&tmp_devcgrp);
break;
case DEVCG_DENY:
if (css_has_online_children(&devcgroup->css))
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index 708de9656bbd..fa5ff13fa8c9 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -335,14 +335,15 @@ static int evm_is_immutable(struct dentry *dentry, struct inode *inode)
(char **)&xattr_data, 0, GFP_NOFS);
if (rc <= 0) {
if (rc == -ENODATA)
- return 0;
- return rc;
+ rc = 0;
+ goto out;
}
if (xattr_data->type == EVM_XATTR_PORTABLE_DIGSIG)
rc = 1;
else
rc = 0;
+out:
kfree(xattr_data);
return rc;
}
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index e01cfd4ad896..f02e609460e2 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -455,14 +455,17 @@ static int evm_xattr_change(struct user_namespace *mnt_userns,
rc = vfs_getxattr_alloc(&init_user_ns, dentry, xattr_name, &xattr_data,
0, GFP_NOFS);
- if (rc < 0)
- return 1;
+ if (rc < 0) {
+ rc = 1;
+ goto out;
+ }
if (rc == xattr_value_len)
rc = !!memcmp(xattr_value, xattr_data, rc);
else
rc = 1;
+out:
kfree(xattr_data);
return rc;
}
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index be965a8715e4..03b440921e61 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -326,7 +326,7 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len);
int ima_read_xattr(struct dentry *dentry,
- struct evm_ima_xattr_data **xattr_value);
+ struct evm_ima_xattr_data **xattr_value, int xattr_len);
#else
static inline int ima_check_blacklist(struct integrity_iint_cache *iint,
@@ -372,7 +372,8 @@ ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len)
}
static inline int ima_read_xattr(struct dentry *dentry,
- struct evm_ima_xattr_data **xattr_value)
+ struct evm_ima_xattr_data **xattr_value,
+ int xattr_len)
{
return 0;
}
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 3c9af3dc0713..ee6f7e237f2e 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -221,12 +221,12 @@ enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
}
int ima_read_xattr(struct dentry *dentry,
- struct evm_ima_xattr_data **xattr_value)
+ struct evm_ima_xattr_data **xattr_value, int xattr_len)
{
- ssize_t ret;
+ int ret;
ret = vfs_getxattr_alloc(&init_user_ns, dentry, XATTR_NAME_IMA,
- (char **)xattr_value, 0, GFP_NOFS);
+ (char **)xattr_value, xattr_len, GFP_NOFS);
if (ret == -EOPNOTSUPP)
ret = 0;
return ret;
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 040b03ddc1c7..0226899947d6 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -293,7 +293,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
/* HASH sets the digital signature and update flags, nothing else */
if ((action & IMA_HASH) &&
!(test_bit(IMA_DIGSIG, &iint->atomic_flags))) {
- xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
+ xattr_len = ima_read_xattr(file_dentry(file),
+ &xattr_value, xattr_len);
if ((xattr_value && xattr_len > 2) &&
(xattr_value->type == EVM_IMA_XATTR_DIGSIG))
set_bit(IMA_DIGSIG, &iint->atomic_flags);
@@ -316,7 +317,8 @@ static int process_measurement(struct file *file, const struct cred *cred,
if ((action & IMA_APPRAISE_SUBMASK) ||
strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) {
/* read 'security.ima' */
- xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
+ xattr_len = ima_read_xattr(file_dentry(file),
+ &xattr_value, xattr_len);
/*
* Read the appended modsig if allowed by the policy, and allow
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 7bf9b1507220..4564faae7d67 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -601,16 +601,15 @@ int ima_eventevmsig_init(struct ima_event_data *event_data,
rc = vfs_getxattr_alloc(&init_user_ns, file_dentry(event_data->file),
XATTR_NAME_EVM, (char **)&xattr_data, 0,
GFP_NOFS);
- if (rc <= 0)
- return 0;
-
- if (xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) {
- kfree(xattr_data);
- return 0;
+ if (rc <= 0 || xattr_data->type != EVM_XATTR_PORTABLE_DIGSIG) {
+ rc = 0;
+ goto out;
}
rc = ima_write_template_field_data((char *)xattr_data, rc, DATA_FMT_HEX,
field_data);
+
+out:
kfree(xattr_data);
return rc;
}
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 75cc3f8d2a42..a7355b4b9bb8 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -190,6 +190,7 @@ static inline void print_ipv4_addr(struct audit_buffer *ab, __be32 addr,
/**
* dump_common_audit_data - helper to dump common audit data
+ * @ab : the audit buffer
* @a : common audit data
*
*/
diff --git a/security/security.c b/security/security.c
index b967e035b456..d1571900a8c7 100644
--- a/security/security.c
+++ b/security/security.c
@@ -161,8 +161,8 @@ static void __init append_ordered_lsm(struct lsm_info *lsm, const char *from)
lsm->enabled = &lsm_enabled_true;
ordered_lsms[last_lsm++] = lsm;
- init_debug("%s ordering: %s (%sabled)\n", from, lsm->name,
- is_enabled(lsm) ? "en" : "dis");
+ init_debug("%s ordered: %s (%s)\n", from, lsm->name,
+ is_enabled(lsm) ? "enabled" : "disabled");
}
/* Is an LSM allowed to be initialized? */
@@ -225,7 +225,7 @@ static void __init prepare_lsm(struct lsm_info *lsm)
if (enabled) {
if ((lsm->flags & LSM_FLAG_EXCLUSIVE) && !exclusive) {
exclusive = lsm;
- init_debug("exclusive chosen: %s\n", lsm->name);
+ init_debug("exclusive chosen: %s\n", lsm->name);
}
lsm_set_blob_sizes(lsm->blobs);
@@ -253,7 +253,7 @@ static void __init ordered_lsm_parse(const char *order, const char *origin)
/* LSM_ORDER_FIRST is always first. */
for (lsm = __start_lsm_info; lsm < __end_lsm_info; lsm++) {
if (lsm->order == LSM_ORDER_FIRST)
- append_ordered_lsm(lsm, "first");
+ append_ordered_lsm(lsm, " first");
}
/* Process "security=", if given. */
@@ -271,7 +271,7 @@ static void __init ordered_lsm_parse(const char *order, const char *origin)
if ((major->flags & LSM_FLAG_LEGACY_MAJOR) &&
strcmp(major->name, chosen_major_lsm) != 0) {
set_enabled(major, false);
- init_debug("security=%s disabled: %s\n",
+ init_debug("security=%s disabled: %s (only one legacy major LSM)\n",
chosen_major_lsm, major->name);
}
}
@@ -292,7 +292,8 @@ static void __init ordered_lsm_parse(const char *order, const char *origin)
}
if (!found)
- init_debug("%s ignored: %s\n", origin, name);
+ init_debug("%s ignored: %s (not built into kernel)\n",
+ origin, name);
}
/* Process "security=", if given. */
@@ -310,7 +311,8 @@ static void __init ordered_lsm_parse(const char *order, const char *origin)
if (exists_ordered_lsm(lsm))
continue;
set_enabled(lsm, false);
- init_debug("%s disabled: %s\n", origin, lsm->name);
+ init_debug("%s skipped: %s (not in requested order)\n",
+ origin, lsm->name);
}
kfree(sep);
@@ -321,6 +323,24 @@ static void __init lsm_early_task(struct task_struct *task);
static int lsm_append(const char *new, char **result);
+static void __init report_lsm_order(void)
+{
+ struct lsm_info **lsm, *early;
+ int first = 0;
+
+ pr_info("initializing lsm=");
+
+ /* Report each enabled LSM name, comma separated. */
+ 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++)
+ if (is_enabled(*lsm))
+ pr_cont("%s%s", first++ == 0 ? "" : ",", (*lsm)->name);
+
+ pr_cont("\n");
+}
+
static void __init ordered_lsm_init(void)
{
struct lsm_info **lsm;
@@ -330,7 +350,8 @@ static void __init ordered_lsm_init(void)
if (chosen_lsm_order) {
if (chosen_major_lsm) {
- pr_info("security= is ignored because it is superseded by lsm=\n");
+ pr_warn("security=%s is ignored because it is superseded by lsm=%s\n",
+ chosen_major_lsm, chosen_lsm_order);
chosen_major_lsm = NULL;
}
ordered_lsm_parse(chosen_lsm_order, "cmdline");
@@ -340,6 +361,8 @@ static void __init ordered_lsm_init(void)
for (lsm = ordered_lsms; *lsm; lsm++)
prepare_lsm(*lsm);
+ report_lsm_order();
+
init_debug("cred blob size = %d\n", blob_sizes.lbs_cred);
init_debug("file blob size = %d\n", blob_sizes.lbs_file);
init_debug("inode blob size = %d\n", blob_sizes.lbs_inode);
@@ -396,13 +419,17 @@ int __init security_init(void)
{
struct lsm_info *lsm;
- pr_info("Security Framework initializing\n");
+ 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*");
/*
* Append the names of the early LSM modules now that kmalloc() is
* available
*/
for (lsm = __start_early_lsm_info; lsm < __end_early_lsm_info; lsm++) {
+ init_debug(" early started: %s (%s)\n", lsm->name,
+ is_enabled(lsm) ? "enabled" : "disabled");
if (lsm->enabled)
lsm_append(lsm->name, &lsm_names);
}
@@ -2315,11 +2342,11 @@ int security_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
}
EXPORT_SYMBOL(security_sock_rcv_skb);
-int security_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len)
+int security_socket_getpeersec_stream(struct socket *sock, sockptr_t optval,
+ sockptr_t optlen, unsigned int len)
{
return call_int_hook(socket_getpeersec_stream, -ENOPROTOOPT, sock,
- optval, optlen, len);
+ optval, optlen, len);
}
int security_socket_getpeersec_dgram(struct socket *sock, struct sk_buff *skb, u32 *secid)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7c5c8d17695c..3c5be76a9199 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5138,11 +5138,12 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
return err;
}
-static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *optval,
- int __user *optlen, unsigned len)
+static int selinux_socket_getpeersec_stream(struct socket *sock,
+ sockptr_t optval, sockptr_t optlen,
+ unsigned int len)
{
int err = 0;
- char *scontext;
+ char *scontext = NULL;
u32 scontext_len;
struct sk_security_struct *sksec = sock->sk->sk_security;
u32 peer_sid = SECSID_NULL;
@@ -5158,17 +5159,15 @@ static int selinux_socket_getpeersec_stream(struct socket *sock, char __user *op
&scontext_len);
if (err)
return err;
-
if (scontext_len > len) {
err = -ERANGE;
goto out_len;
}
- if (copy_to_user(optval, scontext, scontext_len))
+ if (copy_to_sockptr(optval, scontext, scontext_len))
err = -EFAULT;
-
out_len:
- if (put_user(scontext_len, optlen))
+ if (copy_to_sockptr(optlen, &scontext_len, sizeof(scontext_len)))
err = -EFAULT;
kfree(scontext);
return err;
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index cadef2f6a75e..9a82a15685d1 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -4074,12 +4074,12 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
* returns zero on success, an error code otherwise
*/
static int smack_socket_getpeersec_stream(struct socket *sock,
- char __user *optval,
- int __user *optlen, unsigned len)
+ sockptr_t optval, sockptr_t optlen,
+ unsigned int len)
{
struct socket_smack *ssp;
char *rcp = "";
- int slen = 1;
+ u32 slen = 1;
int rc = 0;
ssp = sock->sk->sk_security;
@@ -4087,15 +4087,16 @@ static int smack_socket_getpeersec_stream(struct socket *sock,
rcp = ssp->smk_packet->smk_known;
slen = strlen(rcp) + 1;
}
-
- if (slen > len)
+ if (slen > len) {
rc = -ERANGE;
- else if (copy_to_user(optval, rcp, slen) != 0)
- rc = -EFAULT;
+ goto out_len;
+ }
- if (put_user(slen, optlen) != 0)
+ if (copy_to_sockptr(optval, rcp, slen))
+ rc = -EFAULT;
+out_len:
+ if (copy_to_sockptr(optlen, &slen, sizeof(slen)))
rc = -EFAULT;
-
return rc;
}