aboutsummaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorAndrew G. Morgan <morgan@kernel.org>2008-04-28 05:13:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-28 11:58:26 -0400
commit3898b1b4ebff8dcfbcf1807e0661585e06c9a91c (patch)
tree69a338864dfe654f68064a599c5d0da460df34ac /include
parent4016a1390d07f15b267eecb20e76a48fd5c524ef (diff)
capabilities: implement per-process securebits
Filesystem capability support makes it possible to do away with (set)uid-0 based privilege and use capabilities instead. That is, with filesystem support for capabilities but without this present patch, it is (conceptually) possible to manage a system with capabilities alone and never need to obtain privilege via (set)uid-0. Of course, conceptually isn't quite the same as currently possible since few user applications, certainly not enough to run a viable system, are currently prepared to leverage capabilities to exercise privilege. Further, many applications exist that may never get upgraded in this way, and the kernel will continue to want to support their setuid-0 base privilege needs. Where pure-capability applications evolve and replace setuid-0 binaries, it is desirable that there be a mechanisms by which they can contain their privilege. In addition to leveraging the per-process bounding and inheritable sets, this should include suppressing the privilege of the uid-0 superuser from the process' tree of children. The feature added by this patch can be leveraged to suppress the privilege associated with (set)uid-0. This suppression requires CAP_SETPCAP to initiate, and only immediately affects the 'current' process (it is inherited through fork()/exec()). This reimplementation differs significantly from the historical support for securebits which was system-wide, unwieldy and which has ultimately withered to a dead relic in the source of the modern kernel. With this patch applied a process, that is capable(CAP_SETPCAP), can now drop all legacy privilege (through uid=0) for itself and all subsequently fork()'d/exec()'d children with: prctl(PR_SET_SECUREBITS, 0x2f); This patch represents a no-op unless CONFIG_SECURITY_FILE_CAPABILITIES is enabled at configure time. [akpm@linux-foundation.org: fix uninitialised var warning] [serue@us.ibm.com: capabilities: use cap_task_prctl when !CONFIG_SECURITY] Signed-off-by: Andrew G. Morgan <morgan@kernel.org> Acked-by: Serge Hallyn <serue@us.ibm.com> Reviewed-by: James Morris <jmorris@namei.org> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: Paul Moore <paul.moore@hp.com> Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r--include/linux/capability.h3
-rw-r--r--include/linux/init_task.h3
-rw-r--r--include/linux/prctl.h9
-rw-r--r--include/linux/sched.h3
-rw-r--r--include/linux/securebits.h25
-rw-r--r--include/linux/security.h16
6 files changed, 38 insertions, 21 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 7d50ff6d269f..eaab759b1460 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -155,6 +155,7 @@ typedef struct kernel_cap_struct {
155 * Add any capability from current's capability bounding set 155 * Add any capability from current's capability bounding set
156 * to the current process' inheritable set 156 * to the current process' inheritable set
157 * Allow taking bits out of capability bounding set 157 * Allow taking bits out of capability bounding set
158 * Allow modification of the securebits for a process
158 */ 159 */
159 160
160#define CAP_SETPCAP 8 161#define CAP_SETPCAP 8
@@ -490,8 +491,6 @@ extern const kernel_cap_t __cap_init_eff_set;
490int capable(int cap); 491int capable(int cap);
491int __capable(struct task_struct *t, int cap); 492int __capable(struct task_struct *t, int cap);
492 493
493extern long cap_prctl_drop(unsigned long cap);
494
495#endif /* __KERNEL__ */ 494#endif /* __KERNEL__ */
496 495
497#endif /* !_LINUX_CAPABILITY_H */ 496#endif /* !_LINUX_CAPABILITY_H */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index 37a6f5bc4a92..bf6b8a61f8db 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -9,6 +9,7 @@
9#include <linux/ipc.h> 9#include <linux/ipc.h>
10#include <linux/pid_namespace.h> 10#include <linux/pid_namespace.h>
11#include <linux/user_namespace.h> 11#include <linux/user_namespace.h>
12#include <linux/securebits.h>
12#include <net/net_namespace.h> 13#include <net/net_namespace.h>
13 14
14#define INIT_FDTABLE \ 15#define INIT_FDTABLE \
@@ -172,7 +173,7 @@ extern struct group_info init_groups;
172 .cap_inheritable = CAP_INIT_INH_SET, \ 173 .cap_inheritable = CAP_INIT_INH_SET, \
173 .cap_permitted = CAP_FULL_SET, \ 174 .cap_permitted = CAP_FULL_SET, \
174 .cap_bset = CAP_INIT_BSET, \ 175 .cap_bset = CAP_INIT_BSET, \
175 .keep_capabilities = 0, \ 176 .securebits = SECUREBITS_DEFAULT, \
176 .user = INIT_USER, \ 177 .user = INIT_USER, \
177 .comm = "swapper", \ 178 .comm = "swapper", \
178 .thread = INIT_THREAD, \ 179 .thread = INIT_THREAD, \
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index 5c80b1939636..5ad79198d6f9 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -16,7 +16,8 @@
16# define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */ 16# define PR_UNALIGN_NOPRINT 1 /* silently fix up unaligned user accesses */
17# define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */ 17# define PR_UNALIGN_SIGBUS 2 /* generate SIGBUS on unaligned user access */
18 18
19/* Get/set whether or not to drop capabilities on setuid() away from uid 0 */ 19/* Get/set whether or not to drop capabilities on setuid() away from
20 * uid 0 (as per security/commoncap.c) */
20#define PR_GET_KEEPCAPS 7 21#define PR_GET_KEEPCAPS 7
21#define PR_SET_KEEPCAPS 8 22#define PR_SET_KEEPCAPS 8
22 23
@@ -63,7 +64,7 @@
63#define PR_GET_SECCOMP 21 64#define PR_GET_SECCOMP 21
64#define PR_SET_SECCOMP 22 65#define PR_SET_SECCOMP 22
65 66
66/* Get/set the capability bounding set */ 67/* Get/set the capability bounding set (as per security/commoncap.c) */
67#define PR_CAPBSET_READ 23 68#define PR_CAPBSET_READ 23
68#define PR_CAPBSET_DROP 24 69#define PR_CAPBSET_DROP 24
69 70
@@ -73,4 +74,8 @@
73# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ 74# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
74# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ 75# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
75 76
77/* Get/set securebits (as per security/commoncap.c) */
78#define PR_GET_SECUREBITS 27
79#define PR_SET_SECUREBITS 28
80
76#endif /* _LINUX_PRCTL_H */ 81#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 9a4f3e63e3bf..024d72b47a0c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -68,7 +68,6 @@ struct sched_param {
68#include <linux/smp.h> 68#include <linux/smp.h>
69#include <linux/sem.h> 69#include <linux/sem.h>
70#include <linux/signal.h> 70#include <linux/signal.h>
71#include <linux/securebits.h>
72#include <linux/fs_struct.h> 71#include <linux/fs_struct.h>
73#include <linux/compiler.h> 72#include <linux/compiler.h>
74#include <linux/completion.h> 73#include <linux/completion.h>
@@ -1133,7 +1132,7 @@ struct task_struct {
1133 gid_t gid,egid,sgid,fsgid; 1132 gid_t gid,egid,sgid,fsgid;
1134 struct group_info *group_info; 1133 struct group_info *group_info;
1135 kernel_cap_t cap_effective, cap_inheritable, cap_permitted, cap_bset; 1134 kernel_cap_t cap_effective, cap_inheritable, cap_permitted, cap_bset;
1136 unsigned keep_capabilities:1; 1135 unsigned securebits;
1137 struct user_struct *user; 1136 struct user_struct *user;
1138#ifdef CONFIG_KEYS 1137#ifdef CONFIG_KEYS
1139 struct key *request_key_auth; /* assumed request_key authority */ 1138 struct key *request_key_auth; /* assumed request_key authority */
diff --git a/include/linux/securebits.h b/include/linux/securebits.h
index 5b0617840fa4..c1f19dbceb05 100644
--- a/include/linux/securebits.h
+++ b/include/linux/securebits.h
@@ -3,28 +3,39 @@
3 3
4#define SECUREBITS_DEFAULT 0x00000000 4#define SECUREBITS_DEFAULT 0x00000000
5 5
6extern unsigned securebits;
7
8/* When set UID 0 has no special privileges. When unset, we support 6/* When set UID 0 has no special privileges. When unset, we support
9 inheritance of root-permissions and suid-root executable under 7 inheritance of root-permissions and suid-root executable under
10 compatibility mode. We raise the effective and inheritable bitmasks 8 compatibility mode. We raise the effective and inheritable bitmasks
11 *of the executable file* if the effective uid of the new process is 9 *of the executable file* if the effective uid of the new process is
12 0. If the real uid is 0, we raise the inheritable bitmask of the 10 0. If the real uid is 0, we raise the inheritable bitmask of the
13 executable file. */ 11 executable file. */
14#define SECURE_NOROOT 0 12#define SECURE_NOROOT 0
13#define SECURE_NOROOT_LOCKED 1 /* make bit-0 immutable */
15 14
16/* When set, setuid to/from uid 0 does not trigger capability-"fixes" 15/* When set, setuid to/from uid 0 does not trigger capability-"fixes"
17 to be compatible with old programs relying on set*uid to loose 16 to be compatible with old programs relying on set*uid to loose
18 privileges. When unset, setuid doesn't change privileges. */ 17 privileges. When unset, setuid doesn't change privileges. */
19#define SECURE_NO_SETUID_FIXUP 2 18#define SECURE_NO_SETUID_FIXUP 2
19#define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */
20
21/* When set, a process can retain its capabilities even after
22 transitioning to a non-root user (the set-uid fixup suppressed by
23 bit 2). Bit-4 is cleared when a process calls exec(); setting both
24 bit 4 and 5 will create a barrier through exec that no exec()'d
25 child can use this feature again. */
26#define SECURE_KEEP_CAPS 4
27#define SECURE_KEEP_CAPS_LOCKED 5 /* make bit-4 immutable */
20 28
21/* Each securesetting is implemented using two bits. One bit specify 29/* Each securesetting is implemented using two bits. One bit specify
22 whether the setting is on or off. The other bit specify whether the 30 whether the setting is on or off. The other bit specify whether the
23 setting is fixed or not. A setting which is fixed cannot be changed 31 setting is fixed or not. A setting which is fixed cannot be changed
24 from user-level. */ 32 from user-level. */
33#define issecure_mask(X) (1 << (X))
34#define issecure(X) (issecure_mask(X) & current->securebits)
25 35
26#define issecure(X) ( (1 << (X+1)) & SECUREBITS_DEFAULT ? \ 36#define SECURE_ALL_BITS (issecure_mask(SECURE_NOROOT) | \
27 (1 << (X)) & SECUREBITS_DEFAULT : \ 37 issecure_mask(SECURE_NO_SETUID_FIXUP) | \
28 (1 << (X)) & securebits ) 38 issecure_mask(SECURE_KEEP_CAPS))
39#define SECURE_ALL_LOCKS (SECURE_ALL_BITS << 1)
29 40
30#endif /* !_LINUX_SECUREBITS_H */ 41#endif /* !_LINUX_SECUREBITS_H */
diff --git a/include/linux/security.h b/include/linux/security.h
index 53a34539382a..e6299e50e210 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -34,8 +34,6 @@
34#include <linux/xfrm.h> 34#include <linux/xfrm.h>
35#include <net/flow.h> 35#include <net/flow.h>
36 36
37extern unsigned securebits;
38
39/* Maximum number of letters for an LSM name string */ 37/* Maximum number of letters for an LSM name string */
40#define SECURITY_NAME_MAX 10 38#define SECURITY_NAME_MAX 10
41 39
@@ -61,6 +59,8 @@ extern int cap_inode_need_killpriv(struct dentry *dentry);
61extern int cap_inode_killpriv(struct dentry *dentry); 59extern int cap_inode_killpriv(struct dentry *dentry);
62extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags); 60extern int cap_task_post_setuid (uid_t old_ruid, uid_t old_euid, uid_t old_suid, int flags);
63extern void cap_task_reparent_to_init (struct task_struct *p); 61extern void cap_task_reparent_to_init (struct task_struct *p);
62extern int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3,
63 unsigned long arg4, unsigned long arg5, long *rc_p);
64extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp); 64extern int cap_task_setscheduler (struct task_struct *p, int policy, struct sched_param *lp);
65extern int cap_task_setioprio (struct task_struct *p, int ioprio); 65extern int cap_task_setioprio (struct task_struct *p, int ioprio);
66extern int cap_task_setnice (struct task_struct *p, int nice); 66extern int cap_task_setnice (struct task_struct *p, int nice);
@@ -720,7 +720,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
720 * @arg3 contains a argument. 720 * @arg3 contains a argument.
721 * @arg4 contains a argument. 721 * @arg4 contains a argument.
722 * @arg5 contains a argument. 722 * @arg5 contains a argument.
723 * Return 0 if permission is granted. 723 * @rc_p contains a pointer to communicate back the forced return code
724 * Return 0 if permission is granted, and non-zero if the security module
725 * has taken responsibility (setting *rc_p) for the prctl call.
724 * @task_reparent_to_init: 726 * @task_reparent_to_init:
725 * Set the security attributes in @p->security for a kernel thread that 727 * Set the security attributes in @p->security for a kernel thread that
726 * is being reparented to the init task. 728 * is being reparented to the init task.
@@ -1420,7 +1422,7 @@ struct security_operations {
1420 int (*task_wait) (struct task_struct * p); 1422 int (*task_wait) (struct task_struct * p);
1421 int (*task_prctl) (int option, unsigned long arg2, 1423 int (*task_prctl) (int option, unsigned long arg2,
1422 unsigned long arg3, unsigned long arg4, 1424 unsigned long arg3, unsigned long arg4,
1423 unsigned long arg5); 1425 unsigned long arg5, long *rc_p);
1424 void (*task_reparent_to_init) (struct task_struct * p); 1426 void (*task_reparent_to_init) (struct task_struct * p);
1425 void (*task_to_inode)(struct task_struct *p, struct inode *inode); 1427 void (*task_to_inode)(struct task_struct *p, struct inode *inode);
1426 1428
@@ -1684,7 +1686,7 @@ int security_task_kill(struct task_struct *p, struct siginfo *info,
1684 int sig, u32 secid); 1686 int sig, u32 secid);
1685int security_task_wait(struct task_struct *p); 1687int security_task_wait(struct task_struct *p);
1686int security_task_prctl(int option, unsigned long arg2, unsigned long arg3, 1688int security_task_prctl(int option, unsigned long arg2, unsigned long arg3,
1687 unsigned long arg4, unsigned long arg5); 1689 unsigned long arg4, unsigned long arg5, long *rc_p);
1688void security_task_reparent_to_init(struct task_struct *p); 1690void security_task_reparent_to_init(struct task_struct *p);
1689void security_task_to_inode(struct task_struct *p, struct inode *inode); 1691void security_task_to_inode(struct task_struct *p, struct inode *inode);
1690int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag); 1692int security_ipc_permission(struct kern_ipc_perm *ipcp, short flag);
@@ -2271,9 +2273,9 @@ static inline int security_task_wait (struct task_struct *p)
2271static inline int security_task_prctl (int option, unsigned long arg2, 2273static inline int security_task_prctl (int option, unsigned long arg2,
2272 unsigned long arg3, 2274 unsigned long arg3,
2273 unsigned long arg4, 2275 unsigned long arg4,
2274 unsigned long arg5) 2276 unsigned long arg5, long *rc_p)
2275{ 2277{
2276 return 0; 2278 return cap_task_prctl(option, arg2, arg3, arg3, arg5, rc_p);
2277} 2279}
2278 2280
2279static inline void security_task_reparent_to_init (struct task_struct *p) 2281static inline void security_task_reparent_to_init (struct task_struct *p)