From df40f9604c78752536de9314f1f03744531d7915 Mon Sep 17 00:00:00 2001 From: Sapan Bhatia Date: Tue, 25 Feb 2014 00:03:55 -0500 Subject: [PATCH] Implemented native capability dropping, eliminated capsh dependency --- lxcsu | 26 +++++--------------------- setns.c | 17 +++++++++++++++++ 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/lxcsu b/lxcsu index d5f26cc..85b1ff7 100755 --- a/lxcsu +++ b/lxcsu @@ -7,8 +7,6 @@ import pdb from argparse import ArgumentParser -drop_capabilities='cap_sys_admin,cap_sys_boot,cap_sys_module' - # can set to True here, but also use the -d option debug = False @@ -232,19 +230,6 @@ def main (): fork_pid = os.fork() - # capsh has a --user option starting with f14 - # so if only for f12 we need to fake this one - # - # capsh.c does essentially the following when invoked with --user: - # pwd = getpwnam(user); ... - # ngroups = MAX_GROUPS; - # status = getgrouplist(user, pwd->pw_gid, groups, &ngroups); ... - # status = setgroups(ngroups, groups); ... - # status = setgid(pwd->pw_gid); ... - # status = setuid(pwd->pw_uid); ... - # however we cannot simulate that ourselves because if we did in this process then - # capsh could not be allowed to mess with caps any more - def getuid (slicename): import pwd try: @@ -253,22 +238,21 @@ def main (): return if (fork_pid == 0): - cap_arg = '--drop='+drop_capabilities - if (not args.root): + setns.drop_caps() if (args.nosliceuid): # we still want to drop capabilities, but don't want to switch UIDs - exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--','--login',]+args.command_to_run + exec_args = [arch,'/bin/sh','--login',]+args.command_to_run else: uid = getuid (slice_name) if not uid: print "lxcsu could not spot %s in /etc/passwd - exiting"%slice_name exit(1) - exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--uid=%s'%uid,'--','--login',]+args.command_to_run + exec_args = [arch,'/bin/sh','--uid=%s'%uid,'--login',]+args.command_to_run # once we can drop f12, it would be nicer to instead go for -# exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--user=%s'%slice_name,'--','--login',]+args.command_to_run +# exec_args = [arch,'/usr/sbin/capsh',cap_arg,'--user=%s'%slice_name,'--login',]+args.command_to_run else: - exec_args = [arch,'/usr/sbin/capsh','--','--login']+args.command_to_run + exec_args = [arch,'/bin/sh','--login']+args.command_to_run os.environ['SHELL'] = '/bin/sh' if os.path.exists('/etc/planetlab/lib/bind_public.so'): diff --git a/setns.c b/setns.c index 36aa360..aa907b0 100644 --- a/setns.c +++ b/setns.c @@ -4,6 +4,22 @@ #include #include #include +#include +#include + +static PyObject * +drop_caps(PyObject *self, PyObject *args) +{ + unsigned int to_drop[128] = {CAP_NET_ADMIN,CAP_SYS_ADMIN,CAP_SYS_BOOT,CAP_MKNOD,CAP_MAC_ADMIN,CAP_SYS_MODULE}; + unsigned int i; + for (i = 0;i<6;i++) { + if (prctl(PR_CAPBSET_DROP, to_drop[i], 0, 0, 0) == -1) { + perror("prctl"); + return Py_BuildValue("i", 2); + } + } + return Py_BuildValue("i", 0); +} static PyObject * proc_mount(PyObject *self, PyObject *args) @@ -78,6 +94,7 @@ static PyMethodDef SetnsMethods[] = {"proc_mount", proc_mount, METH_VARARGS, "Mount a volume via the mount system call."}, {"proc_umount", proc_umount, METH_VARARGS, "Umount a volume via the umount system call."}, {"chcontext", chcontext, METH_VARARGS, "Switch into an lxc container."}, + {"drop_caps", drop_caps, METH_VARARGS, "Drop dangerous capabilities."}, {"chfscontext", chfscontext, METH_VARARGS, "Switch into an lxc container."}, {NULL, NULL, 0, NULL} }; -- 2.43.0