CRED: Make inode_has_perm() and file_has_perm() take a cred pointer
authorDavid Howells <dhowells@redhat.com>
Thu, 13 Nov 2008 23:39:21 +0000 (10:39 +1100)
committerJames Morris <jmorris@namei.org>
Thu, 13 Nov 2008 23:39:21 +0000 (10:39 +1100)
Make inode_has_perm() and file_has_perm() take a cred pointer rather than a
task pointer.

Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: James Morris <jmorris@namei.org>
Acked-by: Serge Hallyn <serue@us.ibm.com>
Signed-off-by: James Morris <jmorris@namei.org>
security/selinux/hooks.c

index 3f3de565c24261e61f17dff2c72cc76a889f0407..cc6e5a3f10cca5e63d4324a09ed00afadfc20a84 100644 (file)
@@ -172,17 +172,26 @@ static int cred_alloc_security(struct cred *cred)
        return 0;
 }
 
+/*
+ * get the security ID of a set of credentials
+ */
+static inline u32 cred_sid(const struct cred *cred)
+{
+       const struct task_security_struct *tsec;
+
+       tsec = cred->security;
+       return tsec->sid;
+}
+
 /*
  * get the security ID of a task
  */
 static inline u32 task_sid(const struct task_struct *task)
 {
-       const struct task_security_struct *tsec;
        u32 sid;
 
        rcu_read_lock();
-       tsec = __task_cred(task)->security;
-       sid = tsec->sid;
+       sid = cred_sid(__task_cred(task));
        rcu_read_unlock();
        return sid;
 }
@@ -197,6 +206,8 @@ static inline u32 current_sid(void)
        return tsec->sid;
 }
 
+/* Allocate and free functions for each kind of security blob. */
+
 static int inode_alloc_security(struct inode *inode)
 {
        struct inode_security_struct *isec;
@@ -1368,7 +1379,7 @@ static inline u32 signal_to_av(int sig)
 }
 
 /*
- * Check permission betweeen a pair of tasks, e.g. signal checks,
+ * Check permission between a pair of tasks, e.g. signal checks,
  * fork check, ptrace check, etc.
  * tsk1 is the actor and tsk2 is the target
  */
