]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
selinux: Create a common helper to determine an inode label [ver #3]
authorDavid Howells <dhowells@redhat.com>
Fri, 10 Jul 2015 21:19:58 +0000 (17:19 -0400)
committerPaul Moore <pmoore@redhat.com>
Mon, 13 Jul 2015 17:31:59 +0000 (13:31 -0400)
Create a common helper function to determine the label for a new inode.
This is then used by:

- may_create()
- selinux_dentry_init_security()
- selinux_inode_init_security()

This will change the behaviour of the functions slightly, bringing them
all into line.

Suggested-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <pmoore@redhat.com>
security/selinux/hooks.c

index ef310f82717d77d42c40170d28ccc439f5b65f20..f4be0a1107881185976142656fc3265ad0d1519c 100644 (file)
@@ -1709,6 +1709,32 @@ out:
        return rc;
 }
 
+/*
+ * Determine the label for an inode that might be unioned.
+ */
+static int selinux_determine_inode_label(const struct inode *dir,
+                                        const struct qstr *name,
+                                        u16 tclass,
+                                        u32 *_new_isid)
+{
+       const struct superblock_security_struct *sbsec = dir->i_sb->s_security;
+       const struct inode_security_struct *dsec = dir->i_security;
+       const struct task_security_struct *tsec = current_security();
+
+       if ((sbsec->flags & SE_SBINITIALIZED) &&
+           (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)) {
+               *_new_isid = sbsec->mntpoint_sid;
+       } else if ((sbsec->flags & SBLABEL_MNT) &&
+                  tsec->create_sid) {
+               *_new_isid = tsec->create_sid;
+       } else {
+               return security_transition_sid(tsec->sid, dsec->sid, tclass,
+                                              name, _new_isid);
+       }
+
+       return 0;
+}
+
 /* Check whether a task can create a file. */
 static int may_create(struct inode *dir,
                      struct dentry *dentry,
@@ -1725,7 +1751,6 @@ static int may_create(struct inode *dir,
        sbsec = dir->i_sb->s_security;
 
        sid = tsec->sid;
-       newsid = tsec->create_sid;
 
        ad.type = LSM_AUDIT_DATA_DENTRY;
        ad.u.dentry = dentry;
@@ -1736,12 +1761,10 @@ static int may_create(struct inode *dir,
        if (rc)
                return rc;
 
-       if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
-               rc = security_transition_sid(sid, dsec->sid, tclass,
-                                            &dentry->d_name, &newsid);
-               if (rc)
-                       return rc;
-       }
+       rc = selinux_determine_inode_label(dir, &dentry->d_name, tclass,
+                                          &newsid);
+       if (rc)
+               return rc;
 
        rc = avc_has_perm(sid, newsid, tclass, FILE__CREATE, &ad);
        if (rc)
@@ -2715,32 +2738,14 @@ static int selinux_dentry_init_security(struct dentry *dentry, int mode,
                                        struct qstr *name, void **ctx,
                                        u32 *ctxlen)
 {
-       const struct cred *cred = current_cred();
-       struct task_security_struct *tsec;
-       struct inode_security_struct *dsec;
-       struct superblock_security_struct *sbsec;
-       struct inode *dir = d_backing_inode(dentry->d_parent);
        u32 newsid;
        int rc;
 
-       tsec = cred->security;
-       dsec = dir->i_security;
-       sbsec = dir->i_sb->s_security;
-
-       if (tsec->create_sid && sbsec->behavior != SECURITY_FS_USE_MNTPOINT) {
-               newsid = tsec->create_sid;
-       } else {
-               rc = security_transition_sid(tsec->sid, dsec->sid,
-                                            inode_mode_to_security_class(mode),
-                                            name,
-                                            &newsid);
-               if (rc) {
-                       printk(KERN_WARNING
-                               "%s: security_transition_sid failed, rc=%d\n",
-                              __func__, -rc);
-                       return rc;
-               }
-       }
+       rc = selinux_determine_inode_label(d_inode(dentry->d_parent), name,
+                                          inode_mode_to_security_class(mode),
+                                          &newsid);
+       if (rc)
+               return rc;
 
        return security_sid_to_context(newsid, (char **)ctx, ctxlen);
 }
@@ -2763,22 +2768,12 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
        sid = tsec->sid;
        newsid = tsec->create_sid;
 
-       if ((sbsec->flags & SE_SBINITIALIZED) &&
-           (sbsec->behavior == SECURITY_FS_USE_MNTPOINT))
-               newsid = sbsec->mntpoint_sid;
-       else if (!newsid || !(sbsec->flags & SBLABEL_MNT)) {
-               rc = security_transition_sid(sid, dsec->sid,
-                                            inode_mode_to_security_class(inode->i_mode),
-                                            qstr, &newsid);
-               if (rc) {
-                       printk(KERN_WARNING "%s:  "
-                              "security_transition_sid failed, rc=%d (dev=%s "
-                              "ino=%ld)\n",
-                              __func__,
-                              -rc, inode->i_sb->s_id, inode->i_ino);
-                       return rc;
-               }
-       }
+       rc = selinux_determine_inode_label(
+               dir, qstr,
+               inode_mode_to_security_class(inode->i_mode),
+               &newsid);
+       if (rc)
+               return rc;
 
        /* Possibly defer initialization to selinux_complete_init. */
        if (sbsec->flags & SE_SBINITIALIZED) {