Merge commit 'v2.6.39' into 20110526
[linux-2.6.git] / security / selinux / hooks.c
index 8fb2488..a0d3845 100644 (file)
@@ -990,6 +990,7 @@ static void selinux_write_opts(struct seq_file *m,
                        continue;
                default:
                        BUG();
+                       return;
                };
                /* we need a comma before each option */
                seq_putc(m, ',');
@@ -1443,6 +1444,7 @@ static int task_has_capability(struct task_struct *tsk,
                printk(KERN_ERR
                       "SELinux:  out of range capability %d\n", cap);
                BUG();
+               return -EINVAL;
        }
 
        rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd);
@@ -1487,8 +1489,8 @@ static int inode_has_perm(const struct cred *cred,
 
        if (!adp) {
                adp = &ad;
-               COMMON_AUDIT_DATA_INIT(&ad, FS);
-               ad.u.fs.inode = inode;
+               COMMON_AUDIT_DATA_INIT(&ad, INODE);
+               ad.u.inode = inode;
        }
 
        return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags);
@@ -1498,16 +1500,29 @@ static int inode_has_perm(const struct cred *cred,
    the dentry to help the auditing code to more easily generate the
    pathname if needed. */
 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 common_audit_data ad;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path.mnt = mnt;
-       ad.u.fs.path.dentry = dentry;
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.u.dentry = dentry;
+       return inode_has_perm(cred, inode, av, &ad, 0);
+}
+
+/* Same as inode_has_perm, but pass explicit audit data containing
+   the path to help the auditing code to more easily generate the
+   pathname if needed. */
+static inline int path_has_perm(const struct cred *cred,
+                               struct path *path,
+                               u32 av)
+{
+       struct inode *inode = path->dentry->d_inode;
+       struct common_audit_data ad;
+
+       COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.u.path = *path;
        return inode_has_perm(cred, inode, av, &ad, 0);
 }
 
