aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/capability.h
diff options
context:
space:
mode:
authorSerge E. Hallyn <serue@us.ibm.com>2008-02-05 01:29:45 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:20 -0500
commit3b7391de67da515c91f48aa371de77cb6cc5c07e (patch)
tree22b9f5d9d1c36b374eb5765219aca3c7e1f23486 /include/linux/capability.h
parent46c383cc4530ccc438cb325e92e11eb21dd3d4fc (diff)
capabilities: introduce per-process capability bounding set
The capability bounding set is a set beyond which capabilities cannot grow. Currently cap_bset is per-system. It can be manipulated through sysctl, but only init can add capabilities. Root can remove capabilities. By default it includes all caps except CAP_SETPCAP. This patch makes the bounding set per-process when file capabilities are enabled. It is inherited at fork from parent. Noone can add elements, CAP_SETPCAP is required to remove them. One example use of this is to start a safer container. For instance, until device namespaces or per-container device whitelists are introduced, it is best to take CAP_MKNOD away from a container. The bounding set will not affect pP and pE immediately. It will only affect pP' and pE' after subsequent exec()s. It also does not affect pI, and exec() does not constrain pI'. So to really start a shell with no way of regain CAP_MKNOD, you would do prctl(PR_CAPBSET_DROP, CAP_MKNOD); cap_t cap = cap_get_proc(); cap_value_t caparray[1]; caparray[0] = CAP_MKNOD; cap_set_flag(cap, CAP_INHERITABLE, 1, caparray, CAP_DROP); cap_set_proc(cap); cap_free(cap); The following test program will get and set the bounding set (but not pI). For instance ./bset get (lists capabilities in bset) ./bset drop cap_net_raw (starts shell with new bset) (use capset, setuid binary, or binary with file capabilities to try to increase caps) ************************************************************ cap_bound.c ************************************************************ #include <sys/prctl.h> #include <linux/capability.h> #include <sys/types.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #ifndef PR_CAPBSET_READ #define PR_CAPBSET_READ 23 #endif #ifndef PR_CAPBSET_DROP #define PR_CAPBSET_DROP 24 #endif int usage(char *me) { printf("Usage: %s get\n", me); printf(" %s drop <capability>\n", me); return 1; } #define numcaps 32 char *captable[numcaps] = { "cap_chown", "cap_dac_override", "cap_dac_read_search", "cap_fowner", "cap_fsetid", "cap_kill", "cap_setgid", "cap_setuid", "cap_setpcap", "cap_linux_immutable", "cap_net_bind_service", "cap_net_broadcast", "cap_net_admin", "cap_net_raw", "cap_ipc_lock", "cap_ipc_owner", "cap_sys_module", "cap_sys_rawio", "cap_sys_chroot", "cap_sys_ptrace", "cap_sys_pacct", "cap_sys_admin", "cap_sys_boot", "cap_sys_nice", "cap_sys_resource", "cap_sys_time", "cap_sys_tty_config", "cap_mknod", "cap_lease", "cap_audit_write", "cap_audit_control", "cap_setfcap" }; int getbcap(void) { int comma=0; unsigned long i; int ret; printf("i know of %d capabilities\n", numcaps); printf("capability bounding set:"); for (i=0; i<numcaps; i++) { ret = prctl(PR_CAPBSET_READ, i); if (ret < 0) perror("prctl"); else if (ret==1) printf("%s%s", (comma++) ? ", " : " ", captable[i]); } printf("\n"); return 0; } int capdrop(char *str) { unsigned long i; int found=0; for (i=0; i<numcaps; i++) { if (strcmp(captable[i], str) == 0) { found=1; break; } } if (!found) return 1; if (prctl(PR_CAPBSET_DROP, i)) { perror("prctl"); return 1; } return 0; } int main(int argc, char *argv[]) { if (argc<2) return usage(argv[0]); if (strcmp(argv[1], "get")==0) return getbcap(); if (strcmp(argv[1], "drop")!=0 || argc<3) return usage(argv[0]); if (capdrop(argv[2])) { printf("unknown capability\n"); return 1; } return execl("/bin/bash", "/bin/bash", NULL); } ************************************************************ [serue@us.ibm.com: fix typo] Signed-off-by: Serge E. Hallyn <serue@us.ibm.com> Signed-off-by: Andrew G. Morgan <morgan@kernel.org> Cc: Stephen Smalley <sds@tycho.nsa.gov> Cc: James Morris <jmorris@namei.org> Cc: Chris Wright <chrisw@sous-sol.org> Cc: Casey Schaufler <casey@schaufler-ca.com>a Signed-off-by: "Serge E. Hallyn" <serue@us.ibm.com> Tested-by: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/capability.h')
-rw-r--r--include/linux/capability.h11
1 files changed, 9 insertions, 2 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 */