aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerge E. Hallyn2007-10-17 01:31:36 -0500
committerLinus Torvalds2007-10-17 10:43:07 -0500
commitb53767719b6cd8789392ea3e7e2eb7b8906898f0 (patch)
treea0279dc93c79b94d3865b0f19f6b7b353e20608c
parent57c521ce6125e15e99e56c902cb8da96bee7b36d (diff)
downloadam43-linux-kernel-b53767719b6cd8789392ea3e7e2eb7b8906898f0.tar.gz
am43-linux-kernel-b53767719b6cd8789392ea3e7e2eb7b8906898f0.tar.xz
am43-linux-kernel-b53767719b6cd8789392ea3e7e2eb7b8906898f0.zip
Implement file posix capabilities
Implement file posix capabilities. This allows programs to be given a subset of root's powers regardless of who runs them, without having to use setuid and giving the binary all of root's powers. This version works with Kaigai Kohei's userspace tools, found at http://www.kaigai.gr.jp/index.php. For more information on how to use this patch, Chris Friedhoff has posted a nice page at http://www.friedhoff.org/fscaps.html. Changelog: Nov 27: Incorporate fixes from Andrew Morton (security-introduce-file-caps-tweaks and security-introduce-file-caps-warning-fix) Fix Kconfig dependency. Fix change signaling behavior when file caps are not compiled in. Nov 13: Integrate comments from Alexey: Remove CONFIG_ ifdef from capability.h, and use %zd for printing a size_t. Nov 13: Fix endianness warnings by sparse as suggested by Alexey Dobriyan. Nov 09: Address warnings of unused variables at cap_bprm_set_security when file capabilities are disabled, and simultaneously clean up the code a little, by pulling the new code into a helper function. Nov 08: For pointers to required userspace tools and how to use them, see http://www.friedhoff.org/fscaps.html. Nov 07: Fix the calculation of the highest bit checked in check_cap_sanity(). Nov 07: Allow file caps to be enabled without CONFIG_SECURITY, since capabilities are the default. Hook cap_task_setscheduler when !CONFIG_SECURITY. Move capable(TASK_KILL) to end of cap_task_kill to reduce audit messages. Nov 05: Add secondary calls in selinux/hooks.c to task_setioprio and task_setscheduler so that selinux and capabilities with file cap support can be stacked. Sep 05: As Seth Arnold points out, uid checks are out of place for capability code. Sep 01: Define task_setscheduler, task_setioprio, cap_task_kill, and task_setnice to make sure a user cannot affect a process in which they called a program with some fscaps. One remaining question is the note under task_setscheduler: are we ok with CAP_SYS_NICE being sufficient to confine a process to a cpuset? It is a semantic change, as without fsccaps, attach_task doesn't allow CAP_SYS_NICE to override the uid equivalence check. But since it uses security_task_setscheduler, which elsewhere is used where CAP_SYS_NICE can be used to override the uid equivalence check, fixing it might be tough. task_setscheduler note: this also controls cpuset:attach_task. Are we ok with CAP_SYS_NICE being used to confine to a cpuset? task_setioprio task_setnice sys_setpriority uses this (through set_one_prio) for another process. Need same checks as setrlimit Aug 21: Updated secureexec implementation to reflect the fact that euid and uid might be the same and nonzero, but the process might still have elevated caps. Aug 15: Handle endianness of xattrs. Enforce capability version match between kernel and disk. Enforce that no bits beyond the known max capability are set, else return -EPERM. With this extra processing, it may be worth reconsidering doing all the work at bprm_set_security rather than d_instantiate. Aug 10: Always call getxattr at bprm_set_security, rather than caching it at d_instantiate. [morgan@kernel.org: file-caps clean up for linux/capability.h] [bunk@kernel.org: unexport cap_inode_killpriv] Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: James Morris <jmorris@namei.org> Cc: Chris Wright <chrisw@sous-sol.org> Cc: Andrew Morgan <morgan@kernel.org> Signed-off-by: Andrew Morgan <morgan@kernel.org> Signed-off-by: Adrian Bunk <bunk@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--fs/attr.c9
-rw-r--r--fs/nfsd/vfs.c4
-rw-r--r--fs/open.c3
-rw-r--r--fs/splice.c13
-rw-r--r--include/linux/binfmts.h3
-rw-r--r--include/linux/capability.h48
-rw-r--r--include/linux/fs.h1
-rw-r--r--include/linux/security.h40
-rw-r--r--mm/filemap.c14
-rw-r--r--security/Kconfig10
-rw-r--r--security/capability.c6
-rw-r--r--security/commoncap.c244
-rw-r--r--security/dummy.c12
-rw-r--r--security/security.c10
-rw-r--r--security/selinux/hooks.c74
15 files changed, 418 insertions, 73 deletions
diff --git a/fs/attr.c b/fs/attr.c
index f8dfc2269d8..ae58bd3f875 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -116,6 +116,15 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
116 attr->ia_atime = now; 116 attr->ia_atime = now;
117 if (!(ia_valid & ATTR_MTIME_SET)) 117 if (!(ia_valid & ATTR_MTIME_SET))
118 attr->ia_mtime = now; 118 attr->ia_mtime = now;
119 if (ia_valid & ATTR_KILL_PRIV) {
120 attr->ia_valid &= ~ATTR_KILL_PRIV;
121 ia_valid &= ~ATTR_KILL_PRIV;
122 error = security_inode_need_killpriv(dentry);
123 if (error > 0)
124 error = security_inode_killpriv(dentry);
125 if (error)
126 return error;
127 }
119 if (ia_valid & ATTR_KILL_SUID) { 128 if (ia_valid & ATTR_KILL_SUID) {
120 attr->ia_valid &= ~ATTR_KILL_SUID; 129 attr->ia_valid &= ~ATTR_KILL_SUID;
121 if (mode & S_ISUID) { 130 if (mode & S_ISUID) {
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 1d72f993b66..819545d2167 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -368,7 +368,7 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap,
368 368
369 /* Revoke setuid/setgid bit on chown/chgrp */ 369 /* Revoke setuid/setgid bit on chown/chgrp */
370 if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid) 370 if ((iap->ia_valid & ATTR_UID) && iap->ia_uid != inode->i_uid)
371 iap->ia_valid |= ATTR_KILL_SUID; 371 iap->ia_valid |= ATTR_KILL_SUID | ATTR_KILL_PRIV;
372 if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid) 372 if ((iap->ia_valid & ATTR_GID) && iap->ia_gid != inode->i_gid)
373 iap->ia_valid |= ATTR_KILL_SGID; 373 iap->ia_valid |= ATTR_KILL_SGID;
374 374
@@ -937,7 +937,7 @@ out:
937static void kill_suid(struct dentry *dentry) 937static void kill_suid(struct dentry *dentry)
938{ 938{
939 struct iattr ia; 939 struct iattr ia;
940 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID; 940 ia.ia_valid = ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
941 941
942 mutex_lock(&dentry->d_inode->i_mutex); 942 mutex_lock(&dentry->d_inode->i_mutex);
943 notify_change(dentry, &ia); 943 notify_change(dentry, &ia);
diff --git a/fs/open.c b/fs/open.c
index cdbb94a9efc..75385144df7 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -658,7 +658,8 @@ static int chown_common(struct dentry * dentry, uid_t user, gid_t group)
658 newattrs.ia_gid = group; 658 newattrs.ia_gid = group;
659 } 659 }
660 if (!S_ISDIR(inode->i_mode)) 660 if (!S_ISDIR(inode->i_mode))
661 newattrs.ia_valid |= ATTR_KILL_SUID|ATTR_KILL_SGID; 661 newattrs.ia_valid |=
662 ATTR_KILL_SUID | ATTR_KILL_SGID | ATTR_KILL_PRIV;
662 mutex_lock(&inode->i_mutex); 663 mutex_lock(&inode->i_mutex);
663 error = notify_change(dentry, &newattrs); 664 error = notify_change(dentry, &newattrs);
664 mutex_unlock(&inode->i_mutex); 665 mutex_unlock(&inode->i_mutex);
diff --git a/fs/splice.c b/fs/splice.c
index 59a941d404d..6bdcb6107bc 100644
--- a/fs/splice.c
+++ b/fs/splice.c
@@ -824,13 +824,18 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
824{ 824{
825 struct address_space *mapping = out->f_mapping; 825 struct address_space *mapping = out->f_mapping;
826 struct inode *inode = mapping->host; 826 struct inode *inode = mapping->host;
827 int killsuid, killpriv;
827 ssize_t ret; 828 ssize_t ret;
828 int err; 829 int err = 0;
829 830
830 err = should_remove_suid(out->f_path.dentry); 831 killpriv = security_inode_need_killpriv(out->f_path.dentry);
831 if (unlikely(err)) { 832 killsuid = should_remove_suid(out->f_path.dentry);
833 if (unlikely(killsuid || killpriv)) {
832 mutex_lock(&inode->i_mutex); 834 mutex_lock(&inode->i_mutex);
833 err = __remove_suid(out->f_path.dentry, err); 835 if (killpriv)
836 err = security_inode_killpriv(out->f_path.dentry);
837 if (!err && killsuid)
838 err = __remove_suid(out->f_path.dentry, killsuid);
834 mutex_unlock(&inode->i_mutex); 839 mutex_unlock(&inode->i_mutex);
835 if (err) 840 if (err)
836 return err; 841 return err;
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index 3a6512f8ec9..b7fc55ec8d4 100644
--- a/include/linux/binfmts.h
+++ b/include/linux/binfmts.h
@@ -37,7 +37,8 @@ struct linux_binprm{
37 int sh_bang; 37 int sh_bang;
38 struct file * file; 38 struct file * file;
39 int e_uid, e_gid; 39 int e_uid, e_gid;
40 kernel_cap_t cap_inheritable, cap_permitted, cap_effective; 40 kernel_cap_t cap_inheritable, cap_permitted;
41 bool cap_effective;
41 void *security; 42 void *security;
42 int argc, envc; 43 int argc, envc;
43 char * filename; /* Name of binary as seen by procps */ 44 char * filename; /* Name of binary as seen by procps */
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 2dfa5855593..8961e7fb755 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -1,14 +1,14 @@
1/* 1/*
2 * This is <linux/capability.h> 2 * This is <linux/capability.h>
3 * 3 *
4 * Andrew G. Morgan <morgan@transmeta.com> 4 * Andrew G. Morgan <morgan@kernel.org>
5 * Alexander Kjeldaas <astor@guardian.no> 5 * Alexander Kjeldaas <astor@guardian.no>
6 * with help from Aleph1, Roland Buresund and Andrew Main. 6 * with help from Aleph1, Roland Buresund and Andrew Main.
7 * 7 *
8 * See here for the libcap library ("POSIX draft" compliance): 8 * See here for the libcap library ("POSIX draft" compliance):
9 * 9 *
10 * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/ 10 * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.6/
11 */ 11 */
12 12
13#ifndef _LINUX_CAPABILITY_H 13#ifndef _LINUX_CAPABILITY_H
14#define _LINUX_CAPABILITY_H 14#define _LINUX_CAPABILITY_H
@@ -28,23 +28,41 @@ struct task_struct;
28 following structure to such a composite is better handled in a user 28 following structure to such a composite is better handled in a user
29 library since the draft standard requires the use of malloc/free 29 library since the draft standard requires the use of malloc/free
30 etc.. */ 30 etc.. */
31 31
32#define _LINUX_CAPABILITY_VERSION 0x19980330 32#define _LINUX_CAPABILITY_VERSION 0x19980330
33 33
34typedef struct __user_cap_header_struct { 34typedef struct __user_cap_header_struct {
35 __u32 version; 35 __u32 version;
36 int pid; 36 int pid;
37} __user *cap_user_header_t; 37} __user *cap_user_header_t;
38 38
39typedef struct __user_cap_data_struct { 39typedef struct __user_cap_data_struct {
40 __u32 effective; 40 __u32 effective;
41 __u32 permitted; 41 __u32 permitted;
42 __u32 inheritable; 42 __u32 inheritable;
43} __user *cap_user_data_t; 43} __user *cap_user_data_t;
44
45#ifdef __KERNEL__
46 44
47#include <asm/current.h> 45#define XATTR_CAPS_SUFFIX "capability"
46#define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX
47
48#define XATTR_CAPS_SZ (3*sizeof(__le32))
49#define VFS_CAP_REVISION_MASK 0xFF000000
50#define VFS_CAP_REVISION_1 0x01000000
51
52#define VFS_CAP_REVISION VFS_CAP_REVISION_1
53
54#define VFS_CAP_FLAGS_MASK ~VFS_CAP_REVISION_MASK
55#define VFS_CAP_FLAGS_EFFECTIVE 0x000001
56
57struct vfs_cap_data {
58 __u32 magic_etc; /* Little endian */
59 struct {
60 __u32 permitted; /* Little endian */
61 __u32 inheritable; /* Little endian */
62 } data[1];
63};
64
65#ifdef __KERNEL__
48 66
49/* #define STRICT_CAP_T_TYPECHECKS */ 67/* #define STRICT_CAP_T_TYPECHECKS */
50 68
@@ -59,7 +77,7 @@ typedef struct kernel_cap_struct {
59typedef __u32 kernel_cap_t; 77typedef __u32 kernel_cap_t;
60 78
61#endif 79#endif
62 80
63#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32)) 81#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
64#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t)) 82#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
65 83
@@ -67,7 +85,7 @@ typedef __u32 kernel_cap_t;
67 85
68 86
69/** 87/**
70 ** POSIX-draft defined capabilities. 88 ** POSIX-draft defined capabilities.
71 **/ 89 **/
72 90
73/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this 91/* In a system with the [_POSIX_CHOWN_RESTRICTED] option defined, this
@@ -87,7 +105,7 @@ typedef __u32 kernel_cap_t;
87 defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */ 105 defined. Excluding DAC access covered by CAP_LINUX_IMMUTABLE. */
88 106
89#define CAP_DAC_READ_SEARCH 2 107#define CAP_DAC_READ_SEARCH 2
90 108
91/* Overrides all restrictions about allowed operations on files, where 109/* Overrides all restrictions about allowed operations on files, where
92 file owner ID must be equal to the user ID, except where CAP_FSETID 110 file owner ID must be equal to the user ID, except where CAP_FSETID
93 is applicable. It doesn't override MAC and DAC restrictions. */ 111 is applicable. It doesn't override MAC and DAC restrictions. */
@@ -257,7 +275,7 @@ typedef __u32 kernel_cap_t;
257/* Override reserved space on ext2 filesystem */ 275/* Override reserved space on ext2 filesystem */
258/* Modify data journaling mode on ext3 filesystem (uses journaling 276/* Modify data journaling mode on ext3 filesystem (uses journaling
259 resources) */ 277 resources) */
260/* NOTE: ext2 honors fsuid when checking for resource overrides, so 278/* NOTE: ext2 honors fsuid when checking for resource overrides, so
261 you can override using fsuid too */ 279 you can override using fsuid too */
262/* Override size restrictions on IPC message queues */ 280/* Override size restrictions on IPC message queues */
263/* Allow more than 64hz interrupts from the real-time clock */ 281/* Allow more than 64hz interrupts from the real-time clock */
@@ -289,8 +307,10 @@ typedef __u32 kernel_cap_t;
289 307
290#define CAP_AUDIT_CONTROL 30 308#define CAP_AUDIT_CONTROL 30
291 309
310#define CAP_SETFCAP 31
311
292#ifdef __KERNEL__ 312#ifdef __KERNEL__
293/* 313/*
294 * Bounding set 314 * Bounding set
295 */ 315 */
296extern kernel_cap_t cap_bset; 316extern kernel_cap_t cap_bset;
@@ -298,7 +318,7 @@ extern kernel_cap_t cap_bset;
298/* 318/*
299 * Internal kernel functions only 319 * Internal kernel functions only
300 */ 320 */
301 321
302#ifdef STRICT_CAP_T_TYPECHECKS 322#ifdef STRICT_CAP_T_TYPECHECKS
303 323
304#define to_cap_t(x) { x } 324#define to_cap_t(x) { x }
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 365586a4c4d..e3fc5dbb224 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -329,6 +329,7 @@ typedef void (dio_iodone_t)(struct kiocb *iocb, loff_t offset,
329#define ATTR_KILL_SUID 2048 329#define ATTR_KILL_SUID 2048
330#define ATTR_KILL_SGID 4096 330#define ATTR_KILL_SGID 4096
331#define ATTR_FILE 8192 331#define ATTR_FILE 8192
332#define ATTR_KILL_PRIV 16384
332 333
333/* 334/*
334 * This is the Inode Attributes structure, used for notify_change(). It 335 * This is the Inode Attributes structure, used for notify_change(). It
diff --git a/include/linux/security.h b/include/linux/security.h
index a300a3f2fe6..df591d289ec 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -51,8 +51,14 @@ extern void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe);
51extern int cap_bprm_secureexec(struct linux_binprm *bprm); 51extern int cap_bprm_secureexec(struct linux_binprm *bprm);
52extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags); 52extern int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags);
53extern int cap_inode_removexattr(struct dentry *dentry, char *name); 53extern int cap_inode_removexattr(struct dentry *dentry, char *name);
54extern int cap_inode_need_killpriv(struct dentry *dentry);
55extern int cap_inode_killpriv(struct dentry *dentry);
54extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); 56extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
55extern void cap_task_reparent_to_init (struct task_struct *p); 57extern void cap_task_reparent_to_init (struct task_struct *p);
58extern int cap_task_kill(struct task_struct *p, struct siginfo *info, int sig, u32 secid);
59extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp);
60extern int cap_task_setioprio (struct task_struct *p, int ioprio);
61extern int cap_task_setnice (struct task_struct *p, int nice);
56extern int cap_syslog (int type); 62extern int cap_syslog (int type);
57extern int cap_vm_enough_memory(struct mm_struct *mm, long pages); 63extern int cap_vm_enough_memory(struct mm_struct *mm, long pages);
58 64
@@ -413,6 +419,18 @@ struct request_sock;
413 * is specified by @buffer_size. @buffer may be NULL to request 419 * is specified by @buffer_size. @buffer may be NULL to request
414 * the size of the buffer required. 420 * the size of the buffer required.
415 * Returns number of bytes used/required on success. 421 * Returns number of bytes used/required on success.
422 * @inode_need_killpriv:
423 * Called when an inode has been changed.
424 * @dentry is the dentry being changed.
425 * Return <0 on error to abort the inode change operation.
426 * Return 0 if inode_killpriv does not need to be called.
427 * Return >0 if inode_killpriv does need to be called.
428 * @inode_killpriv:
429 * The setuid bit is being removed. Remove similar security labels.
430 * Called with the dentry->d_inode->i_mutex held.
431 * @dentry is the dentry being changed.
432 * Return 0 on success. If error is returned, then the operation
433 * causing setuid bit removal is failed.
416 * 434 *
417 * Security hooks for file operations 435 * Security hooks for file operations
418 * 436 *
@@ -1239,6 +1257,8 @@ struct security_operations {
1239 int (*inode_getxattr) (struct dentry *dentry, char *name); 1257 int (*inode_getxattr) (struct dentry *dentry, char *name);
1240 int (*inode_listxattr) (struct dentry *dentry); 1258 int (*inode_listxattr) (struct dentry *dentry);
1241 int (*inode_removexattr) (struct dentry *dentry, char *name); 1259 int (*inode_removexattr) (struct dentry *dentry, char *name);
1260 int (*inode_need_killpriv) (struct dentry *dentry);
1261 int (*inode_killpriv) (struct dentry *dentry);
1242 const char *(*inode_xattr_getsuffix) (void); 1262 const char *(*inode_xattr_getsuffix) (void);
1243 int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err); 1263 int (*inode_getsecurity)(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
1244 int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags); 1264 int (*inode_setsecurity)(struct inode *inode, const char *name, const void *value, size_t size, int flags);
@@ -1496,6 +1516,8 @@ void security_inode_post_setxattr(struct dentry *dentry, char *name,
1496int security_inode_getxattr(struct dentry *dentry, char *name); 1516int security_inode_getxattr(struct dentry *dentry, char *name);
1497int security_inode_listxattr(struct dentry *dentry); 1517int security_inode_listxattr(struct dentry *dentry);
1498int security_inode_removexattr(struct dentry *dentry, char *name); 1518int security_inode_removexattr(struct dentry *dentry, char *name);
1519int security_inode_need_killpriv(struct dentry *dentry);
1520int security_inode_killpriv(struct dentry *dentry);
1499const char *security_inode_xattr_getsuffix(void); 1521const char *security_inode_xattr_getsuffix(void);
1500int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err); 1522int security_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err);
1501int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags); 1523int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags);
@@ -1891,6 +1913,16 @@ static inline int security_inode_removexattr (struct dentry *dentry, char *name)
1891 return cap_inode_removexattr(dentry, name); 1913 return cap_inode_removexattr(dentry, name);
1892} 1914}
1893 1915
1916static inline int security_inode_need_killpriv(struct dentry *dentry)
1917{
1918 return cap_inode_need_killpriv(dentry);
1919}
1920
1921static inline int security_inode_killpriv(struct dentry *dentry)
1922{
1923 return cap_inode_killpriv(dentry);
1924}
1925
1894static inline const char *security_inode_xattr_getsuffix (void) 1926static inline const char *security_inode_xattr_getsuffix (void)
1895{ 1927{
1896 return NULL ; 1928 return NULL ;
@@ -2035,12 +2067,12 @@ static inline int security_task_setgroups (struct group_info *group_info)
2035 2067
2036static inline int security_task_setnice (struct task_struct *p, int nice) 2068static inline int security_task_setnice (struct task_struct *p, int nice)
2037{ 2069{
2038 return 0; 2070 return cap_task_setnice(p, nice);
2039} 2071}
2040 2072
2041static inline int security_task_setioprio (struct task_struct *p, int ioprio) 2073static inline int security_task_setioprio (struct task_struct *p, int ioprio)
2042{ 2074{
2043 return 0; 2075 return cap_task_setioprio(p, ioprio);
2044} 2076}
2045 2077
2046static inline int security_task_getioprio (struct task_struct *p) 2078static inline int security_task_getioprio (struct task_struct *p)
@@ -2058,7 +2090,7 @@ static inline int security_task_setscheduler (struct task_struct *p,
2058 int policy, 2090 int policy,
2059 struct sched_param *lp) 2091 struct sched_param *lp)
2060{ 2092{
2061 return 0; 2093 return cap_task_setscheduler(p, policy, lp);
2062} 2094}
2063 2095
2064static inline int security_task_getscheduler (struct task_struct *p) 2096static inline int security_task_getscheduler (struct task_struct *p)
@@ -2075,7 +2107,7 @@ static inline int security_task_kill (struct task_struct *p,
2075 struct siginfo *info, int sig, 2107 struct siginfo *info, int sig,
2076 u32 secid) 2108 u32 secid)
2077{ 2109{
2078 return 0; 2110 return cap_task_kill(p, info, sig, secid);
2079} 2111}
2080 2112
2081static inline int security_task_wait (struct task_struct *p) 2113static inline int security_task_wait (struct task_struct *p)
diff --git a/mm/filemap.c b/mm/filemap.c
index 4fb1546bbad..79f24a969cb 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1627,12 +1627,18 @@ int __remove_suid(struct dentry *dentry, int kill)
1627 1627
1628int remove_suid(struct dentry *dentry) 1628int remove_suid(struct dentry *dentry)
1629{ 1629{
1630 int kill = should_remove_suid(dentry); 1630 int killsuid = should_remove_suid(dentry);
1631 int killpriv = security_inode_need_killpriv(dentry);
1632 int error = 0;
1631 1633
1632 if (unlikely(kill)) 1634 if (killpriv < 0)
1633 return __remove_suid(dentry, kill); 1635 return killpriv;
1636 if (killpriv)
1637 error = security_inode_killpriv(dentry);
1638 if (!error && killsuid)
1639 error = __remove_suid(dentry, killsuid);
1634 1640
1635 return 0; 1641 return error;
1636} 1642}
1637EXPORT_SYMBOL(remove_suid); 1643EXPORT_SYMBOL(remove_suid);
1638 1644
diff --git a/security/Kconfig b/security/Kconfig
index a94ee94cf49..8086e61058e 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -80,6 +80,16 @@ config SECURITY_CAPABILITIES
80 This enables the "default" Linux capabilities functionality. 80 This enables the "default" Linux capabilities functionality.
81 If you are unsure how to answer this question, answer Y. 81 If you are unsure how to answer this question, answer Y.
82 82
83config SECURITY_FILE_CAPABILITIES
84 bool "File POSIX Capabilities (EXPERIMENTAL)"
85 depends on (SECURITY=n || SECURITY_CAPABILITIES!=n) && EXPERIMENTAL
86 default n
87 help
88 This enables filesystem capabilities, allowing you to give
89 binaries a subset of root's powers without using setuid 0.
90
91 If in doubt, answer N.
92
83config SECURITY_ROOTPLUG 93config SECURITY_ROOTPLUG
84 bool "Root Plug Support" 94 bool "Root Plug Support"
85 depends on USB=y && SECURITY 95 depends on USB=y && SECURITY
diff --git a/security/capability.c b/security/capability.c
index fda6a14cb24..9e99f36a8b5 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -37,7 +37,13 @@ static struct security_operations capability_ops = {
37 37
38 .inode_setxattr = cap_inode_setxattr, 38 .inode_setxattr = cap_inode_setxattr,
39 .inode_removexattr = cap_inode_removexattr, 39 .inode_removexattr = cap_inode_removexattr,
40 .inode_need_killpriv = cap_inode_need_killpriv,
41 .inode_killpriv = cap_inode_killpriv,
40 42
43 .task_kill = cap_task_kill,
44 .task_setscheduler = cap_task_setscheduler,
45 .task_setioprio = cap_task_setioprio,
46 .task_setnice = cap_task_setnice,
41 .task_post_setuid = cap_task_post_setuid, 47 .task_post_setuid = cap_task_post_setuid,
42 .task_reparent_to_init = cap_task_reparent_to_init, 48 .task_reparent_to_init = cap_task_reparent_to_init,
43 49
diff --git a/security/commoncap.c b/security/commoncap.c
index 0f8a2ce3f3a..afca6dd4ae6 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -22,6 +22,7 @@
22#include <linux/ptrace.h> 22#include <linux/ptrace.h>
23#include <linux/xattr.h> 23#include <linux/xattr.h>
24#include <linux/hugetlb.h> 24#include <linux/hugetlb.h>
25#include <linux/mount.h>
25 26
26int cap_netlink_send(struct sock *sk, struct sk_buff *skb) 27int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
27{ 28{
@@ -108,14 +109,130 @@ void cap_capset_set (struct task_struct *target, kernel_cap_t *effective,
108 target->cap_permitted = *permitted; 109 target->cap_permitted = *permitted;
109} 110}
110 111
112static inline void bprm_clear_caps(struct linux_binprm *bprm)
113{
114 cap_clear(bprm->cap_inheritable);
115 cap_clear(bprm->cap_permitted);
116 bprm->cap_effective = false;
117}
118
119#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
120
121int cap_inode_need_killpriv(struct dentry *dentry)
122{
123 struct inode *inode = dentry->d_inode;
124 int error;
125
126 if (!inode->i_op || !inode->i_op->getxattr)
127 return 0;
128
129 error = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, NULL, 0);
130 if (error <= 0)
131 return 0;
132 return 1;
133}
134
135int cap_inode_killpriv(struct dentry *dentry)
136{
137 struct inode *inode = dentry->d_inode;
138
139 if (!inode->i_op || !inode->i_op->removexattr)
140 return 0;
141
142 return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
143}
144
145static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm,
146 int size)
147{
148 __u32 magic_etc;
149
150 if (size != XATTR_CAPS_SZ)
151 return -EINVAL;
152
153 magic_etc = le32_to_cpu(caps[0]);
154
155 switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
156 case VFS_CAP_REVISION:
157 if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
158 bprm->cap_effective = true;
159 else
160 bprm->cap_effective = false;
161 bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) );
162 bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) );
163 return 0;
164 default:
165 return -EINVAL;
166 }
167}
168
169/* Locate any VFS capabilities: */
170static int get_file_caps(struct linux_binprm *bprm)
171{
172 struct dentry *dentry;
173 int rc = 0;
174 __le32 v1caps[XATTR_CAPS_SZ];
175 struct inode *inode;
176
177 if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
178 bprm_clear_caps(bprm);
179 return 0;
180 }
181
182 dentry = dget(bprm->file->f_dentry);
183 inode = dentry->d_inode;
184 if (!inode->i_op || !inode->i_op->getxattr)
185 goto out;
186
187 rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &v1caps,
188 XATTR_CAPS_SZ);
189 if (rc == -ENODATA || rc == -EOPNOTSUPP) {
190 /* no data, that's ok */
191 rc = 0;
192 goto out;
193 }
194 if (rc < 0)
195 goto out;
196
197 rc = cap_from_disk(v1caps, bprm, rc);
198 if (rc)
199 printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
200 __FUNCTION__, rc, bprm->filename);
201
202out:
203 dput(dentry);
204 if (rc)
205 bprm_clear_caps(bprm);
206
207 return rc;
208}
209
210#else
211int cap_inode_need_killpriv(struct dentry *dentry)
212{
213 return 0;
214}
215
216int cap_inode_killpriv(struct dentry *dentry)
217{
218 return 0;
219}
220
221static inline int get_file_caps(struct linux_binprm *bprm)
222{
223 bprm_clear_caps(bprm);
224 return 0;
225}
226#endif
227
111int cap_bprm_set_security (struct linux_binprm *bprm) 228int cap_bprm_set_security (struct linux_binprm *bprm)
112{ 229{
113 /* Copied from fs/exec.c:prepare_binprm. */ 230 int ret;
114 231
115 /* We don't have VFS support for capabilities yet */ 232 ret = get_file_caps(bprm);
116 cap_clear (bprm->cap_inheritable); 233 if (ret)
117 cap_clear (bprm->cap_permitted); 234 printk(KERN_NOTICE "%s: get_file_caps returned %d for %s\n",
118 cap_clear (bprm->cap_effective); 235 __FUNCTION__, ret, bprm->filename);
119 236
120 /* To support inheritance of root-permissions and suid-root 237 /* To support inheritance of root-permissions and suid-root
121 * executables under compatibility mode, we raise all three 238 * executables under compatibility mode, we raise all three
@@ -131,9 +248,10 @@ int cap_bprm_set_security (struct linux_binprm *bprm)
131 cap_set_full (bprm->cap_permitted); 248 cap_set_full (bprm->cap_permitted);
132 } 249 }
133 if (bprm->e_uid == 0) 250 if (bprm->e_uid == 0)
134 cap_set_full (bprm->cap_effective); 251 bprm->cap_effective = true;
135 } 252 }
136 return 0; 253
254 return ret;
137} 255}
138 256
139void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) 257void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
@@ -149,6 +267,7 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
149 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 267 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
150 !cap_issubset (new_permitted, current->cap_permitted)) { 268 !cap_issubset (new_permitted, current->cap_permitted)) {
151 set_dumpable(current->mm, suid_dumpable); 269 set_dumpable(current->mm, suid_dumpable);
270 current->pdeath_signal = 0;
152 271
153 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { 272 if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
154 if (!capable(CAP_SETUID)) { 273 if (!capable(CAP_SETUID)) {
@@ -170,8 +289,8 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
170 * capability rules */ 289 * capability rules */
171 if (!is_init(current)) { 290 if (!is_init(current)) {
172 current->cap_permitted = new_permitted; 291 current->cap_permitted = new_permitted;
173 current->cap_effective = 292 current->cap_effective = bprm->cap_effective ?
174 cap_intersect (new_permitted, bprm->cap_effective); 293 new_permitted : 0;
175 } 294 }
176 295
177 /* AUD: Audit candidate if current->cap_effective is set */ 296 /* AUD: Audit candidate if current->cap_effective is set */
@@ -181,11 +300,15 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
181 300
182int cap_bprm_secureexec (struct linux_binprm *bprm) 301int cap_bprm_secureexec (struct linux_binprm *bprm)
183{ 302{
184 /* If/when this module is enhanced to incorporate capability 303 if (current->uid != 0) {
185 bits on files, the test below should be extended to also perform a 304 if (bprm->cap_effective)
186 test between the old and new capability sets. For now, 305 return 1;
187 it simply preserves the legacy decision algorithm used by 306 if (!cap_isclear(bprm->cap_permitted))
188 the old userland. */ 307 return 1;
308 if (!cap_isclear(bprm->cap_inheritable))
309 return 1;
310 }
311
189 return (current->euid != current->uid || 312 return (current->euid != current->uid ||
190 current->egid != current->gid); 313 current->egid != current->gid);
191} 314}
@@ -193,7 +316,11 @@ int cap_bprm_secureexec (struct linux_binprm *bprm)
193int cap_inode_setxattr(struct dentry *dentry, char *name, void *value, 316int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
194 size_t size, int flags) 317 size_t size, int flags)
195{ 318{
196 if (!strncmp(name, XATTR_SECURITY_PREFIX, 319 if (!strcmp(name, XATTR_NAME_CAPS)) {
320 if (!capable(CAP_SETFCAP))
321 return -EPERM;
322 return 0;
323 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
197 sizeof(XATTR_SECURITY_PREFIX) - 1) && 324 sizeof(XATTR_SECURITY_PREFIX) - 1) &&
198 !capable(CAP_SYS_ADMIN)) 325 !capable(CAP_SYS_ADMIN))
199 return -EPERM; 326 return -EPERM;
@@ -202,7 +329,11 @@ int cap_inode_setxattr(struct dentry *dentry, char *name, void *value,
202 329
203int cap_inode_removexattr(struct dentry *dentry, char *name) 330int cap_inode_removexattr(struct dentry *dentry, char *name)
204{ 331{
205 if (!strncmp(name, XATTR_SECURITY_PREFIX, 332 if (!strcmp(name, XATTR_NAME_CAPS)) {
333 if (!capable(CAP_SETFCAP))
334 return -EPERM;
335 return 0;
336 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
206 sizeof(XATTR_SECURITY_PREFIX) - 1) && 337 sizeof(XATTR_SECURITY_PREFIX) - 1) &&
207 !capable(CAP_SYS_ADMIN)) 338 !capable(CAP_SYS_ADMIN))
208 return -EPERM; 339 return -EPERM;
@@ -299,6 +430,83 @@ int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid,
299 return 0; 430 return 0;
300} 431}
301 432
433#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
434/*
435 * Rationale: code calling task_setscheduler, task_setioprio, and
436 * task_setnice, assumes that
437 * . if capable(cap_sys_nice), then those actions should be allowed
438 * . if not capable(cap_sys_nice), but acting on your own processes,
439 * then those actions should be allowed
440 * This is insufficient now since you can call code without suid, but
441 * yet with increased caps.
442 * So we check for increased caps on the target process.
443 */
444static inline int cap_safe_nice(struct task_struct *p)
445{
446 if (!cap_issubset(p->cap_permitted, current->cap_permitted) &&
447 !__capable(current, CAP_SYS_NICE))
448 return -EPERM;
449 return 0;
450}
451
452int cap_task_setscheduler (struct task_struct *p, int policy,
453 struct sched_param *lp)
454{
455 return cap_safe_nice(p);
456}
457
458int cap_task_setioprio (struct task_struct *p, int ioprio)
459{
460 return cap_safe_nice(p);
461}
462
463int cap_task_setnice (struct task_struct *p, int nice)
464{
465 return cap_safe_nice(p);
466}
467
468int cap_task_kill(struct task_struct *p, struct siginfo *info,
469 int sig, u32 secid)
470{
471 if (info != SEND_SIG_NOINFO && (is_si_special(info) || SI_FROMKERNEL(info)))
472 return 0;
473
474 if (secid)
475 /*
476 * Signal sent as a particular user.
477 * Capabilities are ignored. May be wrong, but it's the
478 * only thing we can do at the moment.
479 * Used only by usb drivers?
480 */
481 return 0;
482 if (cap_issubset(p->cap_permitted, current->cap_permitted))
483 return 0;
484 if (capable(CAP_KILL))
485 return 0;
486
487 return -EPERM;
488}
489#else
490int cap_task_setscheduler (struct task_struct *p, int policy,
491 struct sched_param *lp)
492{
493 return 0;
494}
495int cap_task_setioprio (struct task_struct *p, int ioprio)
496{
497 return 0;
498}
499int cap_task_setnice (struct task_struct *p, int nice)
500{
501 return 0;
502}
503int cap_task_kill(struct task_struct *p, struct siginfo *info,
504 int sig, u32 secid)
505{
506 return 0;
507}
508#endif
509
302void cap_task_reparent_to_init (struct task_struct *p) 510void cap_task_reparent_to_init (struct task_struct *p)
303{ 511{
304 p->cap_effective = CAP_INIT_EFF_SET; 512 p->cap_effective = CAP_INIT_EFF_SET;
@@ -336,6 +544,10 @@ EXPORT_SYMBOL(cap_bprm_secureexec);
336EXPORT_SYMBOL(cap_inode_setxattr); 544EXPORT_SYMBOL(cap_inode_setxattr);
337EXPORT_SYMBOL(cap_inode_removexattr); 545EXPORT_SYMBOL(cap_inode_removexattr);
338EXPORT_SYMBOL(cap_task_post_setuid); 546EXPORT_SYMBOL(cap_task_post_setuid);
547EXPORT_SYMBOL(cap_task_kill);
548EXPORT_SYMBOL(cap_task_setscheduler);
549EXPORT_SYMBOL(cap_task_setioprio);
550EXPORT_SYMBOL(cap_task_setnice);
339EXPORT_SYMBOL(cap_task_reparent_to_init); 551EXPORT_SYMBOL(cap_task_reparent_to_init);
340EXPORT_SYMBOL(cap_syslog); 552EXPORT_SYMBOL(cap_syslog);
341EXPORT_SYMBOL(cap_vm_enough_memory); 553EXPORT_SYMBOL(cap_vm_enough_memory);
diff --git a/security/dummy.c b/security/dummy.c
index 4129dcf3dae..c77dec82238 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -376,6 +376,16 @@ static int dummy_inode_removexattr (struct dentry *dentry, char *name)
376 return 0; 376 return 0;
377} 377}
378 378
379static int dummy_inode_need_killpriv(struct dentry *dentry)
380{
381 return 0;
382}
383
384static int dummy_inode_killpriv(struct dentry *dentry)
385{
386 return 0;
387}
388
379static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err) 389static int dummy_inode_getsecurity(const struct inode *inode, const char *name, void *buffer, size_t size, int err)
380{ 390{
381 return -EOPNOTSUPP; 391 return -EOPNOTSUPP;
@@ -1022,6 +1032,8 @@ void security_fixup_ops (struct security_operations *ops)
1022 set_to_dummy_if_null(ops, inode_getxattr); 1032 set_to_dummy_if_null(ops, inode_getxattr);
1023 set_to_dummy_if_null(ops, inode_listxattr); 1033 set_to_dummy_if_null(ops, inode_listxattr);
1024 set_to_dummy_if_null(ops, inode_removexattr); 1034 set_to_dummy_if_null(ops, inode_removexattr);
1035 set_to_dummy_if_null(ops, inode_need_killpriv);
1036 set_to_dummy_if_null(ops, inode_killpriv);
1025 set_to_dummy_if_null(ops, inode_xattr_getsuffix); 1037 set_to_dummy_if_null(ops, inode_xattr_getsuffix);
1026 set_to_dummy_if_null(ops, inode_getsecurity); 1038 set_to_dummy_if_null(ops, inode_getsecurity);
1027 set_to_dummy_if_null(ops, inode_setsecurity); 1039 set_to_dummy_if_null(ops, inode_setsecurity);
diff --git a/security/security.c b/security/security.c
index 5b1c034815a..2e1b35dd255 100644
--- a/security/security.c
+++ b/security/security.c
@@ -518,6 +518,16 @@ int security_inode_removexattr(struct dentry *dentry, char *name)
518 return security_ops->inode_removexattr(dentry, name); 518 return security_ops->inode_removexattr(dentry, name);
519} 519}
520 520
521int security_inode_need_killpriv(struct dentry *dentry)
522{
523 return security_ops->inode_need_killpriv(dentry);
524}
525
526int security_inode_killpriv(struct dentry *dentry)
527{
528 return security_ops->inode_killpriv(dentry);
529}
530
521const char *security_inode_xattr_getsuffix(void) 531const char *security_inode_xattr_getsuffix(void)
522{ 532{
523 return security_ops->inode_xattr_getsuffix(); 533 return security_ops->inode_xattr_getsuffix();
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 83a535b7bc6..221def6a0b1 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)
2297 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR); 2297 return dentry_has_perm(current, mnt, dentry, FILE__GETATTR);
2298} 2298}
2299 2299
2300static int selinux_inode_setotherxattr(struct dentry *dentry, char *name)
2301{
2302 if (!strncmp(name, XATTR_SECURITY_PREFIX,
2303 sizeof XATTR_SECURITY_PREFIX - 1)) {
2304 if (!strcmp(name, XATTR_NAME_CAPS)) {
2305 if (!capable(CAP_SETFCAP))
2306 return -EPERM;
2307 } else if (!capable(CAP_SYS_ADMIN)) {
2308 /* A different attribute in the security namespace.
2309 Restrict to administrator. */
2310 return -EPERM;
2311 }
2312 }
2313
2314 /* Not an attribute we recognize, so just check the
2315 ordinary setattr permission. */
2316 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2317}
2318
2300static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags) 2319static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value, size_t size, int flags)
2301{ 2320{
2302 struct task_security_struct *tsec = current->security; 2321 struct task_security_struct *tsec = current->security;
@@ -2307,19 +2326,8 @@ static int selinux_inode_setxattr(struct dentry *dentry, char *name, void *value
2307 u32 newsid; 2326 u32 newsid;
2308 int rc = 0; 2327 int rc = 0;
2309 2328
2310 if (strcmp(name, XATTR_NAME_SELINUX)) { 2329 if (strcmp(name, XATTR_NAME_SELINUX))
2311 if (!strncmp(name, XATTR_SECURITY_PREFIX, 2330 return selinux_inode_setotherxattr(dentry, name);
2312 sizeof XATTR_SECURITY_PREFIX - 1) &&
2313 !capable(CAP_SYS_ADMIN)) {
2314 /* A different attribute in the security namespace.
2315 Restrict to administrator. */
2316 return -EPERM;
2317 }
2318
2319 /* Not an attribute we recognize, so just check the
2320 ordinary setattr permission. */
2321 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2322 }
2323 2331
2324 sbsec = inode->i_sb->s_security; 2332 sbsec = inode->i_sb->s_security;
2325 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT) 2333 if (sbsec->behavior == SECURITY_FS_USE_MNTPOINT)
@@ -2393,20 +2401,8 @@ static int selinux_inode_listxattr (struct dentry *dentry)
2393 2401
2394static int selinux_inode_removexattr (struct dentry *dentry, char *name) 2402static int selinux_inode_removexattr (struct dentry *dentry, char *name)
2395{ 2403{
2396 if (strcmp(name, XATTR_NAME_SELINUX)) { 2404 if (strcmp(name, XATTR_NAME_SELINUX))
2397 if (!strncmp(name, XATTR_SECURITY_PREFIX, 2405 return selinux_inode_setotherxattr(dentry, name);
2398 sizeof XATTR_SECURITY_PREFIX - 1) &&
2399 !capable(CAP_SYS_ADMIN)) {
2400 /* A different attribute in the security namespace.
2401 Restrict to administrator. */
2402 return -EPERM;
2403 }
2404
2405 /* Not an attribute we recognize, so just check the
2406 ordinary setattr permission. Might want a separate
2407 permission for removexattr. */
2408 return dentry_has_perm(current, NULL, dentry, FILE__SETATTR);
2409 }
2410 2406
2411 /* No one is allowed to remove a SELinux security label. 2407 /* No one is allowed to remove a SELinux security label.
2412 You can change the label, but all data must be labeled. */ 2408 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
2464 return len; 2460 return len;
2465} 2461}
2466 2462
2463static int selinux_inode_need_killpriv(struct dentry *dentry)
2464{
2465 return secondary_ops->inode_need_killpriv(dentry);
2466}
2467
2468static int selinux_inode_killpriv(struct dentry *dentry)
2469{
2470 return secondary_ops->inode_killpriv(dentry);
2471}
2472
2467/* file security operations */ 2473/* file security operations */
2468 2474
2469static int selinux_revalidate_file_permission(struct file *file, int mask) 2475static 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)
2882 2888
2883static int selinux_task_setioprio(struct task_struct *p, int ioprio) 2889static int selinux_task_setioprio(struct task_struct *p, int ioprio)
2884{ 2890{
2891 int rc;
2892
2893 rc = secondary_ops->task_setioprio(p, ioprio);
2894 if (rc)
2895 return rc;
2896
2885 return task_has_perm(current, p, PROCESS__SETSCHED); 2897 return task_has_perm(current, p, PROCESS__SETSCHED);
2886} 2898}
2887 2899
@@ -2911,6 +2923,12 @@ static int selinux_task_setrlimit(unsigned int resource, struct rlimit *new_rlim
2911 2923
2912static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp) 2924static int selinux_task_setscheduler(struct task_struct *p, int policy, struct sched_param *lp)
2913{ 2925{
2926 int rc;
2927
2928 rc = secondary_ops->task_setscheduler(p, policy, lp);
2929 if (rc)
2930 return rc;
2931
2914 return task_has_perm(current, p, PROCESS__SETSCHED); 2932 return task_has_perm(current, p, PROCESS__SETSCHED);
2915} 2933}
2916 2934
@@ -4830,6 +4848,8 @@ static struct security_operations selinux_ops = {
4830 .inode_getsecurity = selinux_inode_getsecurity, 4848 .inode_getsecurity = selinux_inode_getsecurity,
4831 .inode_setsecurity = selinux_inode_setsecurity, 4849 .inode_setsecurity = selinux_inode_setsecurity,
4832 .inode_listsecurity = selinux_inode_listsecurity, 4850 .inode_listsecurity = selinux_inode_listsecurity,
4851 .inode_need_killpriv = selinux_inode_need_killpriv,
4852 .inode_killpriv = selinux_inode_killpriv,
4833 4853
4834 .file_permission = selinux_file_permission, 4854 .file_permission = selinux_file_permission,
4835 .file_alloc_security = selinux_file_alloc_security, 4855 .file_alloc_security = selinux_file_alloc_security,