@@ -1529,8 +1544,8 @@ static int file_has_perm(const struct cred *cred,
        u32 sid = cred_sid(cred);
        int rc;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path = file->f_path;
+       COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.u.path = file->f_path;
 
        if (sid != fsec->sid) {
                rc = avc_has_perm(sid, fsec->sid,
@@ -1568,8 +1583,8 @@ static int may_create(struct inode *dir,
        sid = tsec->sid;
        newsid = tsec->create_sid;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path.dentry = dentry;
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.u.dentry = dentry;
 
        rc = avc_has_perm(sid, dsec->sid, SECCLASS_DIR,
                          DIR__ADD_NAME | DIR__SEARCH,
@@ -1621,8 +1636,8 @@ static int may_link(struct inode *dir,
        dsec = dir->i_security;
        isec = dentry->d_inode->i_security;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path.dentry = dentry;
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.u.dentry = dentry;
 
        av = DIR__SEARCH;
        av |= (kind ? DIR__REMOVE_NAME : DIR__ADD_NAME);
@@ -1667,9 +1682,9 @@ static inline int may_rename(struct inode *old_dir,
        old_is_dir = S_ISDIR(old_dentry->d_inode->i_mode);
        new_dsec = new_dir->i_security;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
 
-       ad.u.fs.path.dentry = old_dentry;
+       ad.u.dentry = old_dentry;
        rc = avc_has_perm(sid, old_dsec->sid, SECCLASS_DIR,
                          DIR__REMOVE_NAME | DIR__SEARCH, &ad);
        if (rc)
@@ -1685,7 +1700,7 @@ static inline int may_rename(struct inode *old_dir,
                        return rc;
        }
 
-       ad.u.fs.path.dentry = new_dentry;
+       ad.u.dentry = new_dentry;
        av = DIR__ADD_NAME | DIR__SEARCH;
        if (new_dentry->d_inode)
                av |= DIR__REMOVE_NAME;
@@ -1895,7 +1910,7 @@ static int selinux_quota_on(struct dentry *dentry)
 {
        const struct cred *cred = current_cred();
 
-       return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON);
+       return dentry_has_perm(cred, dentry, FILE__QUOTAON);
 }
 
 static int selinux_syslog(int type)
@@ -1992,8 +2007,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
                        return rc;
        }
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path = bprm->file->f_path;
+       COMMON_AUDIT_DATA_INIT(&ad, PATH);
+       ad.u.path = bprm->file->f_path;
 
        if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
                new_tsec->sid = old_tsec->sid;
@@ -2121,7 +2136,7 @@ static inline void flush_unauthorized_files(const struct cred *cred,
 
        /* Revalidate access to inherited open files. */
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
+       COMMON_AUDIT_DATA_INIT(&ad, INODE);
 
        spin_lock(&files->file_lock);
        for (;;) {
@@ -2469,8 +2484,8 @@ static int selinux_sb_kern_mount(struct super_block *sb, int flags, void *data)
        if (flags & MS_KERNMOUNT)
                return 0;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path.dentry = sb->s_root;
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.u.dentry = sb->s_root;
        return superblock_has_perm(cred, sb, FILESYSTEM__MOUNT, &ad);
 }
 
@@ -2479,8 +2494,8 @@ static int selinux_sb_statfs(struct dentry *dentry)
        const struct cred *cred = current_cred();
        struct common_audit_data ad;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path.dentry = dentry->d_sb->s_root;
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.u.dentry = dentry->d_sb->s_root;
        return superblock_has_perm(cred, dentry->d_sb, FILESYSTEM__GETATTR, &ad);
 }
 
@@ -2496,8 +2511,7 @@ static int selinux_mount(char *dev_name,
                return superblock_has_perm(cred, path->mnt->mnt_sb,
                                           FILESYSTEM__REMOUNT, NULL);
        else
-               return dentry_has_perm(cred, path->mnt, path->dentry,
-                                      FILE__MOUNTON);
+               return path_has_perm(cred, path, FILE__MOUNTON);
 }
 
 static int selinux_umount(struct vfsmount *mnt, int flags)
@@ -2630,14 +2644,14 @@ static int selinux_inode_readlink(struct dentry *dentry)
 {
        const struct cred *cred = current_cred();
 
-       return dentry_has_perm(cred, NULL, dentry, FILE__READ);
+       return dentry_has_perm(cred, dentry, FILE__READ);
 }
 
 static int selinux_inode_follow_link(struct dentry *dentry, struct nameidata *nameidata)
 {
        const struct cred *cred = current_cred();
 
-       return dentry_has_perm(cred, NULL, dentry, FILE__READ);
+       return dentry_has_perm(cred, dentry, FILE__READ);
 }
 
 static int selinux_inode_permission(struct inode *inode, int mask, unsigned flags)
@@ -2654,8 +2668,8 @@ static int selinux_inode_permission(struct inode *inode, int mask, unsigned flag
        if (!mask)
                return 0;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.inode = inode;
+       COMMON_AUDIT_DATA_INIT(&ad, INODE);
+       ad.u.inode = inode;
 
        if (from_access)
                ad.selinux_audit_data.auditdeny |= FILE__AUDIT_ACCESS;
@@ -2680,16 +2694,20 @@ static int selinux_inode_setattr(struct dentry *dentry, struct iattr *iattr)
 
        if (ia_valid & (ATTR_MODE | ATTR_UID | ATTR_GID |
                        ATTR_ATIME_SET | ATTR_MTIME_SET | ATTR_TIMES_SET))
-               return dentry_has_perm(cred, NULL, dentry, FILE__SETATTR);
+               return dentry_has_perm(cred, dentry, FILE__SETATTR);
 
-       return dentry_has_perm(cred, NULL, dentry, FILE__WRITE);
+       return dentry_has_perm(cred, dentry, FILE__WRITE);
 }
 
 static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
 {
        const struct cred *cred = current_cred();
+       struct path path;
+
+       path.dentry = dentry;
+       path.mnt = mnt;
 
-       return dentry_has_perm(cred, mnt, dentry, FILE__GETATTR);
+       return path_has_perm(cred, &path, FILE__GETATTR);
 }
 
 static int selinux_inode_setotherxattr(struct dentry *dentry, const char *name)
@@ -2710,7 +2728,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(cred, NULL, dentry, FILE__SETATTR);
+       return dentry_has_perm(cred, dentry, FILE__SETATTR);
 }
 
 static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
@@ -2733,8 +2751,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
        if (!inode_owner_or_capable(inode))
                return -EPERM;
 
-       COMMON_AUDIT_DATA_INIT(&ad, FS);
-       ad.u.fs.path.dentry = dentry;
+       COMMON_AUDIT_DATA_INIT(&ad, DENTRY);
+       ad.u.dentry = dentry;
 
        rc = avc_has_perm(sid, isec->sid, isec->sclass,
                          FILE__RELABELFROM, &ad);
@@ -2797,14 +2815,14 @@ static int selinux_inode_getxattr(struct dentry *dentry, const char *name)
 {
        const struct cred *cred = current_cred();
 
-       return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
+       return dentry_has_perm(cred, dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_listxattr(struct dentry *dentry)
 {
        const struct cred *cred = current_cred();
 
-       return dentry_has_perm(cred, NULL, dentry, FILE__GETATTR);
+       return dentry_has_perm(cred, dentry, FILE__GETATTR);
 }
 
 static int selinux_inode_removexattr(struct dentry *dentry, const char *name)