Merge d1fec2214b ("Merge tag 'selinux-pr-20210215' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux") into android-mainline

Steps on the way to 5.12-rc1

Resolves conflicts in:
        security/selinux/hooks.c
        security/selinux/include/classmap.h

Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I5aedc69f0f2b3b16351b1f39ed69994ca1ba59a5
This commit is contained in:
Greg Kroah-Hartman 2021-03-03 15:35:19 +01:00
commit 84645f0a33
26 changed files with 327 additions and 138 deletions

View File

@ -55,6 +55,75 @@ static struct file_system_type anon_inode_fs_type = {
.kill_sb = kill_anon_super,
};
static struct inode *anon_inode_make_secure_inode(
const char *name,
const struct inode *context_inode)
{
struct inode *inode;
const struct qstr qname = QSTR_INIT(name, strlen(name));
int error;
inode = alloc_anon_inode(anon_inode_mnt->mnt_sb);
if (IS_ERR(inode))
return inode;
inode->i_flags &= ~S_PRIVATE;
error = security_inode_init_security_anon(inode, &qname, context_inode);
if (error) {
iput(inode);
return ERR_PTR(error);
}
return inode;
}
static struct file *__anon_inode_getfile(const char *name,
const struct file_operations *fops,
void *priv, int flags,
const struct inode *context_inode,
bool secure)
{
struct inode *inode;
struct file *file;
if (fops->owner && !try_module_get(fops->owner))
return ERR_PTR(-ENOENT);
if (secure) {
inode = anon_inode_make_secure_inode(name, context_inode);
if (IS_ERR(inode)) {
file = ERR_CAST(inode);
goto err;
}
} else {
inode = anon_inode_inode;
if (IS_ERR(inode)) {
file = ERR_PTR(-ENODEV);
goto err;
}
/*
* We know the anon_inode inode count is always
* greater than zero, so ihold() is safe.
*/
ihold(inode);
}
file = alloc_file_pseudo(inode, anon_inode_mnt, name,
flags & (O_ACCMODE | O_NONBLOCK), fops);
if (IS_ERR(file))
goto err_iput;
file->f_mapping = inode->i_mapping;
file->private_data = priv;
return file;
err_iput:
iput(inode);
err:
module_put(fops->owner);
return file;
}
/**
* anon_inode_getfile - creates a new file instance by hooking it up to an
* anonymous inode, and a dentry that describe the "class"
@ -75,55 +144,15 @@ struct file *anon_inode_getfile(const char *name,
const struct file_operations *fops,
void *priv, int flags)
{
struct file *file;
if (IS_ERR(anon_inode_inode))
return ERR_PTR(-ENODEV);
if (fops->owner && !try_module_get(fops->owner))
return ERR_PTR(-ENOENT);
/*
* We know the anon_inode inode count is always greater than zero,
* so ihold() is safe.
*/
ihold(anon_inode_inode);
file = alloc_file_pseudo(anon_inode_inode, anon_inode_mnt, name,
flags & (O_ACCMODE | O_NONBLOCK), fops);
if (IS_ERR(file))
goto err;
file->f_mapping = anon_inode_inode->i_mapping;
file->private_data = priv;
return file;
err:
iput(anon_inode_inode);
module_put(fops->owner);
return file;
return __anon_inode_getfile(name, fops, priv, flags, NULL, false);
}
EXPORT_SYMBOL_GPL(anon_inode_getfile);
/**
* anon_inode_getfd - creates a new file instance by hooking it up to an
* anonymous inode, and a dentry that describe the "class"
* of the file
*
* @name: [in] name of the "class" of the new file
* @fops: [in] file operations for the new file
* @priv: [in] private data for the new file (will be file's private_data)
* @flags: [in] flags
*
* Creates a new file by hooking it on a single inode. This is useful for files
* that do not need to have a full-fledged inode in order to operate correctly.
* All the files created with anon_inode_getfd() will share a single inode,
* hence saving memory and avoiding code duplication for the file/inode/dentry
* setup. Returns new descriptor or an error code.
*/
int anon_inode_getfd(const char *name, const struct file_operations *fops,
void *priv, int flags)
static int __anon_inode_getfd(const char *name,
const struct file_operations *fops,
void *priv, int flags,
const struct inode *context_inode,
bool secure)
{
int error, fd;
struct file *file;
@ -133,7 +162,8 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
return error;
fd = error;
file = anon_inode_getfile(name, fops, priv, flags);
file = __anon_inode_getfile(name, fops, priv, flags, context_inode,
secure);
if (IS_ERR(file)) {
error = PTR_ERR(file);
goto err_put_unused_fd;
@ -146,8 +176,55 @@ int anon_inode_getfd(const char *name, const struct file_operations *fops,
put_unused_fd(fd);
return error;
}
/**
* anon_inode_getfd - creates a new file instance by hooking it up to
* an anonymous inode and a dentry that describe
* the "class" of the file
*
* @name: [in] name of the "class" of the new file
* @fops: [in] file operations for the new file
* @priv: [in] private data for the new file (will be file's private_data)
* @flags: [in] flags
*
* Creates a new file by hooking it on a single inode. This is
* useful for files that do not need to have a full-fledged inode in
* order to operate correctly. All the files created with
* anon_inode_getfd() will use the same singleton inode, reducing
* memory use and avoiding code duplication for the file/inode/dentry
* setup. Returns a newly created file descriptor or an error code.
*/
int anon_inode_getfd(const char *name, const struct file_operations *fops,
void *priv, int flags)
{
return __anon_inode_getfd(name, fops, priv, flags, NULL, false);
}
EXPORT_SYMBOL_GPL(anon_inode_getfd);
/**
* anon_inode_getfd_secure - Like anon_inode_getfd(), but creates a new
* !S_PRIVATE anon inode rather than reuse the singleton anon inode, and calls
* the inode_init_security_anon() LSM hook. This allows the inode to have its
* own security context and for a LSM to reject creation of the inode.
*
* @name: [in] name of the "class" of the new file
* @fops: [in] file operations for the new file
* @priv: [in] private data for the new file (will be file's private_data)
* @flags: [in] flags
* @context_inode:
* [in] the logical relationship with the new inode (optional)
*
* The LSM may use @context_inode in inode_init_security_anon(), but a
* reference to it is not held.
*/
int anon_inode_getfd_secure(const char *name, const struct file_operations *fops,
void *priv, int flags,
const struct inode *context_inode)
{
return __anon_inode_getfd(name, fops, priv, flags, context_inode, true);
}
EXPORT_SYMBOL_GPL(anon_inode_getfd_secure);
static int __init anon_inode_init(void)
{
anon_inode_mnt = kern_mount(&anon_inode_fs_type);

View File

@ -1214,11 +1214,6 @@ static int anon_set_page_dirty(struct page *page)
return 0;
};
/*
* A single inode exists for all anon_inode files. Contrary to pipes,
* anon_inode inodes have no associated per-instance data, so we need
* only allocate one of them.
*/
struct inode *alloc_anon_inode(struct super_block *s)
{
static const struct address_space_operations anon_aops = {

View File

@ -980,14 +980,14 @@ static __poll_t userfaultfd_poll(struct file *file, poll_table *wait)
static const struct file_operations userfaultfd_fops;
static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
struct userfaultfd_ctx *new,
static int resolve_userfault_fork(struct userfaultfd_ctx *new,
struct inode *inode,
struct uffd_msg *msg)
{
int fd;
fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, new,
O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS));
fd = anon_inode_getfd_secure("[userfaultfd]", &userfaultfd_fops, new,
O_RDWR | (new->flags & UFFD_SHARED_FCNTL_FLAGS), inode);
if (fd < 0)
return fd;
@ -997,7 +997,7 @@ static int resolve_userfault_fork(struct userfaultfd_ctx *ctx,
}
static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
struct uffd_msg *msg)
struct uffd_msg *msg, struct inode *inode)
{
ssize_t ret;
DECLARE_WAITQUEUE(wait, current);
@ -1108,7 +1108,7 @@ static ssize_t userfaultfd_ctx_read(struct userfaultfd_ctx *ctx, int no_wait,
spin_unlock_irq(&ctx->fd_wqh.lock);
if (!ret && msg->event == UFFD_EVENT_FORK) {
ret = resolve_userfault_fork(ctx, fork_nctx, msg);
ret = resolve_userfault_fork(fork_nctx, inode, msg);
spin_lock_irq(&ctx->event_wqh.lock);
if (!list_empty(&fork_event)) {
/*
@ -1168,6 +1168,7 @@ static ssize_t userfaultfd_read(struct file *file, char __user *buf,
ssize_t _ret, ret = 0;
struct uffd_msg msg;
int no_wait = file->f_flags & O_NONBLOCK;
struct inode *inode = file_inode(file);
if (ctx->state == UFFD_STATE_WAIT_API)
return -EINVAL;
@ -1175,7 +1176,7 @@ static ssize_t userfaultfd_read(struct file *file, char __user *buf,
for (;;) {
if (count < sizeof(msg))
return ret ? ret : -EINVAL;
_ret = userfaultfd_ctx_read(ctx, no_wait, &msg);
_ret = userfaultfd_ctx_read(ctx, no_wait, &msg, inode);
if (_ret < 0)
return ret ? ret : _ret;
if (copy_to_user((__u64 __user *) buf, &msg, sizeof(msg)))
@ -2002,8 +2003,8 @@ SYSCALL_DEFINE1(userfaultfd, int, flags)
/* prevent the mm struct to be freed */
mmgrab(ctx->mm);
fd = anon_inode_getfd("[userfaultfd]", &userfaultfd_fops, ctx,
O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS));
fd = anon_inode_getfd_secure("[userfaultfd]", &userfaultfd_fops, ctx,
O_RDWR | (flags & UFFD_SHARED_FCNTL_FLAGS), NULL);
if (fd < 0) {
mmdrop(ctx->mm);
kmem_cache_free(userfaultfd_ctx_cachep, ctx);

View File

@ -10,12 +10,17 @@
#define _LINUX_ANON_INODES_H
struct file_operations;
struct inode;
struct file *anon_inode_getfile(const char *name,
const struct file_operations *fops,
void *priv, int flags);
int anon_inode_getfd(const char *name, const struct file_operations *fops,
void *priv, int flags);
int anon_inode_getfd_secure(const char *name,
const struct file_operations *fops,
void *priv, int flags,
const struct inode *context_inode);
#endif /* _LINUX_ANON_INODES_H */

View File

@ -113,6 +113,8 @@ LSM_HOOK(void, LSM_RET_VOID, inode_free_security, struct inode *inode)
LSM_HOOK(int, 0, inode_init_security, struct inode *inode,
struct inode *dir, const struct qstr *qstr, const char **name,
void **value, size_t *len)
LSM_HOOK(int, 0, inode_init_security_anon, struct inode *inode,
const struct qstr *name, const struct inode *context_inode)
LSM_HOOK(int, 0, inode_create, struct inode *dir, struct dentry *dentry,
umode_t mode)
LSM_HOOK(int, 0, inode_link, struct dentry *old_dentry, struct inode *dir,

View File

@ -233,6 +233,15 @@
* Returns 0 if @name and @value have been successfully set,
* -EOPNOTSUPP if no security attribute is needed, or
* -ENOMEM on memory allocation failure.
* @inode_init_security_anon:
* Set up the incore security field for the new anonymous inode
* and return whether the inode creation is permitted by the security
* module or not.
* @inode contains the inode structure
* @name name of the anonymous inode class
* @context_inode optional related inode
* Returns 0 on success, -EACCES if the security module denies the
* creation of this inode, or another -errno upon other errors.
* @inode_create:
* Check permission to create a regular file.
* @dir contains inode structure of the parent of the new file.

View File

@ -322,6 +322,9 @@ void security_inode_free(struct inode *inode);
int security_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr,
initxattrs initxattrs, void *fs_data);
int security_inode_init_security_anon(struct inode *inode,
const struct qstr *name,
const struct inode *context_inode);
int security_old_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr, const char **name,
void **value, size_t *len);
@ -736,6 +739,13 @@ static inline int security_inode_init_security(struct inode *inode,
return 0;
}
static inline int security_inode_init_security_anon(struct inode *inode,
const struct qstr *name,
const struct inode *context_inode)
{
return 0;
}
static inline int security_old_inode_init_security(struct inode *inode,
struct inode *dir,
const struct qstr *qstr,

View File

@ -1059,6 +1059,14 @@ int security_inode_init_security(struct inode *inode, struct inode *dir,
}
EXPORT_SYMBOL(security_inode_init_security);
int security_inode_init_security_anon(struct inode *inode,
const struct qstr *name,
const struct inode *context_inode)
{
return call_int_hook(inode_init_security_anon, 0, inode, name,
context_inode);
}
int security_old_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr, const char **name,
void **value, size_t *len)

View File

@ -118,11 +118,11 @@ void avc_set_cache_threshold(struct selinux_avc *avc,
avc->avc_cache_threshold = cache_threshold;
}
static struct avc_callback_node *avc_callbacks;
static struct kmem_cache *avc_node_cachep;
static struct kmem_cache *avc_xperms_data_cachep;
static struct kmem_cache *avc_xperms_decision_cachep;
static struct kmem_cache *avc_xperms_cachep;
static struct avc_callback_node *avc_callbacks __ro_after_init;
static struct kmem_cache *avc_node_cachep __ro_after_init;
static struct kmem_cache *avc_xperms_data_cachep __ro_after_init;
static struct kmem_cache *avc_xperms_decision_cachep __ro_after_init;
static struct kmem_cache *avc_xperms_cachep __ro_after_init;
static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
{

View File

@ -484,6 +484,56 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
}
}
static int sb_check_xattr_support(struct super_block *sb)
{
struct superblock_security_struct *sbsec = sb->s_security;
struct dentry *root = sb->s_root;
struct inode *root_inode = d_backing_inode(root);
u32 sid;
int rc;
/*
* Make sure that the xattr handler exists and that no
* error other than -ENODATA is returned by getxattr on
* the root directory. -ENODATA is ok, as this may be
* the first boot of the SELinux kernel before we have
* assigned xattr values to the filesystem.
*/
if (!(root_inode->i_opflags & IOP_XATTR)) {
pr_warn("SELinux: (dev %s, type %s) has no xattr support\n",
sb->s_id, sb->s_type->name);
goto fallback;
}
rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL, 0,
XATTR_NOSECURITY);
if (rc < 0 && rc != -ENODATA) {
if (rc == -EOPNOTSUPP) {
pr_warn("SELinux: (dev %s, type %s) has no security xattr handler\n",
sb->s_id, sb->s_type->name);
goto fallback;
} else {
pr_warn("SELinux: (dev %s, type %s) getxattr errno %d\n",
sb->s_id, sb->s_type->name, -rc);
return rc;
}
}
return 0;
fallback:
/* No xattr support - try to fallback to genfs if possible. */
rc = security_genfs_sid(&selinux_state, sb->s_type->name, "/",
SECCLASS_DIR, &sid);
if (rc)
return -EOPNOTSUPP;
pr_warn("SELinux: (dev %s, type %s) falling back to genfs\n",
sb->s_id, sb->s_type->name);
sbsec->behavior = SECURITY_FS_USE_GENFS;
sbsec->sid = sid;
return 0;
}
static int sb_finish_set_opts(struct super_block *sb)
{
struct superblock_security_struct *sbsec = sb->s_security;
@ -492,31 +542,9 @@ static int sb_finish_set_opts(struct super_block *sb)
int rc = 0;
if (sbsec->behavior == SECURITY_FS_USE_XATTR) {
/* Make sure that the xattr handler exists and that no
error other than -ENODATA is returned by getxattr on
the root directory. -ENODATA is ok, as this may be
the first boot of the SELinux kernel before we have
assigned xattr values to the filesystem. */
if (!(root_inode->i_opflags & IOP_XATTR)) {
pr_warn("SELinux: (dev %s, type %s) has no "
"xattr support\n", sb->s_id, sb->s_type->name);
rc = -EOPNOTSUPP;
goto out;
}
rc = __vfs_getxattr(root, root_inode, XATTR_NAME_SELINUX, NULL,
0, XATTR_NOSECURITY);
if (rc < 0 && rc != -ENODATA) {
if (rc == -EOPNOTSUPP)
pr_warn("SELinux: (dev %s, type "
"%s) has no security xattr handler\n",
sb->s_id, sb->s_type->name);
else
pr_warn("SELinux: (dev %s, type "
"%s) getxattr errno %d\n", sb->s_id,
sb->s_type->name, -rc);
goto out;
}
rc = sb_check_xattr_support(sb);
if (rc)
return rc;
}
sbsec->flags |= SE_SBINITIALIZED;
@ -555,7 +583,6 @@ static int sb_finish_set_opts(struct super_block *sb)
spin_lock(&sbsec->isec_lock);
}
spin_unlock(&sbsec->isec_lock);
out:
return rc;
}
@ -1121,7 +1148,8 @@ static inline u16 inode_mode_to_security_class(umode_t mode)
static inline int default_protocol_stream(int protocol)
{
return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP);
return (protocol == IPPROTO_IP || protocol == IPPROTO_TCP ||
protocol == IPPROTO_MPTCP);
}
static inline int default_protocol_dgram(int protocol)
@ -2937,6 +2965,62 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
return 0;
}
static int selinux_inode_init_security_anon(struct inode *inode,
const struct qstr *name,
const struct inode *context_inode)
{
const struct task_security_struct *tsec = selinux_cred(current_cred());
struct common_audit_data ad;
struct inode_security_struct *isec;
int rc;
if (unlikely(!selinux_initialized(&selinux_state)))
return 0;
isec = selinux_inode(inode);
/*
* We only get here once per ephemeral inode. The inode has
* been initialized via inode_alloc_security but is otherwise
* untouched.
*/
if (context_inode) {
struct inode_security_struct *context_isec =
selinux_inode(context_inode);
if (context_isec->initialized != LABEL_INITIALIZED) {
pr_err("SELinux: context_inode is not initialized");
return -EACCES;
}
isec->sclass = context_isec->sclass;
isec->sid = context_isec->sid;
} else {
isec->sclass = SECCLASS_ANON_INODE;
rc = security_transition_sid(
&selinux_state, tsec->sid, tsec->sid,
isec->sclass, name, &isec->sid);
if (rc)
return rc;
}
isec->initialized = LABEL_INITIALIZED;
/*
* Now that we've initialized security, check whether we're
* allowed to actually create this type of anonymous inode.
*/
ad.type = LSM_AUDIT_DATA_INODE;
ad.u.inode = inode;
return avc_has_perm(&selinux_state,
tsec->sid,
isec->sid,
isec->sclass,
FILE__CREATE,
&ad);
}
static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
return may_create(dir, dentry, SECCLASS_FILE);
@ -3416,6 +3500,10 @@ static int selinux_inode_setsecurity(struct inode *inode, const char *name,
static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t buffer_size)
{
const int len = sizeof(XATTR_NAME_SELINUX);
if (!selinux_initialized(&selinux_state))
return 0;
if (buffer && len <= buffer_size)
memcpy(buffer, XATTR_NAME_SELINUX, len);
return len;
@ -6975,6 +7063,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
LSM_HOOK_INIT(inode_free_security, selinux_inode_free_security),
LSM_HOOK_INIT(inode_init_security, selinux_inode_init_security),
LSM_HOOK_INIT(inode_init_security_anon, selinux_inode_init_security_anon),
LSM_HOOK_INIT(inode_create, selinux_inode_create),
LSM_HOOK_INIT(inode_link, selinux_inode_link),
LSM_HOOK_INIT(inode_unlink, selinux_inode_unlink),

View File

@ -40,7 +40,6 @@ struct sel_ib_pkey {
struct rcu_head rcu;
};
static LIST_HEAD(sel_ib_pkey_list);
static DEFINE_SPINLOCK(sel_ib_pkey_lock);
static struct sel_ib_pkey_bkt sel_ib_pkey_hash[SEL_PKEY_HASH_SIZE];

View File

@ -247,6 +247,8 @@ struct security_class_mapping secclass_map[] = {
{ COMMON_SOCK_PERMS, NULL } },
{ "perf_event",
{"open", "cpu", "kernel", "tracepoint", "read", "write"} },
{ "anon_inode",
{ COMMON_FILE_PERMS, NULL } },
{ NULL }
};

