Implement file posix capabilities
[safe/jmp/linux-2.6] / security / selinux / hooks.c
index 97b7e27..221def6 100644 (file)
@@ -22,7 +22,6 @@
  *      as published by the Free Software Foundation.
  */
 
-#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
@@ -86,6 +85,7 @@
 extern unsigned int policydb_loaded_version;
 extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm);
 extern int selinux_compat_net;
+extern struct security_operations *security_ops;
 
 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
 int selinux_enforcing = 0;
@@ -2297,6 +2297,25 @@ static int selinux_inode_getattr(struct vfsmount *mnt, struct dentry *dentry)
        return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
 }
 
+static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
+{
+       if (!strncmp(name, XATTR_SECURITY_PREFIX,
+                    sizeof XATTR_SECURITY_PREFIX - 1)) {
+               if (!strcmp(name, XATTR_NAME_CAPS)) {
+                       if (!capable(CAP_SETFCAP))
+                               return -EPERM;
+               } else if (!capable(CAP_SYS_ADMIN)) {
+                       /* A different attribute in the security namespace.
+                          Restrict to administrator. */
+                       return -EPERM;
+               }
+       }
+
+       /* Not an attribute we recognize, so just check the
+          ordinary setattr permission. */
+       return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
+}
+
 static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
 {
        struct task_security_struct *tsec = current->security;
@@ -2307,19 +2326,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
        u32 newsid;
        int rc = 0;
 
-       if (strcmp(name, XATTR_NAME_SELINUX)) {
-               if (!strncmp(name, XATTR_SECURITY_PREFIX,
-                            sizeof XATTR_SECURITY_PREFIX - 1) &&
-                   !capable(CAP_SYS_ADMIN)) {
-                       /* A different attribute in the security namespace.
-                          Restrict to administrator. */
-                       return -EPERM;
-               }
-
-               /* Not an attribute we recognize, so just check the
-                  ordinary setattr permission. */
-               return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
-       }
+       if (strcmp(name, XATTR_NAME_SELINUX))
+               return selinux_inode_setotherxattr(dentry, name);
 
        sbsec = inode->i_sb->s_security;
        if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
@@ -2393,20 +2401,8 @@ static int selinux_inode_listxattr (struct dentry *dentry)
 
 static int selinux_inode_removexattr (struct dentry *dentry, char *name)
 {
-       if (strcmp(name, XATTR_NAME_SELINUX)) {
-               if (!strncmp(name, XATTR_SECURITY_PREFIX,
-                            sizeof XATTR_SECURITY_PREFIX - 1) &&
-                   !capable(CAP_SYS_ADMIN)) {
-                       /* A different attribute in the security namespace.
-                          Restrict to administrator. */
-                       return -EPERM;
-               }
-
-               /* Not an attribute we recognize, so just check the
-                  ordinary setattr permission. Might want a separate
-                  permission for removexattr. */
-               return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
-       }
+       if (strcmp(name, XATTR_NAME_SELINUX))
+               return selinux_inode_setotherxattr(dentry, name);
 
        /* No one is allowed to remove a SELinux security label.
           You can change the label, but all data must be labeled. */
@@ -2464,6 +2460,16 @@ static int selinux_inode_listsecurity(struct inode *inode, char *buffer, size_t
        return len;
 }
 
+static int selinux_inode_need_killpriv(struct dentry *dentry)
+{
+       return secondary_ops->inode_need_killpriv(dentry);
+}
+
+static int selinux_inode_killpriv(struct dentry *dentry)
+{
+       return secondary_ops->inode_killpriv(dentry);
+}
+
 /* file security operations */
 
 static int selinux_revalidate_file_permission(struct file *file, int mask)
@@ -2882,6 +2888,12 @@ static int selinux_task_setnice(struct task_struct *p, int nice)
 
 static int selinux_task_setioprio(struct task_struct *p, int ioprio)
 {
+       int rc;
+
+       rc = secondary_ops->task_setioprio(p, ioprio);
+       if (rc)
+               return rc;
+
        return task_has_perm(current, p, PROCESS__SETSCHED);
 }
 
@@ -2911,6 +2923,12 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim
 
 static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
 {
+       int rc;
+
+       rc = secondary_ops->task_setscheduler(p, policy, lp);
+       if (rc)
+               return rc;
+
        return task_has_perm(current, p, PROCESS__SETSCHED);
 }
 
@@ -4830,6 +4848,8 @@ static struct security_operations selinux_ops = {
        .inode_getsecurity =            selinux_inode_getsecurity,
        .inode_setsecurity =            selinux_inode_setsecurity,
        .inode_listsecurity =           selinux_inode_listsecurity,
+       .inode_need_killpriv =          selinux_inode_need_killpriv,
+       .inode_killpriv =               selinux_inode_killpriv,
 
        .file_permission =              selinux_file_permission,
        .file_alloc_security =          selinux_file_alloc_security,