diff options
Diffstat (limited to 'security/selinux/hooks.c')
-rw-r--r-- | security/selinux/hooks.c | 74 |
1 files changed, 47 insertions, 27 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 83a535b7bc60..221def6a0b1d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -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, |