aboutsummaryrefslogtreecommitdiffstats
path: root/security/selinux
diff options
context:
space:
mode:
authorSerge E. Hallyn <serue@us.ibm.com>2007-10-17 02:31:36 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-17 11:43:07 -0400
commitb53767719b6cd8789392ea3e7e2eb7b8906898f0 (patch)
treea0279dc93c79b94d3865b0f19f6b7b353e20608c /security/selinux
parent57c521ce6125e15e99e56c902cb8da96bee7b36d (diff)
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/selinux')
-rw-r--r--security/selinux/hooks.c74
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)
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,