mirror of
https://github.com/S3NEO/android_kernel_samsung_msm8226.git
synced 2024-11-07 03:47:13 +00:00
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:
parent
854d305299
commit
6a22e4656b
6 changed files with 139 additions and 3 deletions
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
14
fs/namei.c
14
fs/namei.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in a new issue