diff options
-rw-r--r-- | include/linux/capability.h | 4 | ||||
-rw-r--r-- | include/linux/security.h | 7 | ||||
-rw-r--r-- | kernel/capability.c | 5 | ||||
-rw-r--r-- | kernel/sysctl.c | 8 | ||||
-rw-r--r-- | kernel/sysctl_check.c | 5 | ||||
-rw-r--r-- | security/commoncap.c | 59 | ||||
-rw-r--r-- | security/dummy.c | 16 |
7 files changed, 80 insertions, 24 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h index 8961e7fb755c..7a8d7ade28a0 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
@@ -310,10 +310,6 @@ typedef __u32 kernel_cap_t; | |||
310 | #define CAP_SETFCAP 31 | 310 | #define CAP_SETFCAP 31 |
311 | 311 | ||
312 | #ifdef __KERNEL__ | 312 | #ifdef __KERNEL__ |
313 | /* | ||
314 | * Bounding set | ||
315 | */ | ||
316 | extern kernel_cap_t cap_bset; | ||
317 | 313 | ||
318 | /* | 314 | /* |
319 | * Internal kernel functions only | 315 | * Internal kernel functions only |
diff --git a/include/linux/security.h b/include/linux/security.h index 9b0b63c50f44..ff3f857f6957 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -34,6 +34,13 @@ | |||
34 | #include <linux/xfrm.h> | 34 | #include <linux/xfrm.h> |
35 | #include <net/flow.h> | 35 | #include <net/flow.h> |
36 | 36 | ||
37 | /* | ||
38 | * Bounding set | ||
39 | */ | ||
40 | extern kernel_cap_t cap_bset; | ||
41 | |||
42 | extern unsigned securebits; | ||
43 | |||
37 | struct ctl_table; | 44 | struct ctl_table; |
38 | 45 | ||
39 | /* | 46 | /* |
diff --git a/kernel/capability.c b/kernel/capability.c index 4e350a36ed6a..14853be5944d 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (C) 1997 Andrew Main <zefram@fysh.org> | 4 | * Copyright (C) 1997 Andrew Main <zefram@fysh.org> |
5 | * | 5 | * |
6 | * Integrated into 2.1.97+, Andrew G. Morgan <morgan@transmeta.com> | 6 | * Integrated into 2.1.97+, Andrew G. Morgan <morgan@kernel.org> |
7 | * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> | 7 | * 30 May 2002: Cleanup, Robert M. Love <rml@tech9.net> |
8 | */ | 8 | */ |
9 | 9 | ||
@@ -14,9 +14,6 @@ | |||
14 | #include <linux/syscalls.h> | 14 | #include <linux/syscalls.h> |
15 | #include <asm/uaccess.h> | 15 | #include <asm/uaccess.h> |
16 | 16 | ||
17 | unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ | ||
18 | kernel_cap_t cap_bset = CAP_INIT_EFF_SET; | ||
19 | |||
20 | /* | 17 | /* |
21 | * This lock protects task->cap_* for all tasks including current. | 18 | * This lock protects task->cap_* for all tasks including current. |
22 | * Locking rule: acquire this prior to tasklist_lock. | 19 | * Locking rule: acquire this prior to tasklist_lock. |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index c25e67e19af7..067554bda8b7 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/sysctl.h> | 25 | #include <linux/sysctl.h> |
26 | #include <linux/proc_fs.h> | 26 | #include <linux/proc_fs.h> |
27 | #include <linux/capability.h> | 27 | #include <linux/security.h> |
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/utsname.h> | 29 | #include <linux/utsname.h> |
30 | #include <linux/smp_lock.h> | 30 | #include <linux/smp_lock.h> |
@@ -371,6 +371,7 @@ static struct ctl_table kern_table[] = { | |||
371 | .proc_handler = &proc_dointvec_taint, | 371 | .proc_handler = &proc_dointvec_taint, |
372 | }, | 372 | }, |
373 | #endif | 373 | #endif |
374 | #ifdef CONFIG_SECURITY_CAPABILITIES | ||
374 | { | 375 | { |
375 | .procname = "cap-bound", | 376 | .procname = "cap-bound", |
376 | .data = &cap_bset, | 377 | .data = &cap_bset, |
@@ -378,6 +379,7 @@ static struct ctl_table kern_table[] = { | |||
378 | .mode = 0600, | 379 | .mode = 0600, |
379 | .proc_handler = &proc_dointvec_bset, | 380 | .proc_handler = &proc_dointvec_bset, |
380 | }, | 381 | }, |
382 | #endif /* def CONFIG_SECURITY_CAPABILITIES */ | ||
381 | #ifdef CONFIG_BLK_DEV_INITRD | 383 | #ifdef CONFIG_BLK_DEV_INITRD |
382 | { | 384 | { |
383 | .ctl_name = KERN_REALROOTDEV, | 385 | .ctl_name = KERN_REALROOTDEV, |
@@ -1872,10 +1874,11 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp, | |||
1872 | return 0; | 1874 | return 0; |
1873 | } | 1875 | } |
1874 | 1876 | ||
1877 | #ifdef CONFIG_SECURITY_CAPABILITIES | ||
1875 | /* | 1878 | /* |
1876 | * init may raise the set. | 1879 | * init may raise the set. |
1877 | */ | 1880 | */ |
1878 | 1881 | ||
1879 | int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp, | 1882 | int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp, |
1880 | void __user *buffer, size_t *lenp, loff_t *ppos) | 1883 | void __user *buffer, size_t *lenp, loff_t *ppos) |
1881 | { | 1884 | { |
@@ -1889,6 +1892,7 @@ int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp, | |||
1889 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, | 1892 | return do_proc_dointvec(table,write,filp,buffer,lenp,ppos, |
1890 | do_proc_dointvec_bset_conv,&op); | 1893 | do_proc_dointvec_bset_conv,&op); |
1891 | } | 1894 | } |
1895 | #endif /* def CONFIG_SECURITY_CAPABILITIES */ | ||
1892 | 1896 | ||
1893 | /* | 1897 | /* |
1894 | * Taint values can only be increased | 1898 | * Taint values can only be increased |
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c index f47c33d17032..3c9ef5a7d575 100644 --- a/kernel/sysctl_check.c +++ b/kernel/sysctl_check.c | |||
@@ -38,7 +38,10 @@ static struct trans_ctl_table trans_kern_table[] = { | |||
38 | { KERN_NODENAME, "hostname" }, | 38 | { KERN_NODENAME, "hostname" }, |
39 | { KERN_DOMAINNAME, "domainname" }, | 39 | { KERN_DOMAINNAME, "domainname" }, |
40 | 40 | ||
41 | #ifdef CONFIG_SECURITY_CAPABILITIES | ||
41 | { KERN_CAP_BSET, "cap-bound" }, | 42 | { KERN_CAP_BSET, "cap-bound" }, |
43 | #endif /* def CONFIG_SECURITY_CAPABILITIES */ | ||
44 | |||
42 | { KERN_PANIC, "panic" }, | 45 | { KERN_PANIC, "panic" }, |
43 | { KERN_REALROOTDEV, "real-root-dev" }, | 46 | { KERN_REALROOTDEV, "real-root-dev" }, |
44 | 47 | ||
@@ -1532,7 +1535,9 @@ int sysctl_check_table(struct ctl_table *table) | |||
1532 | (table->strategy == sysctl_ms_jiffies) || | 1535 | (table->strategy == sysctl_ms_jiffies) || |
1533 | (table->proc_handler == proc_dostring) || | 1536 | (table->proc_handler == proc_dostring) || |
1534 | (table->proc_handler == proc_dointvec) || | 1537 | (table->proc_handler == proc_dointvec) || |
1538 | #ifdef CONFIG_SECURITY_CAPABILITIES | ||
1535 | (table->proc_handler == proc_dointvec_bset) || | 1539 | (table->proc_handler == proc_dointvec_bset) || |
1540 | #endif /* def CONFIG_SECURITY_CAPABILITIES */ | ||
1536 | (table->proc_handler == proc_dointvec_minmax) || | 1541 | (table->proc_handler == proc_dointvec_minmax) || |
1537 | (table->proc_handler == proc_dointvec_jiffies) || | 1542 | (table->proc_handler == proc_dointvec_jiffies) || |
1538 | (table->proc_handler == proc_dointvec_userhz_jiffies) || | 1543 | (table->proc_handler == proc_dointvec_userhz_jiffies) || |
diff --git a/security/commoncap.c b/security/commoncap.c index 778cb0cfc5d8..48ca5b092768 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -24,6 +24,25 @@ | |||
24 | #include <linux/hugetlb.h> | 24 | #include <linux/hugetlb.h> |
25 | #include <linux/mount.h> | 25 | #include <linux/mount.h> |
26 | 26 | ||
27 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | ||
28 | /* | ||
29 | * Because of the reduced scope of CAP_SETPCAP when filesystem | ||
30 | * capabilities are in effect, it is safe to allow this capability to | ||
31 | * be available in the default configuration. | ||
32 | */ | ||
33 | # define CAP_INIT_BSET CAP_FULL_SET | ||
34 | #else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */ | ||
35 | # define CAP_INIT_BSET CAP_INIT_EFF_SET | ||
36 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ | ||
37 | |||
38 | kernel_cap_t cap_bset = CAP_INIT_BSET; /* systemwide capability bound */ | ||
39 | EXPORT_SYMBOL(cap_bset); | ||
40 | |||
41 | /* Global security state */ | ||
42 | |||
43 | unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ | ||
44 | EXPORT_SYMBOL(securebits); | ||
45 | |||
27 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) | 46 | int cap_netlink_send(struct sock *sk, struct sk_buff *skb) |
28 | { | 47 | { |
29 | NETLINK_CB(skb).eff_cap = current->cap_effective; | 48 | NETLINK_CB(skb).eff_cap = current->cap_effective; |
@@ -73,14 +92,44 @@ int cap_capget (struct task_struct *target, kernel_cap_t *effective, | |||
73 | return 0; | 92 | return 0; |
74 | } | 93 | } |
75 | 94 | ||
95 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | ||
96 | |||
97 | static inline int cap_block_setpcap(struct task_struct *target) | ||
98 | { | ||
99 | /* | ||
100 | * No support for remote process capability manipulation with | ||
101 | * filesystem capability support. | ||
102 | */ | ||
103 | return (target != current); | ||
104 | } | ||
105 | |||
106 | static inline int cap_inh_is_capped(void) | ||
107 | { | ||
108 | /* | ||
109 | * return 1 if changes to the inheritable set are limited | ||
110 | * to the old permitted set. | ||
111 | */ | ||
112 | return !cap_capable(current, CAP_SETPCAP); | ||
113 | } | ||
114 | |||
115 | #else /* ie., ndef CONFIG_SECURITY_FILE_CAPABILITIES */ | ||
116 | |||
117 | static inline int cap_block_setpcap(struct task_struct *t) { return 0; } | ||
118 | static inline int cap_inh_is_capped(void) { return 1; } | ||
119 | |||
120 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ | ||
121 | |||
76 | int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, | 122 | int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, |
77 | kernel_cap_t *inheritable, kernel_cap_t *permitted) | 123 | kernel_cap_t *inheritable, kernel_cap_t *permitted) |
78 | { | 124 | { |
79 | /* Derived from kernel/capability.c:sys_capset. */ | 125 | if (cap_block_setpcap(target)) { |
80 | /* verify restrictions on target's new Inheritable set */ | 126 | return -EPERM; |
81 | if (!cap_issubset (*inheritable, | 127 | } |
82 | cap_combine (target->cap_inheritable, | 128 | if (cap_inh_is_capped() |
83 | current->cap_permitted))) { | 129 | && !cap_issubset(*inheritable, |
130 | cap_combine(target->cap_inheritable, | ||
131 | current->cap_permitted))) { | ||
132 | /* incapable of using this inheritable set */ | ||
84 | return -EPERM; | 133 | return -EPERM; |
85 | } | 134 | } |
86 | 135 | ||
diff --git a/security/dummy.c b/security/dummy.c index bc43d4c7383e..6d895ade73de 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -37,15 +37,13 @@ static int dummy_capget (struct task_struct *target, kernel_cap_t * effective, | |||
37 | kernel_cap_t * inheritable, kernel_cap_t * permitted) | 37 | kernel_cap_t * inheritable, kernel_cap_t * permitted) |
38 | { | 38 | { |
39 | *effective = *inheritable = *permitted = 0; | 39 | *effective = *inheritable = *permitted = 0; |
40 | if (!issecure(SECURE_NOROOT)) { | 40 | if (target->euid == 0) { |
41 | if (target->euid == 0) { | 41 | *permitted |= (~0 & ~CAP_FS_MASK); |
42 | *permitted |= (~0 & ~CAP_FS_MASK); | 42 | *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK); |
43 | *effective |= (~0 & ~CAP_TO_MASK(CAP_SETPCAP) & ~CAP_FS_MASK); | 43 | } |
44 | } | 44 | if (target->fsuid == 0) { |
45 | if (target->fsuid == 0) { | 45 | *permitted |= CAP_FS_MASK; |
46 | *permitted |= CAP_FS_MASK; | 46 | *effective |= CAP_FS_MASK; |
47 | *effective |= CAP_FS_MASK; | ||
48 | } | ||
49 | } | 47 | } |
50 | return 0; | 48 | return 0; |
51 | } | 49 | } |