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 /security
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>
Diffstat (limited to 'security')
-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
6 files changed, 313 insertions, 43 deletions
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,