View File

@ -444,7 +444,6 @@ extern void selinux_complete_init(void);
extern int selinux_disable(struct selinux_state *state);
extern void exit_sel_fs(void);
extern struct path selinux_null;
extern struct vfsmount *selinuxfs_mount;
extern void selnl_notify_setenforce(int val);
extern void selnl_notify_policyload(u32 seqno);
extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);

View File

@ -36,7 +36,6 @@ struct sel_netif {
};
static u32 sel_netif_total;
static LIST_HEAD(sel_netif_list);
static DEFINE_SPINLOCK(sel_netif_lock);
static struct list_head sel_netif_hash[SEL_NETIF_HASH_SIZE];

View File

@ -19,7 +19,7 @@
#include "security.h"
static struct sock *selnl;
static struct sock *selnl __ro_after_init;
static int selnl_msglen(int msgtype)
{

View File

@ -54,7 +54,6 @@ struct sel_netnode {
* if this becomes a problem we can always add a hash table for each address
* family later */
static LIST_HEAD(sel_netnode_list);
static DEFINE_SPINLOCK(sel_netnode_lock);
static struct sel_netnode_bkt sel_netnode_hash[SEL_NETNODE_HASH_SIZE];

View File

@ -53,7 +53,6 @@ struct sel_netport {
* if this becomes a problem we can always add a hash table for each address
* family later */
static LIST_HEAD(sel_netport_list);
static DEFINE_SPINLOCK(sel_netport_lock);
static struct sel_netport_bkt sel_netport_hash[SEL_NETPORT_HASH_SIZE];

View File

@ -2204,8 +2204,8 @@ static struct file_system_type sel_fs_type = {
.kill_sb = sel_kill_sb,
};
struct vfsmount *selinuxfs_mount;
struct path selinux_null;
static struct vfsmount *selinuxfs_mount __ro_after_init;
struct path selinux_null __ro_after_init;
static int __init init_sel_fs(void)
{

View File

@ -23,8 +23,8 @@
#include "avtab.h"
#include "policydb.h"
static struct kmem_cache *avtab_node_cachep;
static struct kmem_cache *avtab_xperms_cachep;
static struct kmem_cache *avtab_node_cachep __ro_after_init;
static struct kmem_cache *avtab_xperms_cachep __ro_after_init;
/* Based on MurmurHash3, written by Austin Appleby and placed in the
* public domain.

View File

@ -26,7 +26,7 @@
#define BITS_PER_U64 (sizeof(u64) * 8)
static struct kmem_cache *ebitmap_node_cachep;
static struct kmem_cache *ebitmap_node_cachep __ro_after_init;
int ebitmap_cmp(struct ebitmap *e1, struct ebitmap *e2)
{

View File

@ -9,7 +9,7 @@
#include <linux/errno.h>
#include "hashtab.h"
static struct kmem_cache *hashtab_node_cachep;
static struct kmem_cache *hashtab_node_cachep __ro_after_init;
/*
* Here we simply round the number of elements up to the nearest power of two.

View File

@ -3696,15 +3696,11 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule)
return match;
}
static int (*aurule_callback)(void) = audit_update_lsm_rules;
static int aurule_avc_callback(u32 event)
{
int err = 0;
if (event == AVC_CALLBACK_RESET && aurule_callback)
err = aurule_callback();
return err;
if (event == AVC_CALLBACK_RESET)
return audit_update_lsm_rules();
return 0;
}
static int __init aurule_init(void)

View File

@ -47,7 +47,7 @@
#include "xfrm.h"
/* Labeled XFRM instance counter */
atomic_t selinux_xfrm_refcount = ATOMIC_INIT(0);
atomic_t selinux_xfrm_refcount __read_mostly = ATOMIC_INIT(0);
/*
* Returns true if the context is an LSM/SELinux context.

View File

@ -362,14 +362,14 @@ static bool tomoyo_merge_path_acl(struct tomoyo_acl_info *a,
{
u16 * const a_perm = &container_of(a, struct tomoyo_path_acl, head)
->perm;
u16 perm = *a_perm;
u16 perm = READ_ONCE(*a_perm);
const u16 b_perm = container_of(b, struct tomoyo_path_acl, head)->perm;
if (is_delete)
perm &= ~b_perm;
else
perm |= b_perm;
*a_perm = perm;
WRITE_ONCE(*a_perm, perm);
return !perm;
}
@ -437,7 +437,7 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
{
u8 *const a_perm = &container_of(a, struct tomoyo_mkdev_acl,
head)->perm;
u8 perm = *a_perm;
u8 perm = READ_ONCE(*a_perm);
const u8 b_perm = container_of(b, struct tomoyo_mkdev_acl, head)
->perm;
@ -445,7 +445,7 @@ static bool tomoyo_merge_mkdev_acl(struct tomoyo_acl_info *a,
perm &= ~b_perm;
else
perm |= b_perm;
*a_perm = perm;
WRITE_ONCE(*a_perm, perm);
return !perm;
}
@ -517,14 +517,14 @@ static bool tomoyo_merge_path2_acl(struct tomoyo_acl_info *a,
{
u8 * const a_perm = &container_of(a, struct tomoyo_path2_acl, head)
->perm;
u8 perm = *a_perm;
u8 perm = READ_ONCE(*a_perm);
const u8 b_perm = container_of(b, struct tomoyo_path2_acl, head)->perm;
if (is_delete)
perm &= ~b_perm;
else
perm |= b_perm;
*a_perm = perm;
WRITE_ONCE(*a_perm, perm);
return !perm;
}
@ -655,7 +655,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
{
u8 * const a_perm = &container_of(a, struct tomoyo_path_number_acl,
head)->perm;
u8 perm = *a_perm;
u8 perm = READ_ONCE(*a_perm);
const u8 b_perm = container_of(b, struct tomoyo_path_number_acl, head)
->perm;
@ -663,7 +663,7 @@ static bool tomoyo_merge_path_number_acl(struct tomoyo_acl_info *a,
perm &= ~b_perm;
else
perm |= b_perm;
*a_perm = perm;
WRITE_ONCE(*a_perm, perm);
return !perm;
}

View File

@ -233,14 +233,14 @@ static bool tomoyo_merge_inet_acl(struct tomoyo_acl_info *a,
{
u8 * const a_perm =
&container_of(a, struct tomoyo_inet_acl, head)->perm;
u8 perm = *a_perm;
u8 perm = READ_ONCE(*a_perm);
const u8 b_perm = container_of(b, struct tomoyo_inet_acl, head)->perm;
if (is_delete)
perm &= ~b_perm;
else
perm |= b_perm;
*a_perm = perm;
WRITE_ONCE(*a_perm, perm);
return !perm;
}
@ -259,14 +259,14 @@ static bool tomoyo_merge_unix_acl(struct tomoyo_acl_info *a,
{
u8 * const a_perm =
&container_of(a, struct tomoyo_unix_acl, head)->perm;
u8 perm = *a_perm;
u8 perm = READ_ONCE(*a_perm);
const u8 b_perm = container_of(b, struct tomoyo_unix_acl, head)->perm;
if (is_delete)
perm &= ~b_perm;
else
perm |= b_perm;
*a_perm = perm;
WRITE_ONCE(*a_perm, perm);
return !perm;
}
@ -613,7 +613,7 @@ static int tomoyo_check_unix_address(struct sockaddr *addr,
static bool tomoyo_kernel_service(void)
{
/* Nothing to do if I am a kernel service. */
return uaccess_kernel();
return (current->flags & (PF_KTHREAD | PF_IO_WORKER)) == PF_KTHREAD;
}
/**

View File

@ -1058,30 +1058,30 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_request_info *r)
if (ptr->is_deleted)
continue;
/*
* Reading perm bitmap might race with tomoyo_merge_*() because
* caller does not hold tomoyo_policy_lock mutex. But exceeding
* max_learning_entry parameter by a few entries does not harm.
*/
switch (ptr->type) {
case TOMOYO_TYPE_PATH_ACL:
perm = container_of(ptr, struct tomoyo_path_acl, head)
->perm;
data_race(perm = container_of(ptr, struct tomoyo_path_acl, head)->perm);
break;
case TOMOYO_TYPE_PATH2_ACL:
perm = container_of(ptr, struct tomoyo_path2_acl, head)
->perm;
data_race(perm = container_of(ptr, struct tomoyo_path2_acl, head)->perm);
break;
case TOMOYO_TYPE_PATH_NUMBER_ACL:
perm = container_of(ptr, struct tomoyo_path_number_acl,
head)->perm;
data_race(perm = container_of(ptr, struct tomoyo_path_number_acl, head)
->perm);
break;
case TOMOYO_TYPE_MKDEV_ACL:
perm = container_of(ptr, struct tomoyo_mkdev_acl,
head)->perm;
data_race(perm = container_of(ptr, struct tomoyo_mkdev_acl, head)->perm);
break;
case TOMOYO_TYPE_INET_ACL:
perm = container_of(ptr, struct tomoyo_inet_acl,
head)->perm;
data_race(perm = container_of(ptr, struct tomoyo_inet_acl, head)->perm);
break;
case TOMOYO_TYPE_UNIX_ACL:
perm = container_of(ptr, struct tomoyo_unix_acl,
head)->perm;
data_race(perm = container_of(ptr, struct tomoyo_unix_acl, head)->perm);
break;
case TOMOYO_TYPE_MANUAL_TASK_ACL:
perm = 0;