Merge 3ba310f2a3 ("Merge tag 'lsm-pr-20260410' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm") into android-mainline
Steps on the way to v7.1-rc1 Change-Id: I3cc8f06a585a438eb4e04cf1b324d43dbd1390e4 Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
commit
183b5bfea5
25 files changed
+451
-105
No files matched your search
+13
-5
@@ -12,6 +12,7 @@
|
||||
#include <linux/backing-file.h>
|
||||
#include <linux/splice.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/security.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
@@ -29,14 +30,15 @@
|
||||
* returned file into a container structure that also stores the stacked
|
||||
* file's path, which can be retrieved using backing_file_user_path().
|
||||
*/
|
||||
struct file *backing_file_open(const struct path *user_path, int flags,
|
||||
struct file *backing_file_open(const struct file *user_file, int flags,
|
||||
const struct path *real_path,
|
||||
const struct cred *cred)
|
||||
{
|
||||
const struct path *user_path = &user_file->f_path;
|
||||
struct file *f;
|
||||
int error;
|
||||
|
||||
f = alloc_empty_backing_file(flags, cred);
|
||||
f = alloc_empty_backing_file(flags, cred, user_file);
|
||||
if (IS_ERR(f))
|
||||
return f;
|
||||
|
||||
@@ -52,15 +54,16 @@ struct file *backing_file_open(const struct path *user_path, int flags,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(backing_file_open);
|
||||
|
||||
struct file *backing_tmpfile_open(const struct path *user_path, int flags,
|
||||
struct file *backing_tmpfile_open(const struct file *user_file, int flags,
|
||||
const struct path *real_parentpath,
|
||||
umode_t mode, const struct cred *cred)
|
||||
{
|
||||
struct mnt_idmap *real_idmap = mnt_idmap(real_parentpath->mnt);
|
||||
const struct path *user_path = &user_file->f_path;
|
||||
struct file *f;
|
||||
int error;
|
||||
|
||||
f = alloc_empty_backing_file(flags, cred);
|
||||
f = alloc_empty_backing_file(flags, cred, user_file);
|
||||
if (IS_ERR(f))
|
||||
return f;
|
||||
|
||||
@@ -336,8 +339,13 @@ int backing_file_mmap(struct file *file, struct vm_area_struct *vma,
|
||||
|
||||
vma_set_file(vma, file);
|
||||
|
||||
scoped_with_creds(ctx->cred)
|
||||
scoped_with_creds(ctx->cred) {
|
||||
ret = security_mmap_backing_file(vma, file, user_file);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = vfs_mmap(vma->vm_file, vma);
|
||||
}
|
||||
|
||||
if (ctx->accessed)
|
||||
ctx->accessed(user_file);
|
||||
|
||||
+9
-1
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include <linux/xxhash.h>
|
||||
#include <linux/mount.h>
|
||||
#include <linux/security.h>
|
||||
#include "internal.h"
|
||||
#include "xattr.h"
|
||||
|
||||
@@ -106,7 +107,8 @@ static int erofs_ishare_file_open(struct inode *inode, struct file *file)
|
||||
|
||||
if (file->f_flags & O_DIRECT)
|
||||
return -EINVAL;
|
||||
realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred());
|
||||
realfile = alloc_empty_backing_file(O_RDONLY|O_NOATIME, current_cred(),
|
||||
file);
|
||||
if (IS_ERR(realfile))
|
||||
return PTR_ERR(realfile);
|
||||
ihold(sharedinode);
|
||||
@@ -150,8 +152,14 @@ static ssize_t erofs_ishare_file_read_iter(struct kiocb *iocb,
|
||||
static int erofs_ishare_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
{
|
||||
struct file *realfile = file->private_data;
|
||||
int err;
|
||||
|
||||
vma_set_file(vma, realfile);
|
||||
|
||||
err = security_mmap_backing_file(vma, realfile, file);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return generic_file_readonly_mmap(file, vma);
|
||||
}
|
||||
|
||||
|
||||
+40
-3
@@ -54,6 +54,9 @@ struct backing_file {
|
||||
struct path user_path;
|
||||
freeptr_t bf_freeptr;
|
||||
};
|
||||
#ifdef CONFIG_SECURITY
|
||||
void *security;
|
||||
#endif
|
||||
};
|
||||
|
||||
#define backing_file(f) container_of(f, struct backing_file, file)
|
||||
@@ -70,6 +73,25 @@ void backing_file_set_user_path(struct file *f, const struct path *path)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(backing_file_set_user_path);
|
||||
|
||||
#ifdef CONFIG_SECURITY
|
||||
void *backing_file_security(const struct file *f)
|
||||
{
|
||||
return backing_file(f)->security;
|
||||
}
|
||||
|
||||
void backing_file_set_security(struct file *f, void *security)
|
||||
{
|
||||
backing_file(f)->security = security;
|
||||
}
|
||||
#endif /* CONFIG_SECURITY */
|
||||
|
||||
static inline void backing_file_free(struct backing_file *ff)
|
||||
{
|
||||
security_backing_file_free(&ff->file);
|
||||
path_put(&ff->user_path);
|
||||
kmem_cache_free(bfilp_cache, ff);
|
||||
}
|
||||
|
||||
static inline void file_free(struct file *f)
|
||||
{
|
||||
security_file_free(f);
|
||||
@@ -77,8 +99,7 @@ static inline void file_free(struct file *f)
|
||||
percpu_counter_dec(&nr_files);
|
||||
put_cred(f->f_cred);
|
||||
if (unlikely(f->f_mode & FMODE_BACKING)) {
|
||||
path_put(backing_file_user_path(f));
|
||||
kmem_cache_free(bfilp_cache, backing_file(f));
|
||||
backing_file_free(backing_file(f));
|
||||
} else {
|
||||
kmem_cache_free(filp_cache, f);
|
||||
}
|
||||
@@ -287,6 +308,14 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
|
||||
return f;
|
||||
}
|
||||
|
||||
static int init_backing_file(struct backing_file *ff,
|
||||
const struct file *user_file)
|
||||
{
|
||||
memset(&ff->user_path, 0, sizeof(ff->user_path));
|
||||
backing_file_set_security(&ff->file, NULL);
|
||||
return security_backing_file_alloc(&ff->file, user_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Variant of alloc_empty_file() that allocates a backing_file container
|
||||
* and doesn't check and modify nr_files.
|
||||
@@ -294,7 +323,8 @@ struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred)
|
||||
* This is only for kernel internal use, and the allocate file must not be
|
||||
* installed into file tables or such.
|
||||
*/
|
||||
struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
|
||||
struct file *alloc_empty_backing_file(int flags, const struct cred *cred,
|
||||
const struct file *user_file)
|
||||
{
|
||||
struct backing_file *ff;
|
||||
int error;
|
||||
@@ -309,7 +339,14 @@ struct file *alloc_empty_backing_file(int flags, const struct cred *cred)
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
/* The f_mode flags must be set before fput(). */
|
||||
ff->file.f_mode |= FMODE_BACKING | FMODE_NOACCOUNT;
|
||||
error = init_backing_file(ff, user_file);
|
||||
if (unlikely(error)) {
|
||||
fput(&ff->file);
|
||||
return ERR_PTR(error);
|
||||
}
|
||||
|
||||
return &ff->file;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(alloc_empty_backing_file);
|
||||
|
||||
@@ -188,7 +188,7 @@ struct fuse_backing *fuse_passthrough_open(struct file *file, int backing_id)
|
||||
goto out;
|
||||
|
||||
/* Allocate backing file per fuse file to store fuse path */
|
||||
backing_file = backing_file_open(&file->f_path, file->f_flags,
|
||||
backing_file = backing_file_open(file, file->f_flags,
|
||||
&fb->file->f_path, fb->cred);
|
||||
err = PTR_ERR(backing_file);
|
||||
if (IS_ERR(backing_file)) {
|
||||
|
||||
+2
-1
@@ -106,7 +106,8 @@ extern void chroot_fs_refs(const struct path *, const struct path *);
|
||||
*/
|
||||
struct file *alloc_empty_file(int flags, const struct cred *cred);
|
||||
struct file *alloc_empty_file_noaccount(int flags, const struct cred *cred);
|
||||
struct file *alloc_empty_backing_file(int flags, const struct cred *cred);
|
||||
struct file *alloc_empty_backing_file(int flags, const struct cred *cred,
|
||||
const struct file *user_file);
|
||||
void backing_file_set_user_path(struct file *f, const struct path *path);
|
||||
|
||||
static inline void file_put_write_access(struct file *file)
|
||||
|
||||
+1
-1
@@ -1389,7 +1389,7 @@ static int ovl_create_tmpfile(struct file *file, struct dentry *dentry,
|
||||
return PTR_ERR(cred);
|
||||
|
||||
ovl_path_upper(dentry->d_parent, &realparentpath);
|
||||
realfile = backing_tmpfile_open(&file->f_path, flags, &realparentpath,
|
||||
realfile = backing_tmpfile_open(file, flags, &realparentpath,
|
||||
mode, current_cred());
|
||||
err = PTR_ERR_OR_ZERO(realfile);
|
||||
pr_debug("tmpfile/open(%pd2, 0%o) = %i\n", realparentpath.dentry, mode, err);
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ static struct file *ovl_open_realfile(const struct file *file,
|
||||
if (!inode_owner_or_capable(real_idmap, realinode))
|
||||
flags &= ~O_NOATIME;
|
||||
|
||||
realfile = backing_file_open(file_user_path(file),
|
||||
realfile = backing_file_open(file,
|
||||
flags, realpath, current_cred());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,15 @@
|
||||
#include <uapi/linux/audit.h>
|
||||
#include <uapi/linux/fanotify.h>
|
||||
|
||||
#define AUDIT_STATUS_ALL (AUDIT_STATUS_ENABLED | \
|
||||
AUDIT_STATUS_FAILURE | \
|
||||
AUDIT_STATUS_PID | \
|
||||
AUDIT_STATUS_RATE_LIMIT | \
|
||||
AUDIT_STATUS_BACKLOG_LIMIT | \
|
||||
AUDIT_STATUS_BACKLOG_WAIT_TIME | \
|
||||
AUDIT_STATUS_LOST | \
|
||||
AUDIT_STATUS_BACKLOG_WAIT_TIME_ACTUAL)
|
||||
|
||||
#define AUDIT_INO_UNSET ((u64)-1)
|
||||
#define AUDIT_DEV_UNSET ((dev_t)-1)
|
||||
|
||||
|
||||
@@ -18,10 +18,10 @@ struct backing_file_ctx {
|
||||
void (*end_write)(struct kiocb *iocb, ssize_t);
|
||||
};
|
||||
|
||||
struct file *backing_file_open(const struct path *user_path, int flags,
|
||||
struct file *backing_file_open(const struct file *user_file, int flags,
|
||||
const struct path *real_path,
|
||||
const struct cred *cred);
|
||||
struct file *backing_tmpfile_open(const struct path *user_path, int flags,
|
||||
struct file *backing_tmpfile_open(const struct file *user_file, int flags,
|
||||
const struct path *real_parentpath,
|
||||
umode_t mode, const struct cred *cred);
|
||||
ssize_t backing_file_read_iter(struct file *file, struct iov_iter *iter,
|
||||
|
||||
@@ -33,12 +33,14 @@ struct group_info {
|
||||
|
||||
/**
|
||||
* get_group_info - Get a reference to a group info structure
|
||||
* @group_info: The group info to reference
|
||||
* @gi: The group info to reference
|
||||
*
|
||||
* This gets a reference to a set of supplementary groups.
|
||||
*
|
||||
* If the caller is accessing a task's credentials, they must hold the RCU read
|
||||
* lock when reading.
|
||||
*
|
||||
* Returns: @gi
|
||||
*/
|
||||
static inline struct group_info *get_group_info(struct group_info *gi)
|
||||
{
|
||||
@@ -209,6 +211,8 @@ DEFINE_CLASS(override_creds,
|
||||
* usage count. The purpose of this is to attempt to catch at compile time the
|
||||
* accidental alteration of a set of credentials that should be considered
|
||||
* immutable.
|
||||
*
|
||||
* Returns: @cred when the references are acquired, NULL otherwise.
|
||||
*/
|
||||
static inline const struct cred *get_cred_many(const struct cred *cred, int nr)
|
||||
{
|
||||
@@ -246,8 +250,8 @@ static inline const struct cred *get_cred_rcu(const struct cred *cred)
|
||||
}
|
||||
|
||||
/**
|
||||
* put_cred - Release a reference to a set of credentials
|
||||
* @cred: The credentials to release
|
||||
* put_cred_many - Release a reference to a set of credentials
|
||||
* @_cred: The credentials to release
|
||||
* @nr: Number of references to release
|
||||
*
|
||||
* Release a reference to a set of credentials, deleting them when the last ref
|
||||
|
||||
@@ -2475,6 +2475,19 @@ struct file *dentry_create(struct path *path, int flags, umode_t mode,
|
||||
const struct cred *cred);
|
||||
const struct path *backing_file_user_path(const struct file *f);
|
||||
|
||||
#ifdef CONFIG_SECURITY
|
||||
void *backing_file_security(const struct file *f);
|
||||
void backing_file_set_security(struct file *f, void *security);
|
||||
#else
|
||||
static inline void *backing_file_security(const struct file *f)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline void backing_file_set_security(struct file *f, void *security)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_SECURITY */
|
||||
|
||||
/*
|
||||
* When mmapping a file on a stackable filesystem (e.g., overlayfs), the file
|
||||
* stored in ->vm_file is a backing file whose f_inode is on the underlying
|
||||
|
||||
@@ -94,7 +94,7 @@ struct common_audit_data {
|
||||
#endif
|
||||
char *kmod_name;
|
||||
struct lsm_ioctlop_audit *op;
|
||||
struct file *file;
|
||||
const struct file *file;
|
||||
struct lsm_ibpkey_audit *ibpkey;
|
||||
struct lsm_ibendport_audit *ibendport;
|
||||
int reason;
|
||||
|
||||
@@ -191,6 +191,9 @@ LSM_HOOK(int, 0, file_permission, struct file *file, int mask)
|
||||
LSM_HOOK(int, 0, file_alloc_security, struct file *file)
|
||||
LSM_HOOK(void, LSM_RET_VOID, file_release, struct file *file)
|
||||
LSM_HOOK(void, LSM_RET_VOID, file_free_security, struct file *file)
|
||||
LSM_HOOK(int, 0, backing_file_alloc, struct file *backing_file,
|
||||
const struct file *user_file)
|
||||
LSM_HOOK(void, LSM_RET_VOID, backing_file_free, struct file *backing_file)
|
||||
LSM_HOOK(int, 0, file_ioctl, struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd,
|
||||
@@ -198,6 +201,8 @@ LSM_HOOK(int, 0, file_ioctl_compat, struct file *file, unsigned int cmd,
|
||||
LSM_HOOK(int, 0, mmap_addr, unsigned long addr)
|
||||
LSM_HOOK(int, 0, mmap_file, struct file *file, unsigned long reqprot,
|
||||
unsigned long prot, unsigned long flags)
|
||||
LSM_HOOK(int, 0, mmap_backing_file, struct vm_area_struct *vma,
|
||||
struct file *backing_file, struct file *user_file)
|
||||
LSM_HOOK(int, 0, file_mprotect, struct vm_area_struct *vma,
|
||||
unsigned long reqprot, unsigned long prot)
|
||||
LSM_HOOK(int, 0, file_lock, struct file *file, unsigned int cmd)
|
||||
|
||||
@@ -104,6 +104,7 @@ struct security_hook_list {
|
||||
struct lsm_blob_sizes {
|
||||
unsigned int lbs_cred;
|
||||
unsigned int lbs_file;
|
||||
unsigned int lbs_backing_file;
|
||||
unsigned int lbs_ib;
|
||||
unsigned int lbs_inode;
|
||||
unsigned int lbs_sock;
|
||||
|
||||
@@ -472,11 +472,17 @@ int security_file_permission(struct file *file, int mask);
|
||||
int security_file_alloc(struct file *file);
|
||||
void security_file_release(struct file *file);
|
||||
void security_file_free(struct file *file);
|
||||
int security_backing_file_alloc(struct file *backing_file,
|
||||
const struct file *user_file);
|
||||
void security_backing_file_free(struct file *backing_file);
|
||||
int security_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
|
||||
int security_file_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
int security_mmap_file(struct file *file, unsigned long prot,
|
||||
unsigned long flags);
|
||||
int security_mmap_backing_file(struct vm_area_struct *vma,
|
||||
struct file *backing_file,
|
||||
struct file *user_file);
|
||||
int security_mmap_addr(unsigned long addr);
|
||||
int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot,
|
||||
unsigned long prot);
|
||||
@@ -1141,6 +1147,15 @@ static inline void security_file_release(struct file *file)
|
||||
static inline void security_file_free(struct file *file)
|
||||
{ }
|
||||
|
||||
static inline int security_backing_file_alloc(struct file *backing_file,
|
||||
const struct file *user_file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void security_backing_file_free(struct file *backing_file)
|
||||
{ }
|
||||
|
||||
static inline int security_file_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
@@ -1160,6 +1175,13 @@ static inline int security_mmap_file(struct file *file, unsigned long prot,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_mmap_backing_file(struct vm_area_struct *vma,
|
||||
struct file *backing_file,
|
||||
struct file *user_file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int security_mmap_addr(unsigned long addr)
|
||||
{
|
||||
return cap_mmap_addr(addr);
|
||||
|
||||
@@ -350,7 +350,7 @@ enum {
|
||||
#define AUDIT_STATUS_ENABLED 0x0001
|
||||
#define AUDIT_STATUS_FAILURE 0x0002
|
||||
#define AUDIT_STATUS_PID 0x0004
|
||||
#define AUDIT_STATUS_RATE_LIMIT 0x0008
|
||||
#define AUDIT_STATUS_RATE_LIMIT 0x0008
|
||||
#define AUDIT_STATUS_BACKLOG_LIMIT 0x0010
|
||||
#define AUDIT_STATUS_BACKLOG_WAIT_TIME 0x0020
|
||||
#define AUDIT_STATUS_LOST 0x0040
|
||||
@@ -386,8 +386,8 @@ enum {
|
||||
* These bits disambiguate different calling conventions that share an
|
||||
* ELF machine type, bitness, and endianness
|
||||
*/
|
||||
#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000
|
||||
#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000
|
||||
#define __AUDIT_ARCH_CONVENTION_MASK 0x30000000
|
||||
#define __AUDIT_ARCH_CONVENTION_MIPS64_N32 0x20000000
|
||||
|
||||
/* distinguish syscall tables */
|
||||
#define __AUDIT_ARCH_64BIT 0x80000000
|
||||
@@ -508,7 +508,7 @@ struct audit_tty_status {
|
||||
__u32 log_passwd; /* 1 = enabled, 0 = disabled */
|
||||
};
|
||||
|
||||
#define AUDIT_UID_UNSET (unsigned int)-1
|
||||
#define AUDIT_UID_UNSET ((unsigned int)-1)
|
||||
#define AUDIT_SID_UNSET ((unsigned int)-1)
|
||||
|
||||
/* audit_rule_data supports filter rules with both integer and string
|
||||
|
||||
+5
-3
@@ -355,8 +355,8 @@ void audit_panic(const char *message)
|
||||
|
||||
static inline int audit_rate_check(void)
|
||||
{
|
||||
static unsigned long last_check = 0;
|
||||
static int messages = 0;
|
||||
static unsigned long last_check;
|
||||
static int messages;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
unsigned long flags;
|
||||
unsigned long now;
|
||||
@@ -391,7 +391,7 @@ static inline int audit_rate_check(void)
|
||||
*/
|
||||
void audit_log_lost(const char *message)
|
||||
{
|
||||
static unsigned long last_msg = 0;
|
||||
static unsigned long last_msg;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
unsigned long flags;
|
||||
unsigned long now;
|
||||
@@ -1295,6 +1295,8 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
|
||||
memset(&s, 0, sizeof(s));
|
||||
/* guard against past and future API changes */
|
||||
memcpy(&s, data, min_t(size_t, sizeof(s), data_len));
|
||||
if (s.mask & ~AUDIT_STATUS_ALL)
|
||||
return -EINVAL;
|
||||
if (s.mask & AUDIT_STATUS_ENABLED) {
|
||||
err = audit_set_enabled(s.enabled);
|
||||
if (err < 0)
|
||||
|
||||
@@ -303,8 +303,7 @@ exit_err:
|
||||
return ERR_PTR(err);
|
||||
}
|
||||
|
||||
static u32 audit_ops[] =
|
||||
{
|
||||
static u32 audit_ops[] = {
|
||||
[Audit_equal] = AUDIT_EQUAL,
|
||||
[Audit_not_equal] = AUDIT_NOT_EQUAL,
|
||||
[Audit_bitmask] = AUDIT_BIT_MASK,
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ int audit_classify_syscall(int abi, unsigned syscall)
|
||||
if (audit_is_compat(abi))
|
||||
return audit_classify_compat_syscall(abi, syscall);
|
||||
|
||||
switch(syscall) {
|
||||
switch (syscall) {
|
||||
#ifdef __NR_open
|
||||
case __NR_open:
|
||||
return AUDITSC_OPEN;
|
||||
|
||||
+5
-5
@@ -30,7 +30,7 @@ static int mount_count;
|
||||
static void securityfs_free_inode(struct inode *inode)
|
||||
{
|
||||
if (S_ISLNK(inode->i_mode))
|
||||
kfree(inode->i_link);
|
||||
kfree_const(inode->i_link);
|
||||
free_inode_nonrcu(inode);
|
||||
}
|
||||
|
||||
@@ -258,17 +258,17 @@ struct dentry *securityfs_create_symlink(const char *name,
|
||||
const struct inode_operations *iops)
|
||||
{
|
||||
struct dentry *dent;
|
||||
char *link = NULL;
|
||||
const char *link = NULL;
|
||||
|
||||
if (target) {
|
||||
link = kstrdup(target, GFP_KERNEL);
|
||||
link = kstrdup_const(target, GFP_KERNEL);
|
||||
if (!link)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
}
|
||||
dent = securityfs_create_dentry(name, S_IFLNK | 0444, parent,
|
||||
link, NULL, iops);
|
||||
(void *)link, NULL, iops);
|
||||
if (IS_ERR(dent))
|
||||
kfree(link);
|
||||
kfree_const(link);
|
||||
|
||||
return dent;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ extern struct lsm_blob_sizes blob_sizes;
|
||||
|
||||
/* LSM blob caches */
|
||||
extern struct kmem_cache *lsm_file_cache;
|
||||
extern struct kmem_cache *lsm_backing_file_cache;
|
||||
extern struct kmem_cache *lsm_inode_cache;
|
||||
|
||||
/* LSM blob allocators */
|
||||
|
||||
@@ -293,6 +293,8 @@ static void __init lsm_prepare(struct lsm_info *lsm)
|
||||
blobs = lsm->blobs;
|
||||
lsm_blob_size_update(&blobs->lbs_cred, &blob_sizes.lbs_cred);
|
||||
lsm_blob_size_update(&blobs->lbs_file, &blob_sizes.lbs_file);
|
||||
lsm_blob_size_update(&blobs->lbs_backing_file,
|
||||
&blob_sizes.lbs_backing_file);
|
||||
lsm_blob_size_update(&blobs->lbs_ib, &blob_sizes.lbs_ib);
|
||||
/* inode blob gets an rcu_head in addition to LSM blobs. */
|
||||
if (blobs->lbs_inode && blob_sizes.lbs_inode == 0)
|
||||
@@ -441,6 +443,8 @@ int __init security_init(void)
|
||||
if (lsm_debug) {
|
||||
lsm_pr("blob(cred) size %d\n", blob_sizes.lbs_cred);
|
||||
lsm_pr("blob(file) size %d\n", blob_sizes.lbs_file);
|
||||
lsm_pr("blob(backing_file) size %d\n",
|
||||
blob_sizes.lbs_backing_file);
|
||||
lsm_pr("blob(ib) size %d\n", blob_sizes.lbs_ib);
|
||||
lsm_pr("blob(inode) size %d\n", blob_sizes.lbs_inode);
|
||||
lsm_pr("blob(ipc) size %d\n", blob_sizes.lbs_ipc);
|
||||
@@ -462,6 +466,11 @@ int __init security_init(void)
|
||||
lsm_file_cache = kmem_cache_create("lsm_file_cache",
|
||||
blob_sizes.lbs_file, 0,
|
||||
SLAB_PANIC, NULL);
|
||||
if (blob_sizes.lbs_backing_file)
|
||||
lsm_backing_file_cache = kmem_cache_create(
|
||||
"lsm_backing_file_cache",
|
||||
blob_sizes.lbs_backing_file,
|
||||
0, SLAB_PANIC, NULL);
|
||||
if (blob_sizes.lbs_inode)
|
||||
lsm_inode_cache = kmem_cache_create("lsm_inode_cache",
|
||||
blob_sizes.lbs_inode, 0,
|
||||
|
||||
@@ -82,6 +82,7 @@ const struct lsm_id *lsm_idlist[MAX_LSM_COUNT];
|
||||
struct lsm_blob_sizes blob_sizes;
|
||||
|
||||
struct kmem_cache *lsm_file_cache;
|
||||
struct kmem_cache *lsm_backing_file_cache;
|
||||
struct kmem_cache *lsm_inode_cache;
|
||||
|
||||
#define SECURITY_HOOK_ACTIVE_KEY(HOOK, IDX) security_hook_active_##HOOK##_##IDX
|
||||
@@ -173,6 +174,30 @@ static int lsm_file_alloc(struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lsm_backing_file_alloc - allocate a composite backing file blob
|
||||
* @backing_file: the backing file
|
||||
*
|
||||
* Allocate the backing file blob for all the modules.
|
||||
*
|
||||
* Returns 0, or -ENOMEM if memory can't be allocated.
|
||||
*/
|
||||
static int lsm_backing_file_alloc(struct file *backing_file)
|
||||
{
|
||||
void *blob;
|
||||
|
||||
if (!lsm_backing_file_cache) {
|
||||
backing_file_set_security(backing_file, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
blob = kmem_cache_zalloc(lsm_backing_file_cache, GFP_KERNEL);
|
||||
backing_file_set_security(backing_file, blob);
|
||||
if (!blob)
|
||||
return -ENOMEM;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lsm_blob_alloc - allocate a composite blob
|
||||
* @dest: the destination for the blob
|
||||
@@ -2418,6 +2443,57 @@ void security_file_free(struct file *file)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* security_backing_file_alloc() - Allocate and setup a backing file blob
|
||||
* @backing_file: the backing file
|
||||
* @user_file: the associated user visible file
|
||||
*
|
||||
* Allocate a backing file LSM blob and perform any necessary initialization of
|
||||
* the LSM blob. There will be some operations where the LSM will not have
|
||||
* access to @user_file after this point, so any important state associated
|
||||
* with @user_file that is important to the LSM should be captured in the
|
||||
* backing file's LSM blob.
|
||||
*
|
||||
* LSM's should avoid taking a reference to @user_file in this hook as it will
|
||||
* result in problems later when the system attempts to drop/put the file
|
||||
* references due to a circular dependency.
|
||||
*
|
||||
* Return: Return 0 if the hook is successful, negative values otherwise.
|
||||
*/
|
||||
int security_backing_file_alloc(struct file *backing_file,
|
||||
const struct file *user_file)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = lsm_backing_file_alloc(backing_file);
|
||||
if (rc)
|
||||
return rc;
|
||||
rc = call_int_hook(backing_file_alloc, backing_file, user_file);
|
||||
if (unlikely(rc))
|
||||
security_backing_file_free(backing_file);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* security_backing_file_free() - Free a backing file blob
|
||||
* @backing_file: the backing file
|
||||
*
|
||||
* Free any LSM state associate with a backing file's LSM blob, including the
|
||||
* blob itself.
|
||||
*/
|
||||
void security_backing_file_free(struct file *backing_file)
|
||||
{
|
||||
void *blob = backing_file_security(backing_file);
|
||||
|
||||
call_void_hook(backing_file_free, backing_file);
|
||||
|
||||
if (blob) {
|
||||
backing_file_set_security(backing_file, NULL);
|
||||
kmem_cache_free(lsm_backing_file_cache, blob);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* security_file_ioctl() - Check if an ioctl is allowed
|
||||
* @file: associated file
|
||||
@@ -2506,6 +2582,32 @@ int security_mmap_file(struct file *file, unsigned long prot,
|
||||
flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* security_mmap_backing_file - Check if mmap'ing a backing file is allowed
|
||||
* @vma: the vm_area_struct for the mmap'd region
|
||||
* @backing_file: the backing file being mmap'd
|
||||
* @user_file: the user file being mmap'd
|
||||
*
|
||||
* Check permissions for a mmap operation on a stacked filesystem. This hook
|
||||
* is called after the security_mmap_file() and is responsible for authorizing
|
||||
* the mmap on @backing_file. It is important to note that the mmap operation
|
||||
* on @user_file has already been authorized and the @vma->vm_file has been
|
||||
* set to @backing_file.
|
||||
*
|
||||
* Return: Returns 0 if permission is granted.
|
||||
*/
|
||||
int security_mmap_backing_file(struct vm_area_struct *vma,
|
||||
struct file *backing_file,
|
||||
struct file *user_file)
|
||||
{
|
||||
/* recommended by the stackable filesystem devs */
|
||||
if (WARN_ON_ONCE(!(backing_file->f_mode & FMODE_BACKING)))
|
||||
return -EIO;
|
||||
|
||||
return call_int_hook(mmap_backing_file, vma, backing_file, user_file);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(security_mmap_backing_file);
|
||||
|
||||
/**
|
||||
* security_mmap_addr() - Check if mmap'ing an address is allowed
|
||||
* @addr: address
|
||||
|
||||
+185
-71
@@ -1745,6 +1745,60 @@ static inline int file_path_has_perm(const struct cred *cred,
|
||||
static int bpf_fd_pass(const struct file *file, u32 sid);
|
||||
#endif
|
||||
|
||||
static int __file_has_perm(const struct cred *cred, const struct file *file,
|
||||
u32 av, bool bf_user_file)
|
||||
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
struct inode *inode;
|
||||
u32 ssid = cred_sid(cred);
|
||||
u32 tsid_fd;
|
||||
int rc;
|
||||
|
||||
if (bf_user_file) {
|
||||
struct backing_file_security_struct *bfsec;
|
||||
const struct path *path;
|
||||
|
||||
if (WARN_ON(!(file->f_mode & FMODE_BACKING)))
|
||||
return -EIO;
|
||||
|
||||
bfsec = selinux_backing_file(file);
|
||||
path = backing_file_user_path(file);
|
||||
tsid_fd = bfsec->uf_sid;
|
||||
inode = d_inode(path->dentry);
|
||||
|
||||
ad.type = LSM_AUDIT_DATA_PATH;
|
||||
ad.u.path = *path;
|
||||
} else {
|
||||
struct file_security_struct *fsec = selinux_file(file);
|
||||
|
||||
tsid_fd = fsec->sid;
|
||||
inode = file_inode(file);
|
||||
|
||||
ad.type = LSM_AUDIT_DATA_FILE;
|
||||
ad.u.file = file;
|
||||
}
|
||||
|
||||
if (ssid != tsid_fd) {
|
||||
rc = avc_has_perm(ssid, tsid_fd, SECCLASS_FD, FD__USE, &ad);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
/* regardless of backing vs user file, use the underlying file here */
|
||||
rc = bpf_fd_pass(file, ssid);
|
||||
if (rc)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
/* av is zero if only checking access to the descriptor. */
|
||||
if (av)
|
||||
return inode_has_perm(cred, inode, av, &ad);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check whether a task can use an open file descriptor to
|
||||
access an inode in a given way. Check access to the
|
||||
descriptor itself, and then use dentry_has_perm to
|
||||
@@ -1753,41 +1807,10 @@ static int bpf_fd_pass(const struct file *file, u32 sid);
|
||||
has the same SID as the process. If av is zero, then
|
||||
access to the file is not checked, e.g. for cases
|
||||
where only the descriptor is affected like seek. */
|
||||
static int file_has_perm(const struct cred *cred,
|
||||
struct file *file,
|
||||
u32 av)
|
||||
static inline int file_has_perm(const struct cred *cred,
|
||||
const struct file *file, u32 av)
|
||||
{
|
||||
struct file_security_struct *fsec = selinux_file(file);
|
||||
struct inode *inode = file_inode(file);
|
||||
struct common_audit_data ad;
|
||||
u32 sid = cred_sid(cred);
|
||||
int rc;
|
||||
|
||||
ad.type = LSM_AUDIT_DATA_FILE;
|
||||
ad.u.file = file;
|
||||
|
||||
if (sid != fsec->sid) {
|
||||
rc = avc_has_perm(sid, fsec->sid,
|
||||
SECCLASS_FD,
|
||||
FD__USE,
|
||||
&ad);
|
||||
if (rc)
|
||||
goto out;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_BPF_SYSCALL
|
||||
rc = bpf_fd_pass(file, cred_sid(cred));
|
||||
if (rc)
|
||||
return rc;
|
||||
#endif
|
||||
|
||||
/* av is zero if only checking access to the descriptor. */
|
||||
rc = 0;
|
||||
if (av)
|
||||
rc = inode_has_perm(cred, inode, av, &ad);
|
||||
|
||||
out:
|
||||
return rc;
|
||||
return __file_has_perm(cred, file, av, false);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3825,6 +3848,17 @@ static int selinux_file_alloc_security(struct file *file)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int selinux_backing_file_alloc(struct file *backing_file,
|
||||
const struct file *user_file)
|
||||
{
|
||||
struct backing_file_security_struct *bfsec;
|
||||
|
||||
bfsec = selinux_backing_file(backing_file);
|
||||
bfsec->uf_sid = selinux_file(user_file)->sid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check whether a task has the ioctl permission and cmd
|
||||
* operation to an inode.
|
||||
@@ -3942,42 +3976,55 @@ static int selinux_file_ioctl_compat(struct file *file, unsigned int cmd,
|
||||
|
||||
static int default_noexec __ro_after_init;
|
||||
|
||||
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
|
||||
static int __file_map_prot_check(const struct cred *cred,
|
||||
const struct file *file, unsigned long prot,
|
||||
bool shared, bool bf_user_file)
|
||||
{
|
||||
const struct cred *cred = current_cred();
|
||||
u32 sid = cred_sid(cred);
|
||||
int rc = 0;
|
||||
struct inode *inode = NULL;
|
||||
bool prot_exec = prot & PROT_EXEC;
|
||||
bool prot_write = prot & PROT_WRITE;
|
||||
|
||||
if (file) {
|
||||
if (bf_user_file)
|
||||
inode = d_inode(backing_file_user_path(file)->dentry);
|
||||
else
|
||||
inode = file_inode(file);
|
||||
}
|
||||
|
||||
if (default_noexec && prot_exec &&
|
||||
(!file || IS_PRIVATE(inode) || (!shared && prot_write))) {
|
||||
int rc;
|
||||
u32 sid = cred_sid(cred);
|
||||
|
||||
if (default_noexec &&
|
||||
(prot & PROT_EXEC) && (!file || IS_PRIVATE(file_inode(file)) ||
|
||||
(!shared && (prot & PROT_WRITE)))) {
|
||||
/*
|
||||
* We are making executable an anonymous mapping or a
|
||||
* private file mapping that will also be writable.
|
||||
* This has an additional check.
|
||||
* We are making executable an anonymous mapping or a private
|
||||
* file mapping that will also be writable.
|
||||
*/
|
||||
rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
|
||||
PROCESS__EXECMEM, NULL);
|
||||
rc = avc_has_perm(sid, sid, SECCLASS_PROCESS, PROCESS__EXECMEM,
|
||||
NULL);
|
||||
if (rc)
|
||||
goto error;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (file) {
|
||||
/* read access is always possible with a mapping */
|
||||
/* "read" always possible, "write" only if shared */
|
||||
u32 av = FILE__READ;
|
||||
|
||||
/* write access only matters if the mapping is shared */
|
||||
if (shared && (prot & PROT_WRITE))
|
||||
if (shared && prot_write)
|
||||
av |= FILE__WRITE;
|
||||
|
||||
if (prot & PROT_EXEC)
|
||||
if (prot_exec)
|
||||
av |= FILE__EXECUTE;
|
||||
|
||||
return file_has_perm(cred, file, av);
|
||||
return __file_has_perm(cred, file, av, bf_user_file);
|
||||
}
|
||||
|
||||
error:
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int file_map_prot_check(const struct cred *cred,
|
||||
const struct file *file,
|
||||
unsigned long prot, bool shared)
|
||||
{
|
||||
return __file_map_prot_check(cred, file, prot, shared, false);
|
||||
}
|
||||
|
||||
static int selinux_mmap_addr(unsigned long addr)
|
||||
@@ -3993,36 +4040,80 @@ static int selinux_mmap_addr(unsigned long addr)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int selinux_mmap_file(struct file *file,
|
||||
unsigned long reqprot __always_unused,
|
||||
unsigned long prot, unsigned long flags)
|
||||
static int selinux_mmap_file_common(const struct cred *cred, struct file *file,
|
||||
unsigned long prot, bool shared)
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
int rc;
|
||||
|
||||
if (file) {
|
||||
int rc;
|
||||
struct common_audit_data ad;
|
||||
|
||||
ad.type = LSM_AUDIT_DATA_FILE;
|
||||
ad.u.file = file;
|
||||
rc = inode_has_perm(current_cred(), file_inode(file),
|
||||
FILE__MAP, &ad);
|
||||
rc = inode_has_perm(cred, file_inode(file), FILE__MAP, &ad);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return file_map_prot_check(file, prot,
|
||||
(flags & MAP_TYPE) == MAP_SHARED);
|
||||
return file_map_prot_check(cred, file, prot, shared);
|
||||
}
|
||||
|
||||
static int selinux_mmap_file(struct file *file,
|
||||
unsigned long reqprot __always_unused,
|
||||
unsigned long prot, unsigned long flags)
|
||||
{
|
||||
return selinux_mmap_file_common(current_cred(), file, prot,
|
||||
(flags & MAP_TYPE) == MAP_SHARED);
|
||||
}
|
||||
|
||||
/**
|
||||
* selinux_mmap_backing_file - Check mmap permissions on a backing file
|
||||
* @vma: memory region
|
||||
* @backing_file: stacked filesystem backing file
|
||||
* @user_file: user visible file
|
||||
*
|
||||
* This is called after selinux_mmap_file() on stacked filesystems, and it
|
||||
* is this function's responsibility to verify access to @backing_file and
|
||||
* setup the SELinux state for possible later use in the mprotect() code path.
|
||||
*
|
||||
* By the time this function is called, mmap() access to @user_file has already
|
||||
* been authorized and @vma->vm_file has been set to point to @backing_file.
|
||||
*
|
||||
* Return zero on success, negative values otherwise.
|
||||
*/
|
||||
static int selinux_mmap_backing_file(struct vm_area_struct *vma,
|
||||
struct file *backing_file,
|
||||
struct file *user_file __always_unused)
|
||||
{
|
||||
unsigned long prot = 0;
|
||||
|
||||
/* translate vma->vm_flags perms into PROT perms */
|
||||
if (vma->vm_flags & VM_READ)
|
||||
prot |= PROT_READ;
|
||||
if (vma->vm_flags & VM_WRITE)
|
||||
prot |= PROT_WRITE;
|
||||
if (vma->vm_flags & VM_EXEC)
|
||||
prot |= PROT_EXEC;
|
||||
|
||||
return selinux_mmap_file_common(backing_file->f_cred, backing_file,
|
||||
prot, vma->vm_flags & VM_SHARED);
|
||||
}
|
||||
|
||||
static int selinux_file_mprotect(struct vm_area_struct *vma,
|
||||
unsigned long reqprot __always_unused,
|
||||
unsigned long prot)
|
||||
{
|
||||
int rc;
|
||||
const struct cred *cred = current_cred();
|
||||
u32 sid = cred_sid(cred);
|
||||
const struct file *file = vma->vm_file;
|
||||
bool backing_file;
|
||||
bool shared = vma->vm_flags & VM_SHARED;
|
||||
|
||||
/* check if we need to trigger the "backing files are awful" mode */
|
||||
backing_file = file && (file->f_mode & FMODE_BACKING);
|
||||
|
||||
if (default_noexec &&
|
||||
(prot & PROT_EXEC) && !(vma->vm_flags & VM_EXEC)) {
|
||||
int rc = 0;
|
||||
/*
|
||||
* We don't use the vma_is_initial_heap() helper as it has
|
||||
* a history of problems and is currently broken on systems
|
||||
@@ -4036,11 +4127,15 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
|
||||
vma->vm_end <= vma->vm_mm->brk) {
|
||||
rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
|
||||
PROCESS__EXECHEAP, NULL);
|
||||
} else if (!vma->vm_file && (vma_is_initial_stack(vma) ||
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (!file && (vma_is_initial_stack(vma) ||
|
||||
vma_is_stack_for_current(vma))) {
|
||||
rc = avc_has_perm(sid, sid, SECCLASS_PROCESS,
|
||||
PROCESS__EXECSTACK, NULL);
|
||||
} else if (vma->vm_file && vma->anon_vma) {
|
||||
if (rc)
|
||||
return rc;
|
||||
} else if (file && vma->anon_vma) {
|
||||
/*
|
||||
* We are making executable a file mapping that has
|
||||
* had some COW done. Since pages might have been
|
||||
@@ -4048,13 +4143,29 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
|
||||
* modified content. This typically should only
|
||||
* occur for text relocations.
|
||||
*/
|
||||
rc = file_has_perm(cred, vma->vm_file, FILE__EXECMOD);
|
||||
rc = __file_has_perm(cred, file, FILE__EXECMOD,
|
||||
backing_file);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (backing_file) {
|
||||
rc = file_has_perm(file->f_cred, file,
|
||||
FILE__EXECMOD);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rc = __file_map_prot_check(cred, file, prot, shared, backing_file);
|
||||
if (rc)
|
||||
return rc;
|
||||
if (backing_file) {
|
||||
rc = file_map_prot_check(file->f_cred, file, prot, shared);
|
||||
if (rc)
|
||||
return rc;
|
||||
}
|
||||
|
||||
return file_map_prot_check(vma->vm_file, prot, vma->vm_flags&VM_SHARED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int selinux_file_lock(struct file *file, unsigned int cmd)
|
||||
@@ -7393,6 +7504,7 @@ struct lsm_blob_sizes selinux_blob_sizes __ro_after_init = {
|
||||
.lbs_cred = sizeof(struct cred_security_struct),
|
||||
.lbs_task = sizeof(struct task_security_struct),
|
||||
.lbs_file = sizeof(struct file_security_struct),
|
||||
.lbs_backing_file = sizeof(struct backing_file_security_struct),
|
||||
.lbs_inode = sizeof(struct inode_security_struct),
|
||||
.lbs_ipc = sizeof(struct ipc_security_struct),
|
||||
.lbs_key = sizeof(struct key_security_struct),
|
||||
@@ -7498,9 +7610,11 @@ static struct security_hook_list selinux_hooks[] __ro_after_init = {
|
||||
|
||||
LSM_HOOK_INIT(file_permission, selinux_file_permission),
|
||||
LSM_HOOK_INIT(file_alloc_security, selinux_file_alloc_security),
|
||||
LSM_HOOK_INIT(backing_file_alloc, selinux_backing_file_alloc),
|
||||
LSM_HOOK_INIT(file_ioctl, selinux_file_ioctl),
|
||||
LSM_HOOK_INIT(file_ioctl_compat, selinux_file_ioctl_compat),
|
||||
LSM_HOOK_INIT(mmap_file, selinux_mmap_file),
|
||||
LSM_HOOK_INIT(mmap_backing_file, selinux_mmap_backing_file),
|
||||
LSM_HOOK_INIT(mmap_addr, selinux_mmap_addr),
|
||||
LSM_HOOK_INIT(file_mprotect, selinux_file_mprotect),
|
||||
LSM_HOOK_INIT(file_lock, selinux_file_lock),
|
||||
|
||||
@@ -88,6 +88,10 @@ struct file_security_struct {
|
||||
u32 pseqno; /* Policy seqno at the time of file open */
|
||||
};
|
||||
|
||||
struct backing_file_security_struct {
|
||||
u32 uf_sid; /* associated user file fsec->sid */
|
||||
};
|
||||
|
||||
struct superblock_security_struct {
|
||||
u32 sid; /* SID of file system superblock */
|
||||
u32 def_sid; /* default SID for labeling */
|
||||
@@ -195,6 +199,13 @@ static inline struct file_security_struct *selinux_file(const struct file *file)
|
||||
return file->f_security + selinux_blob_sizes.lbs_file;
|
||||
}
|
||||
|
||||
static inline struct backing_file_security_struct *
|
||||
selinux_backing_file(const struct file *backing_file)
|
||||
{
|
||||
void *blob = backing_file_security(backing_file);
|
||||
return blob + selinux_blob_sizes.lbs_backing_file;
|
||||
}
|
||||
|
||||
static inline struct inode_security_struct *
|
||||
selinux_inode(const struct inode *inode)
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user