@@ -1437,7 +1448,7 @@ static int task_has_system(struct task_struct *tsk,
 /* Check whether a task has a particular permission to an inode.
    The 'adp' parameter is optional and allows other audit
    data to be passed (e.g. the dentry). */
-static int inode_has_perm(struct task_struct *tsk,
+static int inode_has_perm(const struct cred *cred,
                          struct inode *inode,
                          u32 perms,
                          struct avc_audit_data *adp)
@@ -1449,7 +1460,7 @@ static int inode_has_perm(struct task_struct *tsk,
        if (unlikely(IS_PRIVATE(inode)))
                return 0;
 
-       sid = task_sid(tsk);
+       sid = cred_sid(cred);
        isec = inode->i_security;
 
        if (!adp) {
@@ -1464,17 +1475,18 @@ static int inode_has_perm(struct task_struct *tsk,
 /* Same as inode_has_perm, but pass explicit audit data containing
    the dentry to help the auditing code to more easily generate the
    pathname if needed. */
-static inline int dentry_has_perm(struct task_struct *tsk,
+static inline int dentry_has_perm(const struct cred *cred,
                                  struct vfsmount *mnt,
                                  struct dentry *dentry,
                                  u32 av)
 {
        struct inode *inode = dentry->d_inode;
        struct avc_audit_data ad;
+
        AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.mnt = mnt;
        ad.u.fs.path.dentry = dentry;
-       return inode_has_perm(tsk, inode, av, &ad);
+       return inode_has_perm(cred, inode, av, &ad);
 }
 
 /* Check whether a task can use an open file descriptor to
@@ -1485,14 +1497,14 @@ static inline int dentry_has_perm(struct task_struct *tsk,
    has the same SID as the process.  If av is zero, then
    access to the file is not checked, e.g. for cases
    where only the descriptor is affected like seek. */
-static int file_has_perm(struct task_struct *tsk,
-                               struct file *file,
-                               u32 av)
+static int file_has_perm(const struct cred *cred,
+                        struct file *file,
+                        u32 av)
 {
        struct file_security_struct *fsec = file->f_security;
        struct inode *inode = file->f_path.dentry->d_inode;
        struct avc_audit_data ad;
-       u32 sid = task_sid(tsk);
+       u32 sid = cred_sid(cred);
        int rc;
 
        AVC_AUDIT_DATA_INIT(&ad, FS);
@@ -1504,14 +1516,16 @@ static int file_has_perm(struct task_struct *tsk,
                                  FD__USE,
                                  &ad);
                if (rc)
-                       return rc;
+                       goto out;
        }
 
        /* av is zero if only checking access to the descriptor. */
+       rc = 0;
        if (av)
-               return inode_has_perm(tsk, inode, av, &ad);
+               rc = inode_has_perm(cred, inode, av, &ad);
 
-       return 0;
+out:
+       return rc;
 }
 
 /* Check whether a task can create a file. */
@@ -1670,13 +1684,13 @@ static inline int may_rename(struct inode *old_dir,
 }
 
 /* Check whether a task can perform a filesystem operation. */
-static int superblock_has_perm(struct task_struct *tsk,
+static int superblock_has_perm(const struct cred *cred,
                               struct super_block *sb,
                               u32 perms,
                               struct avc_audit_data *ad)
 {
        struct superblock_security_struct *sbsec;
-       u32 sid = task_sid(tsk);
+       u32 sid = cred_sid(cred);
 
        sbsec = sb->s_security;
        return avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM, perms, ad);
@@ -1919,6 +1933,7 @@ static int selinux_sysctl(ctl_table *table, int op)
 
 static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
 {
+       const struct cred *cred = current_cred();
        int rc = 0;
 
        if (!sb)
@@ -1930,14 +1945,12 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
        case Q_QUOTAOFF:
        case Q_SETINFO:
        case Q_SETQUOTA:
-               rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAMOD,
-                                        NULL);
+               rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAMOD, NULL);
                break;
        case Q_GETFMT:
        case Q_GETINFO:
        case Q_GETQUOTA:
-               rc = superblock_has_perm(current, sb, FILESYSTEM__QUOTAGET,
-                                        NULL);
+               rc = superblock_has_perm(cred, sb, FILESYSTEM__QUOTAGET, NULL);
                break;
        default:
                rc = 0;  /* let the kernel handle invalid cmds */
@@ -1948,7 +1961,9 @@ static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
 
 static int selinux_quota_on(struct dentry *dentry)
 {
-       return dentry_has_perm(current, NULL, dentry, FILE__QUOTAON);
+       const struct cred *cred = current_cred();
+
+       return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
 }
 
 static int selinux_syslog(int type)
@@ -2137,6 +2152,7 @@ extern struct dentry *selinux_null;
 /* Derived from fs/exec.c:flush_old_files. */
 static inline void flush_unauthorized_files(struct files_struct *files)
 {
+       const struct cred *cred = current_cred();
        struct avc_audit_data ad;
        struct file *file, *devnull = NULL;
        struct tty_struct *tty;
@@ -2157,7 +2173,7 @@ static inline void flush_unauthorized_files(struct files_struct *files)
                           interested in the inode-based check here. */
                        file = list_first_entry(&tty->tty_files, struct file, f_u.fu_list);
                        inode = file->f_path.dentry->d_inode;
-                       if (inode_has_perm(current, inode,
+                       if (inode_has_perm(cred, inode,
                                           FILE__READ | FILE__WRITE, NULL)) {
                                drop_tty = 1;
                        }
@@ -2192,7 +2208,7 @@ static inline void flush_unauthorized_files(struct files_struct *files)
                                file = fget(i);
                                if (!file)
                                        continue;
-                               if (file_has_perm(current,
+                               if (file_has_perm(cred,
                                                  file,
                                                  file_to_av(file))) {
                                        sys_close(i);
@@ -2465,6 +2481,7 @@ out:
 
 static int selinux_sb_kern_mount(struct super_block *sb, void *data)
 {
+       const struct cred *cred = current_cred();
        struct avc_audit_data ad;
        int rc;
 
@@ -2474,16 +2491,17 @@ static int selinux_sb_kern_mount(struct super_block *sb, void *data)
 
        AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.dentry = sb->s_root;
-       return superblock_has_perm(current, sb, FILESYSTEM__MOUNT, &ad);
+       return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
 }
 
 static int selinux_sb_statfs(struct dentry *dentry)
 {
+       const struct cred *cred = current_cred();
        struct avc_audit_data ad;
 
        AVC_AUDIT_DATA_INIT(&ad, FS);
        ad.u.fs.path.dentry = dentry->d_sb->s_root;
-       return superblock_has_perm(current, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
+       return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
 static int selinux_mount(char *dev_name,
@@ -2492,6 +2510,7 @@ static int selinux_mount(char *dev_name,
                         unsigned long flags,
                         void *data)
 {
+       const struct cred *cred = current_cred();
        int rc;
 
        rc = secondary_ops->sb_mount(dev_name, path, type, flags, data);
@@ -2499,22 +2518,23 @@ static int selinux_mount(char *dev_name,
                return rc;
 
        if (flags & MS_REMOUNT)
-               return superblock_has_perm(current, path->mnt->mnt_sb,
+               return superblock_has_perm(cred, path->mnt->mnt_sb,
                                           FILESYSTEM__REMOUNT, NULL);
        else
-               return dentry_has_perm(current, path->mnt, path->dentry,
+               return dentry_has_perm(cred, path->mnt, path->dentry,
                                       FILE__MOUNTON);
 }
 
 static int selinux_umount(struct vfsmount *mnt, int flags)
 {
+       const struct cred *cred = current_cred();
        int rc;
 
        rc = secondary_ops->sb_umount(mnt, flags);
        if (rc)
                return rc;
 
-       return superblock_has_perm(current, mnt->mnt_sb,
+       return superblock_has_perm(cred, mnt->mnt_sb,
                                   FILESYSTEM__UNMOUNT, NULL);
 }
 
@@ -2652,21 +2672,25 @@ static int selinux_inode_rename(struct inode *old_inode, struct dentry *old_dent
 
 static int selinux_inode_readlink(struct dentry *dentry)
 {
-       return dentry_has_perm(current, NULL, dentry, FILE__READ);
+       const struct cred *cred = current_cred();
+
+       return dentry_has_perm(cred, NULL, dentry, FILE__READ);
 }
 
 static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
 {
+       const struct cred *cred = current_cred();
        int rc;
 
        rc = secondary_ops->inode_follow_link(dentry, nameidata);
        if (rc)
                return rc;
-       return dentry_has_perm(current, NULL, dentry, FILE__READ);
+       return dentry_has_perm(cred, NULL, dentry, FILE__READ);
 }
 
 static int selinux_inode_permission(struct inode *inode, int mask)
 {
+       const struct cred *cred = current_cred();
        int rc;
 
        rc = secondary_ops->inode_permission(inode, mask);
@@ -2678,12 +2702,13 @@ static int selinux_inode_permission(struct inode *inode, int mask)
                return 0;
        }
 
-       return inode_has_perm(current, inode,
+       return inode_has_perm(cred, inode,
                              file_mask_to_av(inode->i_mode, mask), NULL);
 }
 
 static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 {
+       const struct cred *cred = current_cred();
        int rc;
 
        rc = secondary_ops->inode_setattr(dentry, iattr);
@@ -2695,18 +2720,22 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 
        if (iattr->ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
                               ATTR_ATIME_SET | ATTR_MTIME_SET))
-               return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+               return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
 
-       return dentry_has_perm(current, NULL, dentry, FILE__WRITE);
+       return dentry_has_perm(cred, NULL, dentry, FILE__WRITE);
 }
 
 static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 {
-       return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
+       const struct cred *cred = current_cred();
+
+       return dentry_has_perm(cred, mnt, dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
 {
+       const struct cred *cred = current_cred();
+
        if (!strncmp(name, XATTR_SECURITY_PREFIX,
                     sizeof XATTR_SECURITY_PREFIX - 1)) {
                if (!strcmp(name, XATTR_NAME_CAPS)) {
@@ -2721,7 +2750,7 @@ static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
 
        /* Not an attribute we recognize, so just check the
           ordinary setattr permission. */
-       return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+       return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
 }
 
 static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
@@ -2806,12 +2835,16 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
 
 static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
 {
-       return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+       const struct cred *cred = current_cred();
+
+       return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_listxattr(struct dentry *dentry)
 {
-       return dentry_has_perm(current, NULL, dentry, FILE__GETATTR);
+       const struct cred *cred = current_cred();
+
+       return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
@@ -2915,6 +2948,7 @@ static void selinux_inode_getsecid(const struct inode *inode, u32 *secid)
 
 static int selinux_revalidate_file_permission(struct file *file, int mask)
 {
+       const struct cred *cred = current_cred();
        int rc;
        struct inode *inode = file->f_path.dentry->d_inode;
 
@@ -2927,7 +2961,7 @@ static int selinux_revalidate_file_permission(struct file *file, int mask)
        if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE))
                mask |= MAY_APPEND;
 
-       rc = file_has_perm(current, file,
+       rc = file_has_perm(cred, file,
                           file_mask_to_av(inode->i_mode, mask));
        if (rc)
                return rc;
@@ -2967,6 +3001,7 @@ static void selinux_file_free_security(struct file *file)
 static int selinux_file_ioctl(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
+       const struct cred *cred = current_cred();
        u32 av = 0;
 
        if (_IOC_DIR(cmd) & _IOC_WRITE)
@@ -2976,11 +3011,13 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
        if (!av)
                av = FILE__IOCTL;
 
-       return file_has_perm(current, file, av);
+       return file_has_perm(cred, file, av);
 }
 
 static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
 {
+       const struct cred *cred = current_cred();
+
 #ifndef CONFIG_PPC32
        if ((prot & PROT_EXEC) && (!file || (!shared && (prot & PROT_WRITE)))) {
                /*
@@ -3005,7 +3042,7 @@ static int file_map_prot_check(struct file *file, unsigned long prot, int shared
                if (prot & PROT_EXEC)
                        av |= FILE__EXECUTE;
 
-               return file_has_perm(current, file, av);
+               return file_has_perm(cred, file, av);
        }
        return 0;
 }
@@ -3034,6 +3071,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
                                 unsigned long reqprot,
                                 unsigned long prot)
 {
+       const struct cred *cred = current_cred();
        int rc;
 
        rc = secondary_ops->file_mprotect(vma, reqprot, prot);
@@ -3062,7 +3100,7 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
                         * modified content.  This typically should only
                         * occur for text relocations.
                         */
-                       rc = file_has_perm(current, vma->vm_file,
+                       rc = file_has_perm(cred, vma->vm_file,
                                           FILE__EXECMOD);
                }
                if (rc)
@@ -3075,12 +3113,15 @@ static int selinux_file_mprotect(struct vm_area_struct *vma,
 
 static int selinux_file_lock(struct file *file, unsigned int cmd)
 {
-       return file_has_perm(current, file, FILE__LOCK);
+       const struct cred *cred = current_cred();
+
+       return file_has_perm(cred, file, FILE__LOCK);
 }
 
 static int selinux_file_fcntl(struct file *file, unsigned int cmd,
                              unsigned long arg)
 {
+       const struct cred *cred = current_cred();
        int err = 0;
 
        switch (cmd) {
@@ -3091,7 +3132,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
                }
 
                if ((file->f_flags & O_APPEND) && !(arg & O_APPEND)) {
-                       err = file_has_perm(current, file, FILE__WRITE);
+                       err = file_has_perm(cred, file, FILE__WRITE);
                        break;
                }
                /* fall through */
@@ -3101,7 +3142,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
        case F_GETOWN:
        case F_GETSIG:
                /* Just check FD__USE permission */
-               err = file_has_perm(current, file, 0);
+               err = file_has_perm(cred, file, 0);
                break;
        case F_GETLK:
        case F_SETLK:
@@ -3115,7 +3156,7 @@ static int selinux_file_fcntl(struct file *file, unsigned int cmd,
                        err = -EINVAL;
                        break;
                }
-               err = file_has_perm(current, file, FILE__LOCK);
+               err = file_has_perm(cred, file, FILE__LOCK);
                break;
        }
 
@@ -3156,11 +3197,14 @@ static int selinux_file_send_sigiotask(struct task_struct *tsk,
 
 static int selinux_file_receive(struct file *file)
 {
-       return file_has_perm(current, file, file_to_av(file));
+       const struct cred *cred = current_cred();
+
+       return file_has_perm(cred, file, file_to_av(file));
 }
 
 static int selinux_dentry_open(struct file *file)
 {
+       const struct cred *cred = current_cred();
        struct file_security_struct *fsec;
        struct inode *inode;
        struct inode_security_struct *isec;
@@ -3184,7 +3228,7 @@ static int selinux_dentry_open(struct file *file)
         * new inode label or new policy.
         * This check is not redundant - do not remove.
         */
-       return inode_has_perm(current, inode, open_file_to_av(file), NULL);
+       return inode_has_perm(cred, inode, open_file_to_av(file), NULL);
 }
 
 /* task security operations */