]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - security/selinux/hooks.c
SELinux: Use d_is_positive() rather than testing dentry->d_inode
[karo-tx-linux.git] / security / selinux / hooks.c
index 6da7532893a1973e660f5eabf525d5769c655fef..79f2c2cb68ad637d1db6c1cbc3a56ea93943cde2 100644 (file)
@@ -401,23 +401,14 @@ static int selinux_is_sblabel_mnt(struct super_block *sb)
 {
        struct superblock_security_struct *sbsec = sb->s_security;
 
-       if (sbsec->behavior == SECURITY_FS_USE_XATTR ||
-           sbsec->behavior == SECURITY_FS_USE_TRANS ||
-           sbsec->behavior == SECURITY_FS_USE_TASK)
-               return 1;
-
-       /* Special handling for sysfs. Is genfs but also has setxattr handler*/
-       if (strncmp(sb->s_type->name, "sysfs", sizeof("sysfs")) == 0)
-               return 1;
-
-       /*
-        * Special handling for rootfs. Is genfs but supports
-        * setting SELinux context on in-core inodes.
-        */
-       if (strncmp(sb->s_type->name, "rootfs", sizeof("rootfs")) == 0)
-               return 1;
-
-       return 0;
+       return sbsec->behavior == SECURITY_FS_USE_XATTR ||
+               sbsec->behavior == SECURITY_FS_USE_TRANS ||
+               sbsec->behavior == SECURITY_FS_USE_TASK ||
+               /* Special handling. Genfs but also in-core setxattr handler */
+               !strcmp(sb->s_type->name, "sysfs") ||
+               !strcmp(sb->s_type->name, "pstore") ||
+               !strcmp(sb->s_type->name, "debugfs") ||
+               !strcmp(sb->s_type->name, "rootfs");
 }
 
 static int sb_finish_set_opts(struct super_block *sb)
@@ -456,10 +447,6 @@ static int sb_finish_set_opts(struct super_block *sb)
        if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors))
                printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n",
                       sb->s_id, sb->s_type->name);
-       else
-               printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n",
-                      sb->s_id, sb->s_type->name,
-                      labeling_behaviors[sbsec->behavior-1]);
 
        sbsec->flags |= SE_SBINITIALIZED;
        if (selinux_is_sblabel_mnt(sb))
@@ -1835,12 +1822,12 @@ static inline int may_rename(struct inode *old_dir,
 
        ad.u.dentry = new_dentry;
        av = DIR__ADD_NAME | DIR__SEARCH;
-       if (new_dentry->d_inode)
+       if (d_is_positive(new_dentry))
                av |= DIR__REMOVE_NAME;
        rc = avc_has_perm(sid, new_dsec->sid, SECCLASS_DIR, av, &ad);
        if (rc)
                return rc;
-       if (new_dentry->d_inode) {
+       if (d_is_positive(new_dentry)) {
                new_isec = new_dentry->d_inode->i_security;
                new_is_dir = S_ISDIR(new_dentry->d_inode->i_mode);
                rc = avc_has_perm(sid, new_isec->sid,
@@ -1933,6 +1920,74 @@ static inline u32 open_file_to_av(struct file *file)
 
 /* Hook functions begin here. */
 
+static int selinux_binder_set_context_mgr(struct task_struct *mgr)
+{
+       u32 mysid = current_sid();
+       u32 mgrsid = task_sid(mgr);
+
+       return avc_has_perm(mysid, mgrsid, SECCLASS_BINDER,
+                           BINDER__SET_CONTEXT_MGR, NULL);
+}
+
+static int selinux_binder_transaction(struct task_struct *from,
+                                     struct task_struct *to)
+{
+       u32 mysid = current_sid();
+       u32 fromsid = task_sid(from);
+       u32 tosid = task_sid(to);
+       int rc;
+
+       if (mysid != fromsid) {
+               rc = avc_has_perm(mysid, fromsid, SECCLASS_BINDER,
+                                 BINDER__IMPERSONATE, NULL);
+               if (rc)
+                       return rc;
+       }
+
+       return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__CALL,
+                           NULL);
+}
+
+static int selinux_binder_transfer_binder(struct task_struct *from,
+                                         struct task_struct *to)
+{
+       u32 fromsid = task_sid(from);
+       u32 tosid = task_sid(to);
+
+       return avc_has_perm(fromsid, tosid, SECCLASS_BINDER, BINDER__TRANSFER,
+                           NULL);
+}
+
+static int selinux_binder_transfer_file(struct task_struct *from,
+                                       struct task_struct *to,
+                                       struct file *file)
+{
+       u32 sid = task_sid(to);
+       struct file_security_struct *fsec = file->f_security;
+       struct inode *inode = file->f_path.dentry->d_inode;
+       struct inode_security_struct *isec = inode->i_security;
+       struct common_audit_data ad;
+       int rc;
+
+       ad.type = LSM_AUDIT_DATA_PATH;
+       ad.u.path = file->f_path;
+
+       if (sid != fsec->sid) {
+               rc = avc_has_perm(sid, fsec->sid,
+                                 SECCLASS_FD,
+                                 FD__USE,
+                                 &ad);
+               if (rc)
+                       return rc;
+       }
+
+       if (unlikely(IS_PRIVATE(inode)))
+               return 0;
+
+       return avc_has_perm(sid, isec->sid, isec->sclass, file_to_av(file),
+                           &ad);
+}
+
 static int selinux_ptrace_access_check(struct task_struct *child,
                                     unsigned int mode)
 {
@@ -5810,6 +5865,11 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
 static struct security_operations selinux_ops = {
        .name =                         "selinux",
 
+       .binder_set_context_mgr =       selinux_binder_set_context_mgr,
+       .binder_transaction =           selinux_binder_transaction,
+       .binder_transfer_binder =       selinux_binder_transfer_binder,
+       .binder_transfer_file =         selinux_binder_transfer_file,
+
        .ptrace_access_check =          selinux_ptrace_access_check,
        .ptrace_traceme =               selinux_ptrace_traceme,
        .capget =                       selinux_capget,