security: selinux: Add Per-File-Encryption hooks

Add hooks for tagging/detecting Per-File-Encryption files.

Change-Id: I9d1f791b68d3552b1a508c21ff8336182e8527fa
Signed-off-by: Amir Samuelov <amirs@codeaurora.org>
This commit is contained in:
Amir Samuelov 2014-05-26 11:44:06 +03:00
parent 854d305299
commit 6a22e4656b
6 changed files with 139 additions and 3 deletions

View File

@ -6,6 +6,7 @@
#include <linux/bio.h>
#include <linux/blkdev.h>
#include <linux/scatterlist.h>
#include <linux/security.h>
#include "blk.h"
@ -509,6 +510,10 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
if (bio_integrity(bio) != blk_integrity_rq(rq))
return false;
/* Don't merge bios of files with different encryption */
if (!security_allow_merge_bio(rq->bio, bio))
return false;
return true;
}

View File

@ -2072,6 +2072,13 @@ int vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode,
if (error)
return error;
error = dir->i_op->create(dir, dentry, mode, nd);
if (error)
return error;
error = security_inode_post_create(dir, dentry, mode);
if (error)
return error;
if (!error)
fsnotify_create(dir, dentry);
return error;
@ -2547,6 +2554,13 @@ int vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t dev)
return error;
error = dir->i_op->mknod(dir, dentry, mode, dev);
if (error)
return error;
error = security_inode_post_create(dir, dentry, mode);
if (error)
return error;
if (!error)
fsnotify_create(dir, dentry);
return error;

View File

@ -1054,6 +1054,7 @@ int filp_close(struct file *filp, fl_owner_t id)
dnotify_flush(filp, id);
locks_remove_posix(filp, id);
}
security_file_close(filp);
fput(filp);
return retval;
}

View File

