Merge a45a7db9bc ("Merge tag 'vfs-6.2-merge-1' of git://git.kernel.org/pub/scm/fs/xfs/xfs-linux") into android-mainline
Steps on the way to 6.2-rc1 Change-Id: Idcffea7167784939dc23b60ba1307c197b24e826 Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
+2
-5
@@ -304,7 +304,7 @@ __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||
/* Check that we don't violate system file offset limits. */
|
||||
ret = generic_remap_checks(file_in, pos_in, file_out, pos_out, len,
|
||||
remap_flags);
|
||||
if (ret)
|
||||
if (ret || *len == 0)
|
||||
return ret;
|
||||
|
||||
/* Wait for the completion of any pending IOs on both files */
|
||||
@@ -328,9 +328,6 @@ __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||
if (remap_flags & REMAP_FILE_DEDUP) {
|
||||
bool is_same = false;
|
||||
|
||||
if (*len == 0)
|
||||
return 0;
|
||||
|
||||
if (!IS_DAX(inode_in))
|
||||
ret = vfs_dedupe_file_range_compare(file_in, pos_in,
|
||||
file_out, pos_out, *len, &is_same);
|
||||
@@ -348,7 +345,7 @@ __generic_remap_file_range_prep(struct file *file_in, loff_t pos_in,
|
||||
|
||||
ret = generic_remap_check_len(inode_in, inode_out, pos_out, len,
|
||||
remap_flags);
|
||||
if (ret)
|
||||
if (ret || *len == 0)
|
||||
return ret;
|
||||
|
||||
/* If can't alter the file contents, we're done. */
|
||||
|
||||
+253
-69
@@ -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)
|
||||
@@ -1010,8 +1011,29 @@ const char *xattr_full_name(const struct xattr_handler *handler,
|
||||
}
|
||||
EXPORT_SYMBOL(xattr_full_name);
|
||||
|
||||
/*
|
||||
* Allocate new xattr and copy in the value; but leave the name to callers.
|
||||
/**
|
||||
* free_simple_xattr - free an xattr object
|
||||
* @xattr: the xattr object
|
||||
*
|
||||
* Free the xattr object. Can handle @xattr being NULL.
|
||||
*/
|
||||
static inline void free_simple_xattr(struct simple_xattr *xattr)
|
||||
{
|
||||
if (xattr)
|
||||
kfree(xattr->name);
|
||||
kvfree(xattr);
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattr_alloc - allocate new xattr object
|
||||
* @value: value of the xattr object
|
||||
* @size: size of @value
|
||||
*
|
||||
* Allocate a new xattr object and initialize respective members. The caller is
|
||||
* responsible for handling the name of the xattr.
|
||||
*
|
||||
* Return: On success a new xattr object is returned. On failure NULL is
|
||||
* returned.
|
||||
*/
|
||||
struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
|
||||
{
|
||||
@@ -1032,20 +1054,69 @@ struct simple_xattr *simple_xattr_alloc(const void *value, size_t size)
|
||||
return new_xattr;
|
||||
}
|
||||
|
||||
/*
|
||||
* xattr GET operation for in-memory/pseudo filesystems
|
||||
/**
|
||||
* rbtree_simple_xattr_cmp - compare xattr name with current rbtree xattr entry
|
||||
* @key: xattr name
|
||||
* @node: current node
|
||||
*
|
||||
* Compare the xattr name with the xattr name attached to @node in the rbtree.
|
||||
*
|
||||
* Return: Negative value if continuing left, positive if continuing right, 0
|
||||
* if the xattr attached to @node matches @key.
|
||||
*/
|
||||
static int rbtree_simple_xattr_cmp(const void *key, const struct rb_node *node)
|
||||
{
|
||||
const char *xattr_name = key;
|
||||
const struct simple_xattr *xattr;
|
||||
|
||||
xattr = rb_entry(node, struct simple_xattr, rb_node);
|
||||
return strcmp(xattr->name, xattr_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* rbtree_simple_xattr_node_cmp - compare two xattr rbtree nodes
|
||||
* @new_node: new node
|
||||
* @node: current node
|
||||
*
|
||||
* Compare the xattr attached to @new_node with the xattr attached to @node.
|
||||
*
|
||||
* Return: Negative value if continuing left, positive if continuing right, 0
|
||||
* if the xattr attached to @new_node matches the xattr attached to @node.
|
||||
*/
|
||||
static int rbtree_simple_xattr_node_cmp(struct rb_node *new_node,
|
||||
const struct rb_node *node)
|
||||
{
|
||||
struct simple_xattr *xattr;
|
||||
xattr = rb_entry(new_node, struct simple_xattr, rb_node);
|
||||
return rbtree_simple_xattr_cmp(xattr->name, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattr_get - get an xattr object
|
||||
* @xattrs: the header of the xattr object
|
||||
* @name: the name of the xattr to retrieve
|
||||
* @buffer: the buffer to store the value into
|
||||
* @size: the size of @buffer
|
||||
*
|
||||
* Try to find and retrieve the xattr object associated with @name.
|
||||
* If @buffer is provided store the value of @xattr in @buffer
|
||||
* otherwise just return the length. The size of @buffer is limited
|
||||
* to XATTR_SIZE_MAX which currently is 65536.
|
||||
*
|
||||
* Return: On success the length of the xattr value is returned. On error a
|
||||
* negative error code is returned.
|
||||
*/
|
||||
int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
struct simple_xattr *xattr;
|
||||
struct simple_xattr *xattr = NULL;
|
||||
struct rb_node *rbp;
|
||||
int ret = -ENODATA;
|
||||
|
||||
spin_lock(&xattrs->lock);
|
||||
list_for_each_entry(xattr, &xattrs->head, list) {
|
||||
if (strcmp(name, xattr->name))
|
||||
continue;
|
||||
|
||||
read_lock(&xattrs->lock);
|
||||
rbp = rb_find(name, &xattrs->rb_root, rbtree_simple_xattr_cmp);
|
||||
if (rbp) {
|
||||
xattr = rb_entry(rbp, struct simple_xattr, rb_node);
|
||||
ret = xattr->size;
|
||||
if (buffer) {
|
||||
if (size < xattr->size)
|
||||
@@ -1053,34 +1124,44 @@ int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
||||
else
|
||||
memcpy(buffer, xattr->value, xattr->size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
spin_unlock(&xattrs->lock);
|
||||
read_unlock(&xattrs->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattr_set - xattr SET operation for in-memory/pseudo filesystems
|
||||
* @xattrs: target simple_xattr list
|
||||
* @name: name of the extended attribute
|
||||
* @value: value of the xattr. If %NULL, will remove the attribute.
|
||||
* @size: size of the new xattr
|
||||
* @flags: %XATTR_{CREATE|REPLACE}
|
||||
* @removed_size: returns size of the removed xattr, -1 if none removed
|
||||
* simple_xattr_set - set an xattr object
|
||||
* @xattrs: the header of the xattr object
|
||||
* @name: the name of the xattr to retrieve
|
||||
* @value: the value to store along the xattr
|
||||
* @size: the size of @value
|
||||
* @flags: the flags determining how to set the xattr
|
||||
* @removed_size: the size of the removed xattr
|
||||
*
|
||||
* %XATTR_CREATE is set, the xattr shouldn't exist already; otherwise fails
|
||||
* with -EEXIST. If %XATTR_REPLACE is set, the xattr should exist;
|
||||
* otherwise, fails with -ENODATA.
|
||||
* Set a new xattr object.
|
||||
* If @value is passed a new xattr object will be allocated. If XATTR_REPLACE
|
||||
* is specified in @flags a matching xattr object for @name must already exist.
|
||||
* If it does it will be replaced with the new xattr object. If it doesn't we
|
||||
* fail. If XATTR_CREATE is specified and a matching xattr does already exist
|
||||
* we fail. If it doesn't we create a new xattr. If @flags is zero we simply
|
||||
* insert the new xattr replacing any existing one.
|
||||
*
|
||||
* Returns 0 on success, -errno on failure.
|
||||
* If @value is empty and a matching xattr object is found we delete it if
|
||||
* XATTR_REPLACE is specified in @flags or @flags is zero.
|
||||
*
|
||||
* If @value is empty and no matching xattr object for @name is found we do
|
||||
* nothing if XATTR_CREATE is specified in @flags or @flags is zero. For
|
||||
* XATTR_REPLACE we fail as mentioned above.
|
||||
*
|
||||
* Return: On success zero and on error a negative error code is returned.
|
||||
*/
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags,
|
||||
ssize_t *removed_size)
|
||||
{
|
||||
struct simple_xattr *xattr;
|
||||
struct simple_xattr *new_xattr = NULL;
|
||||
int err = 0;
|
||||
struct simple_xattr *xattr = NULL, *new_xattr = NULL;
|
||||
struct rb_node *parent = NULL, **rbp;
|
||||
int err = 0, ret;
|
||||
|
||||
if (removed_size)
|
||||
*removed_size = -1;
|
||||
@@ -1093,42 +1174,68 @@ int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
|
||||
new_xattr->name = kstrdup(name, GFP_KERNEL);
|
||||
if (!new_xattr->name) {
|
||||
kvfree(new_xattr);
|
||||
free_simple_xattr(new_xattr);
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock(&xattrs->lock);
|
||||
list_for_each_entry(xattr, &xattrs->head, list) {
|
||||
if (!strcmp(name, xattr->name)) {
|
||||
if (flags & XATTR_CREATE) {
|
||||
xattr = new_xattr;
|
||||
err = -EEXIST;
|
||||
} else if (new_xattr) {
|
||||
list_replace(&xattr->list, &new_xattr->list);
|
||||
if (removed_size)
|
||||
*removed_size = xattr->size;
|
||||
} else {
|
||||
list_del(&xattr->list);
|
||||
if (removed_size)
|
||||
*removed_size = xattr->size;
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
write_lock(&xattrs->lock);
|
||||
rbp = &xattrs->rb_root.rb_node;
|
||||
while (*rbp) {
|
||||
parent = *rbp;
|
||||
ret = rbtree_simple_xattr_cmp(name, *rbp);
|
||||
if (ret < 0)
|
||||
rbp = &(*rbp)->rb_left;
|
||||
else if (ret > 0)
|
||||
rbp = &(*rbp)->rb_right;
|
||||
else
|
||||
xattr = rb_entry(*rbp, struct simple_xattr, rb_node);
|
||||
if (xattr)
|
||||
break;
|
||||
}
|
||||
if (flags & XATTR_REPLACE) {
|
||||
xattr = new_xattr;
|
||||
err = -ENODATA;
|
||||
} else {
|
||||
list_add(&new_xattr->list, &xattrs->head);
|
||||
xattr = NULL;
|
||||
}
|
||||
out:
|
||||
spin_unlock(&xattrs->lock);
|
||||
|
||||
if (xattr) {
|
||||
kfree(xattr->name);
|
||||
kvfree(xattr);
|
||||
/* Fail if XATTR_CREATE is requested and the xattr exists. */
|
||||
if (flags & XATTR_CREATE) {
|
||||
err = -EEXIST;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
if (new_xattr)
|
||||
rb_replace_node(&xattr->rb_node, &new_xattr->rb_node,
|
||||
&xattrs->rb_root);
|
||||
else
|
||||
rb_erase(&xattr->rb_node, &xattrs->rb_root);
|
||||
if (!err && removed_size)
|
||||
*removed_size = xattr->size;
|
||||
} else {
|
||||
/* Fail if XATTR_REPLACE is requested but no xattr is found. */
|
||||
if (flags & XATTR_REPLACE) {
|
||||
err = -ENODATA;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
/*
|
||||
* If XATTR_CREATE or no flags are specified together with a
|
||||
* new value simply insert it.
|
||||
*/
|
||||
if (new_xattr) {
|
||||
rb_link_node(&new_xattr->rb_node, parent, rbp);
|
||||
rb_insert_color(&new_xattr->rb_node, &xattrs->rb_root);
|
||||
}
|
||||
|
||||
/*
|
||||
* If XATTR_CREATE or no flags are specified and neither an
|
||||
* old or new xattr exist then we don't need to do anything.
|
||||
*/
|
||||
}
|
||||
|
||||
out_unlock:
|
||||
write_unlock(&xattrs->lock);
|
||||
if (err)
|
||||
free_simple_xattr(new_xattr);
|
||||
else
|
||||
free_simple_xattr(xattr);
|
||||
return err;
|
||||
|
||||
}
|
||||
@@ -1152,14 +1259,31 @@ static int xattr_list_one(char **buffer, ssize_t *remaining_size,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* xattr LIST operation for in-memory/pseudo filesystems
|
||||
/**
|
||||
* simple_xattr_list - list all xattr objects
|
||||
* @inode: inode from which to get the xattrs
|
||||
* @xattrs: the header of the xattr object
|
||||
* @buffer: the buffer to store all xattrs into
|
||||
* @size: the size of @buffer
|
||||
*
|
||||
* List all xattrs associated with @inode. If @buffer is NULL we returned
|
||||
* the required size of the buffer. If @buffer is provided we store the
|
||||
* xattrs value into it provided it is big enough.
|
||||
*
|
||||
* Note, the number of xattr names that can be listed with listxattr(2) is
|
||||
* limited to XATTR_LIST_MAX aka 65536 bytes. If a larger buffer is passed
|
||||
* then vfs_listxattr() caps it to XATTR_LIST_MAX and if more xattr names
|
||||
* are found it will return -E2BIG.
|
||||
*
|
||||
* Return: On success the required size or the size of the copied xattrs is
|
||||
* returned. On error a negative error code is returned.
|
||||
*/
|
||||
ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||
char *buffer, size_t size)
|
||||
{
|
||||
bool trusted = ns_capable_noaudit(&init_user_ns, CAP_SYS_ADMIN);
|
||||
struct simple_xattr *xattr;
|
||||
struct rb_node *rbp;
|
||||
ssize_t remaining_size = size;
|
||||
int err = 0;
|
||||
|
||||
@@ -1180,8 +1304,10 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||
}
|
||||
#endif
|
||||
|
||||
spin_lock(&xattrs->lock);
|
||||
list_for_each_entry(xattr, &xattrs->head, list) {
|
||||
read_lock(&xattrs->lock);
|
||||
for (rbp = rb_first(&xattrs->rb_root); rbp; rbp = rb_next(rbp)) {
|
||||
xattr = rb_entry(rbp, struct simple_xattr, rb_node);
|
||||
|
||||
/* skip "trusted." attributes for unprivileged callers */
|
||||
if (!trusted && xattr_is_trusted(xattr->name))
|
||||
continue;
|
||||
@@ -1190,18 +1316,76 @@ ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||
if (err)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&xattrs->lock);
|
||||
read_unlock(&xattrs->lock);
|
||||
|
||||
return err ? err : size - remaining_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds an extended attribute to the list
|
||||
/**
|
||||
* rbtree_simple_xattr_less - compare two xattr rbtree nodes
|
||||
* @new_node: new node
|
||||
* @node: current node
|
||||
*
|
||||
* Compare the xattr attached to @new_node with the xattr attached to @node.
|
||||
* Note that this function technically tolerates duplicate entries.
|
||||
*
|
||||
* Return: True if insertion point in the rbtree is found.
|
||||
*/
|
||||
void simple_xattr_list_add(struct simple_xattrs *xattrs,
|
||||
struct simple_xattr *new_xattr)
|
||||
static bool rbtree_simple_xattr_less(struct rb_node *new_node,
|
||||
const struct rb_node *node)
|
||||
{
|
||||
spin_lock(&xattrs->lock);
|
||||
list_add(&new_xattr->list, &xattrs->head);
|
||||
spin_unlock(&xattrs->lock);
|
||||
return rbtree_simple_xattr_node_cmp(new_node, node) < 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattr_add - add xattr objects
|
||||
* @xattrs: the header of the xattr object
|
||||
* @new_xattr: the xattr object to add
|
||||
*
|
||||
* Add an xattr object to @xattrs. This assumes no replacement or removal
|
||||
* of matching xattrs is wanted. Should only be called during inode
|
||||
* initialization when a few distinct initial xattrs are supposed to be set.
|
||||
*/
|
||||
void simple_xattr_add(struct simple_xattrs *xattrs,
|
||||
struct simple_xattr *new_xattr)
|
||||
{
|
||||
write_lock(&xattrs->lock);
|
||||
rb_add(&new_xattr->rb_node, &xattrs->rb_root, rbtree_simple_xattr_less);
|
||||
write_unlock(&xattrs->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattrs_init - initialize new xattr header
|
||||
* @xattrs: header to initialize
|
||||
*
|
||||
* Initialize relevant fields of a an xattr header.
|
||||
*/
|
||||
void simple_xattrs_init(struct simple_xattrs *xattrs)
|
||||
{
|
||||
xattrs->rb_root = RB_ROOT;
|
||||
rwlock_init(&xattrs->lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* simple_xattrs_free - free xattrs
|
||||
* @xattrs: xattr header whose xattrs to destroy
|
||||
*
|
||||
* Destroy all xattrs in @xattr. When this is called no one can hold a
|
||||
* reference to any of the xattrs anymore.
|
||||
*/
|
||||
void simple_xattrs_free(struct simple_xattrs *xattrs)
|
||||
{
|
||||
struct rb_node *rbp;
|
||||
|
||||
rbp = rb_first(&xattrs->rb_root);
|
||||
while (rbp) {
|
||||
struct simple_xattr *xattr;
|
||||
struct rb_node *rbp_next;
|
||||
|
||||
rbp_next = rb_next(rbp);
|
||||
xattr = rb_entry(rbp, struct simple_xattr, rb_node);
|
||||
rb_erase(&xattr->rb_node, &xattrs->rb_root);
|
||||
free_simple_xattr(xattr);
|
||||
rbp = rbp_next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
+142
-99
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
+12
-32
@@ -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);
|
||||
|
||||
@@ -86,48 +86,28 @@ static inline const char *xattr_prefix(const struct xattr_handler *handler)
|
||||
}
|
||||
|
||||
struct simple_xattrs {
|
||||
struct list_head head;
|
||||
spinlock_t lock;
|
||||
struct rb_root rb_root;
|
||||
rwlock_t lock;
|
||||
};
|
||||
|
||||
struct simple_xattr {
|
||||
struct list_head list;
|
||||
struct rb_node rb_node;
|
||||
char *name;
|
||||
size_t size;
|
||||
char value[];
|
||||
};
|
||||
|
||||
/*
|
||||
* initialize the simple_xattrs structure
|
||||
*/
|
||||
static inline void simple_xattrs_init(struct simple_xattrs *xattrs)
|
||||
{
|
||||
INIT_LIST_HEAD(&xattrs->head);
|
||||
spin_lock_init(&xattrs->lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* free all the xattrs
|
||||
*/
|
||||
static inline void simple_xattrs_free(struct simple_xattrs *xattrs)
|
||||
{
|
||||
struct simple_xattr *xattr, *node;
|
||||
|
||||
list_for_each_entry_safe(xattr, node, &xattrs->head, list) {
|
||||
kfree(xattr->name);
|
||||
kvfree(xattr);
|
||||
}
|
||||
}
|
||||
|
||||
void simple_xattrs_init(struct simple_xattrs *xattrs);
|
||||
void simple_xattrs_free(struct simple_xattrs *xattrs);
|
||||
struct simple_xattr *simple_xattr_alloc(const void *value, size_t size);
|
||||
int simple_xattr_get(struct simple_xattrs *xattrs, const char *name,
|
||||
void *buffer, size_t size);
|
||||
int simple_xattr_set(struct simple_xattrs *xattrs, const char *name,
|
||||
const void *value, size_t size, int flags,
|
||||
ssize_t *removed_size);
|
||||
ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs, char *buffer,
|
||||
size_t size);
|
||||
void simple_xattr_list_add(struct simple_xattrs *xattrs,
|
||||
struct simple_xattr *new_xattr);
|
||||
ssize_t simple_xattr_list(struct inode *inode, struct simple_xattrs *xattrs,
|
||||
char *buffer, size_t size);
|
||||
void simple_xattr_add(struct simple_xattrs *xattrs,
|
||||
struct simple_xattr *new_xattr);
|
||||
|
||||
#endif /* _LINUX_XATTR_H */
|
||||
|
||||
+1
-1
@@ -3283,7 +3283,7 @@ static int shmem_initxattrs(struct inode *inode,
|
||||
memcpy(new_xattr->name + XATTR_SECURITY_PREFIX_LEN,
|
||||
xattr->name, len);
|
||||
|
||||
simple_xattr_list_add(&info->xattrs, new_xattr);
|
||||
simple_xattr_add(&info->xattrs, new_xattr);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+2
-1
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
+13
-16
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+9
-13
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
rc = dev_exceptions_copy(&devcgroup->exceptions,
|
||||
&parent->exceptions);
|
||||
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) {
|
||||
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))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
*
|
||||
*/
|
||||
|
||||
+39
-12
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user