linux/kernel
Serge E. Hallyn 3b7391de67 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>
2008-02-05 09:44:20 -08:00
..
irq genirq: stackdump after the "Trying to free already-free IRQ" message 2008-01-30 13:33:24 +01:00
power Page allocator: clean up pcp draining functions 2008-02-05 09:44:17 -08:00
time tick-sched: add more debug information 2008-02-01 17:45:14 +01:00
.gitignore
Kconfig.hz sched: high-res preemption tick 2008-01-25 21:08:29 +01:00
Kconfig.preempt sched: remove the !PREEMPT_BKL code 2008-01-25 21:08:33 +01:00
Makefile kobject: Always build in kernel/ksysfs.o. 2008-02-02 15:14:46 -08:00
acct.c acct: real_parent ppid 2008-01-07 14:55:37 -08:00
audit.c [AUDIT] ratelimit printk messages audit 2008-02-01 14:25:04 -05:00
audit.h [PATCH] audit: watching subtrees 2007-10-21 02:37:45 -04:00
audit_tree.c [PATCH] audit: watching subtrees 2007-10-21 02:37:45 -04:00
auditfilter.c [AUDIT] make audit=0 really stop audit messages 2008-02-01 14:24:33 -05:00
auditsc.c [AUDIT] create context if auditing was ever enabled 2008-02-01 14:24:45 -05:00
backtracetest.c x86: add a simple backtrace test module 2008-01-30 13:33:08 +01:00
capability.c Add 64-bit capability support to the kernel 2008-02-05 09:44:20 -08:00
cgroup.c Improve cgroup printks 2007-11-14 18:45:37 -08:00
cgroup_debug.c Task Control Groups: simple task cgroup debug info subsystem 2007-10-19 11:53:36 -07:00
compat.c Merge ssh://master.kernel.org/pub/scm/linux/kernel/git/tglx/linux-2.6-hrt 2007-10-18 15:12:41 -07:00
configs.c
cpu.c cpu-hotplug: replace per-subsystem mutexes with get_online_cpus() 2008-01-25 21:08:02 +01:00
cpuset.c cpu-hotplug: replace lock_cpu_hotplug() with get_online_cpus() 2008-01-25 21:08:02 +01:00
delayacct.c Add scaled time to taskstats based process accounting 2007-10-18 14:37:28 -07:00
dma.c whitespace fixes: DMA channel allocator 2007-10-18 14:37:24 -07:00
exec_domain.c whitespace fixes: execution domains 2007-10-18 14:37:26 -07:00
exit.c exec: rework the group exit and fix the race with kill 2008-02-05 09:44:07 -08:00
extable.c module: Don't report discarded init pages as kernel text. 2008-01-29 17:13:18 +11:00
fork.c capabilities: introduce per-process capability bounding set 2008-02-05 09:44:20 -08:00
futex.c futex: Add bitset conditional wait/wakeup functionality 2008-02-01 17:45:14 +01:00
futex_compat.c futex: Add bitset conditional wait/wakeup functionality 2008-02-01 17:45:14 +01:00
hrtimer.c timerfd: new timerfd API 2008-02-05 09:44:07 -08:00
itimer.c whitespace fixes: interval timers 2007-10-18 14:37:26 -07:00
kallsyms.c module: make module_address_lookup safe 2008-01-29 17:13:23 +11:00
kexec.c vmcoreinfo: add the array length of "free_list" for filtering free pages 2008-01-08 16:10:36 -08:00
kfifo.c
kmod.c Fix unbalanced helper_lock in kernel/kmod.c 2008-01-17 15:38:59 -08:00
kprobes.c x86: kprobes: add kprobes smoke tests that run on boot 2008-01-30 13:32:53 +01:00
ksysfs.c Kobject: convert remaining kobject_unregister() to kobject_put() 2008-01-24 20:40:40 -08:00
kthread.c sched: fix, always create kernel threads with normal priority 2008-01-25 21:08:33 +01:00
latency.c
latencytop.c sched: latencytop support 2008-01-25 21:08:34 +01:00
lockdep.c softlockup: automatically detect hung TASK_UNINTERRUPTIBLE tasks 2008-01-25 21:08:02 +01:00
lockdep_internals.h
lockdep_proc.c
marker.c Linux Kernel Markers: fix marker mutex not taken upon module load 2007-11-14 18:45:40 -08:00
module.c x86/non-x86: percpu, node ids, apic ids x86.git fixup 2008-01-30 13:33:32 +01:00
mutex-debug.c
mutex-debug.h
mutex.c Add mutex_lock_killable 2007-12-06 17:37:59 -05:00
mutex.h
notifier.c Add kernel/notifier.c 2007-10-19 11:53:34 -07:00
ns_cgroup.c cgroups: implement namespace tracking subsystem 2007-10-19 11:53:37 -07:00
nsproxy.c pid namespaces: allow cloning of new namespace 2007-10-19 11:53:39 -07:00
panic.c debug: add the end-of-trace marker and the module list to 2008-01-30 13:32:50 +01:00
params.c module: fix the module name length in param_sysfs_builtin 2008-01-29 17:13:24 +11:00
pid.c pidns: Place under CONFIG_EXPERIMENTAL 2007-11-14 18:45:43 -08:00
posix-cpu-timers.c sched: rt-watchdog: fix .rlim_max = RLIM_INFINITY 2008-01-25 21:08:32 +01:00
posix-timers.c timerfd: new timerfd API 2008-02-05 09:44:07 -08:00
printk.c debug: turn ignore_loglevel into an early param 2008-01-31 22:45:23 +01:00
profile.c debug: clean up kernel/profile.c 2008-01-25 21:08:33 +01:00
ptrace.c Merge branch 'task_killable' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc 2008-02-01 11:45:47 +11:00
rcuclassic.c Preempt-RCU: implementation 2008-01-25 21:08:24 +01:00
rcupdate.c Preempt-RCU: fix rcu_barrier for preemptive environment. 2008-01-25 21:08:24 +01:00
rcupreempt.c Preempt-RCU: CPU Hotplug handling 2008-01-25 21:08:25 +01:00
rcupreempt_trace.c Preempt-RCU: implementation 2008-01-25 21:08:24 +01:00
rcutorture.c cpu-hotplug: replace lock_cpu_hotplug() with get_online_cpus() 2008-01-25 21:08:02 +01:00
relay.c vm audit: add VM_DONTEXPAND to mmap for drivers that need it 2008-02-04 07:55:38 -08:00
resource.c Add IORESOUCE_BUSY flag for System RAM 2007-11-14 18:45:39 -08:00
rtmutex-debug.c Use helpers to obtain task pid in printks 2007-10-19 11:53:43 -07:00
rtmutex-debug.h
rtmutex-tester.c Driver core: change sysdev classes to use dynamic kobject names 2008-01-24 20:40:40 -08:00
rtmutex.c Use helpers to obtain task pid in printks 2007-10-19 11:53:43 -07:00
rtmutex.h
rtmutex_common.h
rwsem.c sched: mark rwsem functions as __sched for wchan/profiling 2007-12-18 15:21:13 +01:00
sched.c Merge branch 'task_killable' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc 2008-02-01 11:45:47 +11:00
sched_debug.c sched: keep total / count stats in addition to the max for 2008-01-25 21:08:35 +01:00
sched_fair.c sched: let +nice tasks have smaller impact 2008-01-31 22:45:22 +01:00
sched_idletask.c sched: high-res preemption tick 2008-01-25 21:08:29 +01:00
sched_rt.c sched: fix goto retry in pick_next_task_rt() 2008-01-25 21:08:34 +01:00
sched_stats.h sched: clean up kernel/sched_stat.h 2007-11-28 15:52:56 +01:00
seccomp.c
signal.c exec: rework the group exit and fix the race with kill 2008-02-05 09:44:07 -08:00
softirq.c time: track accurate idle time with tick_sched.idle_sleeptime 2008-01-30 13:30:04 +01:00
softlockup.c debug: softlockup looping fix 2008-02-02 14:27:45 +11:00
spinlock.c spinlock: lockbreak cleanup 2008-01-30 13:31:20 +01:00
srcu.c
stacktrace.c
stop_machine.c cpu-hotplug: replace lock_cpu_hotplug() with get_online_cpus() 2008-01-25 21:08:02 +01:00
sys.c capabilities: introduce per-process capability bounding set 2008-02-05 09:44:20 -08:00
sys_ni.c timerfd: new timerfd API 2008-02-05 09:44:07 -08:00
sysctl.c capabilities: introduce per-process capability bounding set 2008-02-05 09:44:20 -08:00
sysctl_check.c capabilities: introduce per-process capability bounding set 2008-02-05 09:44:20 -08:00
taskstats.c kernel/taskstats.c: fix bogus nlmsg_free() 2007-11-14 18:45:44 -08:00
test_kprobes.c x86: kprobes: add kprobes smoke tests that run on boot 2008-01-30 13:32:53 +01:00
time.c timekeeping: update xtime_cache when time(zone) changes 2008-02-01 17:45:13 +01:00
timer.c Merge branch 'task_killable' of git://git.kernel.org/pub/scm/linux/kernel/git/willy/misc 2008-02-01 11:45:47 +11:00
tsacct.c Add scaled time to taskstats based process accounting 2007-10-18 14:37:28 -07:00
uid16.c
user.c uids: merge multiple error paths in alloc_uid() into one 2008-01-25 21:08:26 +01:00
user_namespace.c
utsname.c
utsname_sysctl.c Isolate the UTS namespace's domainname and hostname back 2007-11-29 09:24:53 -08:00
wait.c wait: Use TASK_NORMAL 2007-12-06 17:34:36 -05:00
workqueue.c cpu-hotplug: replace per-subsystem mutexes with get_online_cpus() 2008-01-25 21:08:02 +01:00