@ -26,6 +26,7 @@
#include <linux/capability.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/bio.h>
struct linux_binprm;
struct cred;
@ -1453,6 +1454,8 @@ struct security_operations {
void **value, size_t *len);
int (*inode_create) (struct inode *dir,
struct dentry *dentry, umode_t mode);
int (*inode_post_create) (struct inode *dir,
struct dentry *dentry, umode_t mode);
int (*inode_link) (struct dentry *old_dentry,
struct inode *dir, struct dentry *new_dentry);
int (*inode_unlink) (struct inode *dir, struct dentry *dentry);
@ -1503,6 +1506,8 @@ struct security_operations {
struct fown_struct *fown, int sig);
int (*file_receive) (struct file *file);
int (*dentry_open) (struct file *file, const struct cred *cred);
int (*file_close) (struct file *file);
bool (*allow_merge_bio)(struct bio *bio1, struct bio *bio2);
int (*task_create) (unsigned long clone_flags);
void (*task_free) (struct task_struct *task);
@ -1722,6 +1727,9 @@ int security_old_inode_init_security(struct inode *inode, struct inode *dir,
const struct qstr *qstr, char **name,
void **value, size_t *len);
int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode);
int security_inode_post_create(struct inode *dir, struct dentry *dentry,
umode_t mode);
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry);
int security_inode_unlink(struct inode *dir, struct dentry *dentry);
@ -1766,6 +1774,9 @@ int security_file_send_sigiotask(struct task_struct *tsk,
struct fown_struct *fown, int sig);
int security_file_receive(struct file *file);
int security_dentry_open(struct file *file, const struct cred *cred);
int security_file_close(struct file *file);
bool security_allow_merge_bio(struct bio *bio1, struct bio *bio2);
int security_task_create(unsigned long clone_flags);
void security_task_free(struct task_struct *task);
int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
@ -2060,6 +2071,13 @@ static inline int security_inode_create(struct inode *dir,
return 0;
}
static inline int security_inode_post_create(struct inode *dir,
struct dentry *dentry,
umode_t mode)
{
return 0;
}
static inline int security_inode_link(struct dentry *old_dentry,
struct inode *dir,
struct dentry *new_dentry)
@ -2262,6 +2280,16 @@ static inline int security_dentry_open(struct file *file,
return 0;
}
static inline int security_file_close(struct file *file)
{
return 0;
}
static inline bool security_allow_merge_bio(struct bio *bio1, struct bio *bio2)
{
return true; /* The default is to allow it for performance */
}
static inline int security_task_create(unsigned long clone_flags)
{
return 0;

View File

@ -471,6 +471,16 @@ int security_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode
}
EXPORT_SYMBOL_GPL(security_inode_create);
int security_inode_post_create(struct inode *dir, struct dentry *dentry,
umode_t mode)
{
if (unlikely(IS_PRIVATE(dir)))
return 0;
if (security_ops->inode_post_create == NULL)
return 0;
return security_ops->inode_post_create(dir, dentry, mode);
}
int security_inode_link(struct dentry *old_dentry, struct inode *dir,
struct dentry *new_dentry)
{
@ -732,6 +742,22 @@ int security_dentry_open(struct file *file, const struct cred *cred)
return fsnotify_perm(file, MAY_OPEN);
}
int security_file_close(struct file *file)
{
if (security_ops->file_close)
return security_ops->file_close(file);
return 0;
}
bool security_allow_merge_bio(struct bio *bio1, struct bio *bio2)
{
if (security_ops->allow_merge_bio)
return security_ops->allow_merge_bio(bio1, bio2);
return true;
}
int security_task_create(unsigned long clone_flags)
{
return security_ops->task_create(clone_flags);

View File

@ -82,6 +82,7 @@
#include <linux/export.h>
#include <linux/msg.h>
#include <linux/shm.h>
#include <linux/pft.h>
#include "avc.h"
#include "objsec.h"
@ -1617,9 +1618,15 @@ static int may_create(struct inode *dir,
if (rc)
return rc;
return avc_has_perm(newsid, sbsec->sid,
SECCLASS_FILESYSTEM,
FILESYSTEM__ASSOCIATE, &ad);
rc = avc_has_perm(newsid, sbsec->sid,
SECCLASS_FILESYSTEM,
FILESYSTEM__ASSOCIATE, &ad);
if (rc)
return rc;
rc = pft_inode_mknod(dir, dentry, 0, 0);
return rc;
}
/* Check whether a task can create a key. */
@ -1678,6 +1685,12 @@ static int may_link(struct inode *dir,
}
rc = avc_has_perm(sid, isec->sid, isec->sclass, av, &ad);
if (rc)
return rc;
if (kind == MAY_UNLINK)
rc = pft_inode_unlink(dir, dentry);
return rc;
}
@ -2684,9 +2697,25 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
static int selinux_inode_create(struct inode *dir, struct dentry *dentry, umode_t mode)
{
int ret;
ret = pft_inode_create(dir, dentry, mode);
if (ret < 0)
return ret;
return may_create(dir, dentry, SECCLASS_FILE);
}
static int selinux_inode_post_create(struct inode *dir, struct dentry *dentry,
umode_t mode)
{
int ret;
ret = pft_inode_post_create(dir, dentry, mode);
return ret;
}
static int selinux_inode_link(struct dentry *old_dentry, struct inode *dir, struct dentry *new_dentry)
{
return may_link(dir, old_dentry, MAY_LINK);
@ -2720,6 +2749,12 @@ static int selinux_inode_mknod(struct inode *dir, struct dentry *dentry, umode_t
static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dentry,
struct inode *new_inode, struct dentry *new_dentry)
{
int rc;
rc = pft_inode_rename(old_inode, old_dentry, new_inode, new_dentry);
if (rc)
return rc;
return may_rename(old_inode, old_dentry, new_inode, new_dentry);
}
@ -2800,6 +2835,10 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
{
const struct cred *cred = current_cred();
if (pft_inode_set_xattr(dentry, name) < 0)
return -EACCES;
if (!strncmp(name, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
if (!strcmp(name, XATTR_NAME_CAPS)) {
@ -3023,11 +3062,16 @@ static int selinux_file_permission(struct file *file, int mask)
struct file_security_struct *fsec = file->f_security;
struct inode_security_struct *isec = inode->i_security;
u32 sid = current_sid();
int ret;
if (!mask)
/* No permission to check. Existence test. */
return 0;
ret = pft_file_permission(file, mask);
if (ret < 0)
return ret;
if (sid == fsec->sid && fsec->isid == isec->sid &&
fsec->pseqno == avc_policy_seqno())
/* No change since dentry_open check. */
@ -3294,6 +3338,11 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
struct file_security_struct *fsec;
struct inode *inode;
struct inode_security_struct *isec;
int ret;
ret = pft_file_open(file, cred);
if (ret < 0)
return ret;
inode = file->f_path.dentry->d_inode;
fsec = file->f_security;
@ -3318,6 +3367,16 @@ static int selinux_dentry_open(struct file *file, const struct cred *cred)
return inode_has_perm_noadp(cred, inode, open_file_to_av(file), 0);
}
static int selinux_file_close(struct file *file)
{
return pft_file_close(file);
}
static bool selinux_allow_merge_bio(struct bio *bio1, struct bio *bio2)
{
return pft_allow_merge_bio(bio1, bio2);
}
/* task security operations */
static int selinux_task_create(unsigned long clone_flags)
@ -5629,6 +5688,7 @@ static struct security_operations selinux_ops = {
.inode_free_security = selinux_inode_free_security,
.inode_init_security = selinux_inode_init_security,
.inode_create = selinux_inode_create,
.inode_post_create = selinux_inode_post_create,
.inode_link = selinux_inode_link,
.inode_unlink = selinux_inode_unlink,
.inode_symlink = selinux_inode_symlink,
@ -5664,6 +5724,8 @@ static struct security_operations selinux_ops = {
.file_receive = selinux_file_receive,
.dentry_open = selinux_dentry_open,
.file_close = selinux_file_close,
.allow_merge_bio = selinux_allow_merge_bio,
.task_create = selinux_task_create,
.cred_alloc_blank = selinux_cred_alloc_blank,