aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/capability.h11
-rw-r--r--include/linux/init_task.h13
-rw-r--r--include/linux/prctl.h4
-rw-r--r--include/linux/sched.h2
-rw-r--r--include/linux/security.h5
-rw-r--r--include/linux/sysctl.h3
-rw-r--r--kernel/fork.c1
-rw-r--r--kernel/sys.c13
-rw-r--r--kernel/sysctl.c35
-rw-r--r--kernel/sysctl_check.c7
-rw-r--r--security/commoncap.c44
11 files changed, 67 insertions, 71 deletions
diff --git a/include/linux/capability.h b/include/linux/capability.h
index a1d93da67fe9..ffe7bab8c3a0 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -152,7 +152,9 @@ typedef struct kernel_cap_struct {
152 * Transfer any capability in your permitted set to any pid, 152 * Transfer any capability in your permitted set to any pid,
153 * remove any capability in your permitted set from any pid 153 * remove any capability in your permitted set from any pid
154 * With VFS support for capabilities (neither of above, but) 154 * With VFS support for capabilities (neither of above, but)
155 * Add any capability to the current process' inheritable set 155 * Add any capability from current's capability bounding set
156 * to the current process' inheritable set
157 * Allow taking bits out of capability bounding set
156 */ 158 */
157 159
158#define CAP_SETPCAP 8 160#define CAP_SETPCAP 8
@@ -202,7 +204,6 @@ typedef struct kernel_cap_struct {
202#define CAP_IPC_OWNER 15 204#define CAP_IPC_OWNER 15
203 205
204/* Insert and remove kernel modules - modify kernel without limit */ 206/* Insert and remove kernel modules - modify kernel without limit */
205/* Modify cap_bset */
206#define CAP_SYS_MODULE 16 207#define CAP_SYS_MODULE 16
207 208
208/* Allow ioperm/iopl access */ 209/* Allow ioperm/iopl access */
@@ -314,6 +315,10 @@ typedef struct kernel_cap_struct {
314 315
315#define CAP_SETFCAP 31 316#define CAP_SETFCAP 31
316 317
318#define CAP_LAST_CAP CAP_SETFCAP
319
320#define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP)
321
317/* 322/*
318 * Bit location of each capability (used by user-space library and kernel) 323 * Bit location of each capability (used by user-space library and kernel)
319 */ 324 */
@@ -465,6 +470,8 @@ extern const kernel_cap_t __cap_init_eff_set;
465int capable(int cap); 470int capable(int cap);
466int __capable(struct task_struct *t, int cap); 471int __capable(struct task_struct *t, int cap);
467 472
473extern long cap_prctl_drop(unsigned long cap);
474
468#endif /* __KERNEL__ */ 475#endif /* __KERNEL__ */
469 476
470#endif /* !_LINUX_CAPABILITY_H */ 477#endif /* !_LINUX_CAPABILITY_H */
diff --git a/include/linux/init_task.h b/include/linux/init_task.h
index f42663eaf655..1f74e1d7415f 100644
--- a/include/linux/init_task.h
+++ b/include/linux/init_task.h
@@ -121,6 +121,18 @@ extern struct group_info init_groups;
121#else 121#else
122#define INIT_IDS 122#define INIT_IDS
123#endif 123#endif
124
125#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
126/*
127 * Because of the reduced scope of CAP_SETPCAP when filesystem
128 * capabilities are in effect, it is safe to allow CAP_SETPCAP to
129 * be available in the default configuration.
130 */
131# define CAP_INIT_BSET CAP_FULL_SET
132#else
133# define CAP_INIT_BSET CAP_INIT_EFF_SET
134#endif
135
124/* 136/*
125 * INIT_TASK is used to set up the first task table, touch at 137 * INIT_TASK is used to set up the first task table, touch at
126 * your own risk!. Base=0, limit=0x1fffff (=2MB) 138 * your own risk!. Base=0, limit=0x1fffff (=2MB)
@@ -156,6 +168,7 @@ extern struct group_info init_groups;
156 .cap_effective = CAP_INIT_EFF_SET, \ 168 .cap_effective = CAP_INIT_EFF_SET, \
157 .cap_inheritable = CAP_INIT_INH_SET, \ 169 .cap_inheritable = CAP_INIT_INH_SET, \
158 .cap_permitted = CAP_FULL_SET, \ 170 .cap_permitted = CAP_FULL_SET, \
171 .cap_bset = CAP_INIT_BSET, \
159 .keep_capabilities = 0, \ 172 .keep_capabilities = 0, \
160 .user = INIT_USER, \ 173 .user = INIT_USER, \
161 .comm = "swapper", \ 174 .comm = "swapper", \
diff --git a/include/linux/prctl.h b/include/linux/prctl.h
index e2eff9079fe9..3800639775ae 100644
--- a/include/linux/prctl.h
+++ b/include/linux/prctl.h
@@ -63,4 +63,8 @@
63#define PR_GET_SECCOMP 21 63#define PR_GET_SECCOMP 21
64#define PR_SET_SECCOMP 22 64#define PR_SET_SECCOMP 22
65 65
66/* Get/set the capability bounding set */
67#define PR_CAPBSET_READ 23
68#define PR_CAPBSET_DROP 24
69
66#endif /* _LINUX_PRCTL_H */ 70#endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/sched.h b/include/linux/sched.h
index c30d174a02fa..9c13be3a21e8 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1098,7 +1098,7 @@ struct task_struct {
1098 uid_t uid,euid,suid,fsuid; 1098 uid_t uid,euid,suid,fsuid;
1099 gid_t gid,egid,sgid,fsgid; 1099 gid_t gid,egid,sgid,fsgid;
1100 struct group_info *group_info; 1100 struct group_info *group_info;
1101 kernel_cap_t cap_effective, cap_inheritable, cap_permitted; 1101 kernel_cap_t cap_effective, cap_inheritable, cap_permitted, cap_bset;
1102 unsigned keep_capabilities:1; 1102 unsigned keep_capabilities:1;
1103 struct user_struct *user; 1103 struct user_struct *user;
1104#ifdef CONFIG_KEYS 1104#ifdef CONFIG_KEYS
diff --git a/include/linux/security.h b/include/linux/security.h
index 9d289e726fd8..fe52cdeab0a6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -40,11 +40,6 @@
40#define ROOTCONTEXT_MNT 0x04 40#define ROOTCONTEXT_MNT 0x04
41#define DEFCONTEXT_MNT 0x08 41#define DEFCONTEXT_MNT 0x08
42 42
43/*
44 * Bounding set
45 */
46extern kernel_cap_t cap_bset;
47
48extern unsigned securebits; 43extern unsigned securebits;
49 44
50struct ctl_table; 45struct ctl_table;
diff --git a/include/linux/sysctl.h b/include/linux/sysctl.h
index bf4ae4e138f7..571f01d20a86 100644
--- a/include/linux/sysctl.h
+++ b/include/linux/sysctl.h
@@ -102,7 +102,6 @@ enum
102 KERN_NODENAME=7, 102 KERN_NODENAME=7,
103 KERN_DOMAINNAME=8, 103 KERN_DOMAINNAME=8,
104 104
105 KERN_CAP_BSET=14, /* int: capability bounding set */
106 KERN_PANIC=15, /* int: panic timeout */ 105 KERN_PANIC=15, /* int: panic timeout */
107 KERN_REALROOTDEV=16, /* real root device to mount after initrd */ 106 KERN_REALROOTDEV=16, /* real root device to mount after initrd */
108 107
@@ -965,8 +964,6 @@ extern int proc_dostring(struct ctl_table *, int, struct file *,
965 void __user *, size_t *, loff_t *); 964 void __user *, size_t *, loff_t *);
966extern int proc_dointvec(struct ctl_table *, int, struct file *, 965extern int proc_dointvec(struct ctl_table *, int, struct file *,
967 void __user *, size_t *, loff_t *); 966 void __user *, size_t *, loff_t *);
968extern int proc_dointvec_bset(struct ctl_table *, int, struct file *,
969 void __user *, size_t *, loff_t *);
970extern int proc_dointvec_minmax(struct ctl_table *, int, struct file *, 967extern int proc_dointvec_minmax(struct ctl_table *, int, struct file *,
971 void __user *, size_t *, loff_t *); 968 void __user *, size_t *, loff_t *);
972extern int proc_dointvec_jiffies(struct ctl_table *, int, struct file *, 969extern int proc_dointvec_jiffies(struct ctl_table *, int, struct file *,
diff --git a/kernel/fork.c b/kernel/fork.c
index 1160f87ba700..2b55b74cd999 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1118,6 +1118,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
1118#ifdef CONFIG_SECURITY 1118#ifdef CONFIG_SECURITY
1119 p->security = NULL; 1119 p->security = NULL;
1120#endif 1120#endif
1121 p->cap_bset = current->cap_bset;
1121 p->io_context = NULL; 1122 p->io_context = NULL;
1122 p->audit_context = NULL; 1123 p->audit_context = NULL;
1123 cgroup_fork(p); 1124 cgroup_fork(p);
diff --git a/kernel/sys.c b/kernel/sys.c
index d1fe71eb4546..4162d12390b6 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1637,7 +1637,7 @@ asmlinkage long sys_umask(int mask)
1637 mask = xchg(&current->fs->umask, mask & S_IRWXUGO); 1637 mask = xchg(&current->fs->umask, mask & S_IRWXUGO);
1638 return mask; 1638 return mask;
1639} 1639}
1640 1640
1641asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3, 1641asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1642 unsigned long arg4, unsigned long arg5) 1642 unsigned long arg4, unsigned long arg5)
1643{ 1643{
@@ -1742,6 +1742,17 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
1742 error = prctl_set_seccomp(arg2); 1742 error = prctl_set_seccomp(arg2);
1743 break; 1743 break;
1744 1744
1745 case PR_CAPBSET_READ:
1746 if (!cap_valid(arg2))
1747 return -EINVAL;
1748 return !!cap_raised(current->cap_bset, arg2);
1749 case PR_CAPBSET_DROP:
1750#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
1751 return cap_prctl_drop(arg2);
1752#else
1753 return -EINVAL;
1754#endif
1755
1745 default: 1756 default:
1746 error = -EINVAL; 1757 error = -EINVAL;
1747 break; 1758 break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index d0b47b859067..5e2ad5bf88e2 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -419,15 +419,6 @@ static struct ctl_table kern_table[] = {
419 .proc_handler = &proc_dointvec, 419 .proc_handler = &proc_dointvec,
420 }, 420 },
421#endif 421#endif
422#ifdef CONFIG_SECURITY_CAPABILITIES
423 {
424 .procname = "cap-bound",
425 .data = &cap_bset,
426 .maxlen = sizeof(kernel_cap_t),
427 .mode = 0600,
428 .proc_handler = &proc_dointvec_bset,
429 },
430#endif /* def CONFIG_SECURITY_CAPABILITIES */
431#ifdef CONFIG_BLK_DEV_INITRD 422#ifdef CONFIG_BLK_DEV_INITRD
432 { 423 {
433 .ctl_name = KERN_REALROOTDEV, 424 .ctl_name = KERN_REALROOTDEV,
@@ -2096,26 +2087,6 @@ static int do_proc_dointvec_bset_conv(int *negp, unsigned long *lvalp,
2096 return 0; 2087 return 0;
2097} 2088}
2098 2089
2099#ifdef CONFIG_SECURITY_CAPABILITIES
2100/*
2101 * init may raise the set.
2102 */
2103
2104int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
2105 void __user *buffer, size_t *lenp, loff_t *ppos)
2106{
2107 int op;
2108
2109 if (write && !capable(CAP_SYS_MODULE)) {
2110 return -EPERM;
2111 }
2112
2113 op = is_global_init(current) ? OP_SET : OP_AND;
2114 return do_proc_dointvec(table,write,filp,buffer,lenp,ppos,
2115 do_proc_dointvec_bset_conv,&op);
2116}
2117#endif /* def CONFIG_SECURITY_CAPABILITIES */
2118
2119/* 2090/*
2120 * Taint values can only be increased 2091 * Taint values can only be increased
2121 */ 2092 */
@@ -2529,12 +2500,6 @@ int proc_dointvec(struct ctl_table *table, int write, struct file *filp,
2529 return -ENOSYS; 2500 return -ENOSYS;
2530} 2501}
2531 2502
2532int proc_dointvec_bset(struct ctl_table *table, int write, struct file *filp,
2533 void __user *buffer, size_t *lenp, loff_t *ppos)
2534{
2535 return -ENOSYS;
2536}
2537
2538int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp, 2503int proc_dointvec_minmax(struct ctl_table *table, int write, struct file *filp,
2539 void __user *buffer, size_t *lenp, loff_t *ppos) 2504 void __user *buffer, size_t *lenp, loff_t *ppos)
2540{ 2505{
diff --git a/kernel/sysctl_check.c b/kernel/sysctl_check.c
index c3206fa50048..006365b69eaf 100644
--- a/kernel/sysctl_check.c
+++ b/kernel/sysctl_check.c
@@ -37,10 +37,6 @@ static struct trans_ctl_table trans_kern_table[] = {
37 { KERN_NODENAME, "hostname" }, 37 { KERN_NODENAME, "hostname" },
38 { KERN_DOMAINNAME, "domainname" }, 38 { KERN_DOMAINNAME, "domainname" },
39 39
40#ifdef CONFIG_SECURITY_CAPABILITIES
41 { KERN_CAP_BSET, "cap-bound" },
42#endif /* def CONFIG_SECURITY_CAPABILITIES */
43
44 { KERN_PANIC, "panic" }, 40 { KERN_PANIC, "panic" },
45 { KERN_REALROOTDEV, "real-root-dev" }, 41 { KERN_REALROOTDEV, "real-root-dev" },
46 42
@@ -1498,9 +1494,6 @@ int sysctl_check_table(struct nsproxy *namespaces, struct ctl_table *table)
1498 (table->strategy == sysctl_ms_jiffies) || 1494 (table->strategy == sysctl_ms_jiffies) ||
1499 (table->proc_handler == proc_dostring) || 1495 (table->proc_handler == proc_dostring) ||
1500 (table->proc_handler == proc_dointvec) || 1496 (table->proc_handler == proc_dointvec) ||
1501#ifdef CONFIG_SECURITY_CAPABILITIES
1502 (table->proc_handler == proc_dointvec_bset) ||
1503#endif /* def CONFIG_SECURITY_CAPABILITIES */
1504 (table->proc_handler == proc_dointvec_minmax) || 1497 (table->proc_handler == proc_dointvec_minmax) ||
1505 (table->proc_handler == proc_dointvec_jiffies) || 1498 (table->proc_handler == proc_dointvec_jiffies) ||
1506 (table->proc_handler == proc_dointvec_userhz_jiffies) || 1499 (table->proc_handler == proc_dointvec_userhz_jiffies) ||
diff --git a/security/commoncap.c b/security/commoncap.c
index 01ab47845dcf..5aba82679a0b 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -25,20 +25,6 @@
25#include <linux/mount.h> 25#include <linux/mount.h>
26#include <linux/sched.h> 26#include <linux/sched.h>
27 27
28#ifdef CONFIG_SECURITY_FILE_CAPABILITIES
29/*
30 * Because of the reduced scope of CAP_SETPCAP when filesystem
31 * capabilities are in effect, it is safe to allow this capability to
32 * be available in the default configuration.
33 */
34# define CAP_INIT_BSET CAP_FULL_SET
35#else /* ie. ndef CONFIG_SECURITY_FILE_CAPABILITIES */
36# define CAP_INIT_BSET CAP_INIT_EFF_SET
37#endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */
38
39kernel_cap_t cap_bset = CAP_INIT_BSET; /* systemwide capability bound */
40EXPORT_SYMBOL(cap_bset);
41
42/* Global security state */ 28/* Global security state */
43 29
44unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */ 30unsigned securebits = SECUREBITS_DEFAULT; /* systemwide security settings */
@@ -140,6 +126,12 @@ int cap_capset_check (struct task_struct *target, kernel_cap_t *effective,
140 /* incapable of using this inheritable set */ 126 /* incapable of using this inheritable set */
141 return -EPERM; 127 return -EPERM;
142 } 128 }
129 if (!cap_issubset(*inheritable,
130 cap_combine(target->cap_inheritable,
131 current->cap_bset))) {
132 /* no new pI capabilities outside bounding set */
133 return -EPERM;
134 }
143 135
144 /* verify restrictions on target's new Permitted set */ 136 /* verify restrictions on target's new Permitted set */
145 if (!cap_issubset (*permitted, 137 if (!cap_issubset (*permitted,
@@ -337,10 +329,11 @@ void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe)
337 /* Derived from fs/exec.c:compute_creds. */ 329 /* Derived from fs/exec.c:compute_creds. */
338 kernel_cap_t new_permitted, working; 330 kernel_cap_t new_permitted, working;
339 331
340 new_permitted = cap_intersect (bprm->cap_permitted, cap_bset); 332 new_permitted = cap_intersect(bprm->cap_permitted,
341 working = cap_intersect (bprm->cap_inheritable, 333 current->cap_bset);
334 working = cap_intersect(bprm->cap_inheritable,
342 current->cap_inheritable); 335 current->cap_inheritable);
343 new_permitted = cap_combine (new_permitted, working); 336 new_permitted = cap_combine(new_permitted, working);
344 337
345 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || 338 if (bprm->e_uid != current->uid || bprm->e_gid != current->gid ||
346 !cap_issubset (new_permitted, current->cap_permitted)) { 339 !cap_issubset (new_permitted, current->cap_permitted)) {
@@ -581,6 +574,23 @@ int cap_task_kill(struct task_struct *p, struct siginfo *info,
581 574
582 return -EPERM; 575 return -EPERM;
583} 576}
577
578/*
579 * called from kernel/sys.c for prctl(PR_CABSET_DROP)
580 * done without task_capability_lock() because it introduces
581 * no new races - i.e. only another task doing capget() on
582 * this task could get inconsistent info. There can be no
583 * racing writer bc a task can only change its own caps.
584 */
585long cap_prctl_drop(unsigned long cap)
586{
587 if (!capable(CAP_SETPCAP))
588 return -EPERM;
589 if (!cap_valid(cap))
590 return -EINVAL;
591 cap_lower(current->cap_bset, cap);
592 return 0;
593}
584#else 594#else
585int cap_task_setscheduler (struct task_struct *p, int policy, 595int cap_task_setscheduler (struct task_struct *p, int policy,
586 struct sched_param *lp) 596 struct sched_param *lp)