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>
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c868a74..50b003a 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -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 @@
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 @@
}
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_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_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 @@
{
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 @@
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 @@
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 @@
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 @@
.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 @@
.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,