From 52a498200c211e6329d5d8a15f1a6942a286952d Mon Sep 17 00:00:00 2001 From: Daniel Hokka Zakrisson Date: Mon, 16 Jul 2007 15:21:31 +0000 Subject: [PATCH] add support for bcapabilities --- Makefile.in | 17 ++++--- lib/Makefile-files | 3 +- lib/planetlab.c | 79 ++++++++++++-------------------- lib/planetlab.h | 1 + lib/syscall_getccaps-v21.hc | 43 ++++++++++++++++++ lib/syscall_getccaps.c | 15 +++++-- python/vserver.py | 15 ++++++- python/vserverimpl.c | 89 ++++++++++++++++++++++++++++++++++++- 8 files changed, 197 insertions(+), 65 deletions(-) create mode 100644 lib/syscall_getccaps-v21.hc diff --git a/Makefile.in b/Makefile.in index 7895288..7a927cb 100644 --- a/Makefile.in +++ b/Makefile.in @@ -291,9 +291,10 @@ am__lib_libvserver_a_SOURCES_DIST = lib/syscall.c lib/checkversion.c \ lib/syscall_setnamespace-v21.hc lib/syscall_ctxmigrate-v21.hc \ lib/syscall_setmapping.c lib/syscall_setmapping-v21.hc \ lib/syscall_schedinfo.c lib/syscall_schedinfo-v21.hc \ - ensc_fmt/fmt-32.c ensc_fmt/fmt-64.c ensc_fmt/fmtx-32.c \ - ensc_fmt/fmtx-64.c ensc_fmt/fmt-tai64n.c ensc_fmt/fmt.h \ - ensc_fmt/fmt.hc ensc_fmt/fmtx.hc ensc_fmt/fmt-internal.h + lib/syscall_getccaps-v21.hc ensc_fmt/fmt-32.c \ + ensc_fmt/fmt-64.c ensc_fmt/fmtx-32.c ensc_fmt/fmtx-64.c \ + ensc_fmt/fmt-tai64n.c ensc_fmt/fmt.h ensc_fmt/fmt.hc \ + ensc_fmt/fmtx.hc ensc_fmt/fmt-internal.h am__dirstamp = $(am__leading_dot)dirstamp am__objects_1 = lib/lib_libvserver_a-getprocentry-legacy.$(OBJEXT) am__objects_2 = lib/lib_libvserver_a-cflags-compat.$(OBJEXT) \ @@ -663,9 +664,10 @@ am__lib_libvserver_la_SOURCES_DIST = lib/syscall.c lib/checkversion.c \ lib/syscall_setnamespace-v21.hc lib/syscall_ctxmigrate-v21.hc \ lib/syscall_setmapping.c lib/syscall_setmapping-v21.hc \ lib/syscall_schedinfo.c lib/syscall_schedinfo-v21.hc \ - ensc_fmt/fmt-32.c ensc_fmt/fmt-64.c ensc_fmt/fmtx-32.c \ - ensc_fmt/fmtx-64.c ensc_fmt/fmt-tai64n.c ensc_fmt/fmt.h \ - ensc_fmt/fmt.hc ensc_fmt/fmtx.hc ensc_fmt/fmt-internal.h + lib/syscall_getccaps-v21.hc ensc_fmt/fmt-32.c \ + ensc_fmt/fmt-64.c ensc_fmt/fmtx-32.c ensc_fmt/fmtx-64.c \ + ensc_fmt/fmt-tai64n.c ensc_fmt/fmt.h ensc_fmt/fmt.hc \ + ensc_fmt/fmtx.hc ensc_fmt/fmt-internal.h am__objects_18 = lib/lib_libvserver_la-getprocentry-legacy.lo am__objects_19 = lib/lib_libvserver_la-cflags-compat.lo \ lib/lib_libvserver_la-cflags_list-compat.lo @@ -1776,7 +1778,8 @@ lib_v21_SRCS = lib/syscall_setccaps-v21.hc \ lib/syscall_setmapping.c \ lib/syscall_setmapping-v21.hc \ lib/syscall_schedinfo.c \ - lib/syscall_schedinfo-v21.hc + lib/syscall_schedinfo-v21.hc \ + lib/syscall_getccaps-v21.hc PKGCONFIG_FILES = lib/util-vserver lib_SRCS = lib/syscall.c \ diff --git a/lib/Makefile-files b/lib/Makefile-files index 70262c7..e6a5acf 100644 --- a/lib/Makefile-files +++ b/lib/Makefile-files @@ -130,7 +130,8 @@ lib_v21_SRCS = lib/syscall_setccaps-v21.hc \ lib/syscall_setmapping.c \ lib/syscall_setmapping-v21.hc \ lib/syscall_schedinfo.c \ - lib/syscall_schedinfo-v21.hc + lib/syscall_schedinfo-v21.hc \ + lib/syscall_getccaps-v21.hc if ENSC_HAVE_C99_COMPILER lib_v13_SRCS += lib/syscall_adddlimit-v13.hc \ diff --git a/lib/planetlab.c b/lib/planetlab.c index 218f675..902a721 100644 --- a/lib/planetlab.c +++ b/lib/planetlab.c @@ -195,7 +195,7 @@ pl_setsched(xid_t ctx, uint32_t cpu_share, uint32_t cpu_sched_flags) vc_sched.tokens_min = 50; /* need this many tokens to run */ vc_sched.tokens_max = 100; /* max accumulated number of tokens */ - if (cpu_share == VC_LIM_KEEP) + if (cpu_share == (uint32_t)VC_LIM_KEEP) vc_sched.set_mask &= ~(VC_VXSM_FILL_RATE|VC_VXSM_FILL_RATE2); /* guaranteed CPU corresponds to SCHED_SHARE flag being cleared */ @@ -254,6 +254,8 @@ pl_get_limits(char *context, struct sliver_resources *slr) {"rlimits/openfd.min", &slr->vs_openfd.min}, {"whitelisted", &slr->vs_whitelisted}, + + {"bcapabilities", NULL}, {0,0} }; @@ -281,6 +283,11 @@ pl_get_limits(char *context, struct sliver_resources *slr) slr->vs_whitelisted = 1; + slr->vs_capabilities.bcaps = 0; + slr->vs_capabilities.bmask = 0; + slr->vs_capabilities.ccaps = 0; + slr->vs_capabilities.cmask = 0; + cwd = open(".", O_RDONLY); if (cwd == -1) { perror("cannot get a handle on ."); @@ -297,9 +304,21 @@ pl_get_limits(char *context, struct sliver_resources *slr) fb = fopen(r->name, "r"); if (fb == NULL) continue; - if (fgets(buf, sizeof(buf), fb) != NULL && isdigit(*buf)) { - *r->limit = atoi(buf); + /* XXX: UGLY. */ + if (strcmp(r->name, "bcapabilities") == 0) { + size_t len, i; + struct vc_err_listparser err; + + len = fread(buf, 1, sizeof(buf), fb); + for (i = 0; i < len; i++) { + if (buf[i] == '\n') + buf[i] = ','; + } + vc_list2bcap(buf, len, &err, &slr->vs_capabilities); } + else + if (fgets(buf, sizeof(buf), fb) != NULL && isdigit(*buf)) + *r->limit = atoi(buf); fclose(fb); } @@ -307,53 +326,6 @@ pl_get_limits(char *context, struct sliver_resources *slr) out_fd: close(cwd); out: -#if 0 - /* open the conf file for reading */ - fb = fopen(conf,"r"); - if (fb != NULL) { - size_t index; - char *buffer = malloc(1000); - char *p; - - /* the conf file exist */ - while((p=fgets(buffer,1000-1,fb))!=NULL) { - index = 0; - len = strnlen(buffer,1000); - WHITESPACE(buffer,index,len); - if (buffer[index] == '#') - continue; - - for (r=&sliver_list[0]; r->name; r++) - if ((p=strstr(&buffer[index],r->name))!=NULL) { - /* adjust index into buffer */ - index+= (p-&buffer[index])+strlen(r->name); - - /* skip over whitespace */ - WHITESPACE(buffer,index,len); - - /* expecting to see = sign */ - if (buffer[index++]!='=') goto out; - - /* skip over whitespace */ - WHITESPACE(buffer,index,len); - - /* expecting to see a digit for number */ - if (!isdigit((int)buffer[index])) goto out; - - *r->limit = atoi(&buffer[index]); - if (0) /* for debugging only */ - fprintf(stderr,"pl_get_limits found %s=%lld\n", - r->name,*r->limit); - break; - } - } - out: - fclose(fb); - free(buffer); - } else { - fprintf(stderr,"cannot open %s\n",conf); - } -#endif free(conf); } @@ -396,7 +368,6 @@ adjust_lim(struct vc_rlimit *vcr, struct rlimit *lim) return adjusted; } - void pl_set_limits(xid_t ctx, struct sliver_resources *slr) { @@ -454,6 +425,12 @@ pl_set_limits(xid_t ctx, struct sliver_resources *slr) } vs_cpu = slr->vs_cpu; cpu_sched_flags = slr->vs_cpuguaranteed & VS_SCHED_CPU_GUARANTEED; + + slr->vs_capabilities.bmask = vc_get_insecurebcaps(); + if (vc_set_ccaps(ctx, &slr->vs_capabilities) < 0) { + PERROR("pl_setcaps(%u)", ctx); + exit(1); + } } else { vs_cpu = 1; cpu_sched_flags = 0; diff --git a/lib/planetlab.h b/lib/planetlab.h index 739bac6..ef6aad4 100644 --- a/lib/planetlab.h +++ b/lib/planetlab.h @@ -44,6 +44,7 @@ struct sliver_resources { struct vc_rlimit vs_nproc; struct vc_rlimit vs_openfd; unsigned long long vs_whitelisted; + struct vc_ctx_caps vs_capabilities; }; int adjust_lim(struct vc_rlimit *vcr, struct rlimit *lim); diff --git a/lib/syscall_getccaps-v21.hc b/lib/syscall_getccaps-v21.hc new file mode 100644 index 0000000..b6ba7ec --- /dev/null +++ b/lib/syscall_getccaps-v21.hc @@ -0,0 +1,43 @@ +// $Id$ --*- c -*-- + +// Copyright (C) 2004 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif + +static inline ALWAYSINLINE int +vc_get_ccaps_v21(xid_t xid, struct vc_ctx_caps *caps) +{ + struct vcmd_ctx_caps_v1 k_ccaps; + struct vcmd_bcaps k_bcaps; + int res; + + res = vserver(VCMD_get_ccaps, CTX_USER2KERNEL(xid), &k_ccaps); + if (res) + return res; + res = vserver(VCMD_get_bcaps, CTX_USER2KERNEL(xid), &k_bcaps); + if (res) + return res; + + caps->bcaps = k_bcaps.bcaps; + caps->bmask = k_bcaps.bmask; + caps->ccaps = k_ccaps.ccaps; + caps->cmask = k_ccaps.cmask; + + return res; +} diff --git a/lib/syscall_getccaps.c b/lib/syscall_getccaps.c index 3084c10..661ed70 100644 --- a/lib/syscall_getccaps.c +++ b/lib/syscall_getccaps.c @@ -21,14 +21,22 @@ #endif #include "vserver.h" -#include "vserver-internal.h" #include "virtual.h" +#if defined(VC_ENABLE_API_V13) && defined(VC_ENABLE_API_V21) +# define VC_MULTIVERSION_SYSCALL 1 +#endif +#include "vserver-internal.h" + #if defined(VC_ENABLE_API_V13) # include "syscall_getccaps-v13.hc" #endif -#if defined(VC_ENABLE_API_V13) +#if defined(VC_ENABLE_API_V21) +# include "syscall_getccaps-v21.hc" +#endif + +#if defined(VC_ENABLE_API_V13) || defined(VC_ENABLE_API_V21) int vc_get_ccaps(xid_t xid, struct vc_ctx_caps *caps) { @@ -37,6 +45,7 @@ vc_get_ccaps(xid_t xid, struct vc_ctx_caps *caps) return -1; } - CALL_VC(CALL_VC_V13A(vc_get_ccaps, xid, caps)); + CALL_VC(CALL_VC_V21(vc_get_ccaps, xid, caps), + CALL_VC_V13A(vc_get_ccaps, xid, caps)); } #endif diff --git a/python/vserver.py b/python/vserver.py index be76a50..5344cca 100644 --- a/python/vserver.py +++ b/python/vserver.py @@ -177,6 +177,19 @@ class VServer: def set_WHITELISTED_config(self,whitelisted): self.config.update('whitelisted', whitelisted) + def set_capabilities(self, capabilities): + return vserverimpl.setbcaps(self.ctx, vserverimpl.text2bcaps(capabilities)) + + def set_capabilities_config(self, capabilities): + self.config.update('bcapabilities', capabilities) + self.set_capabilities(capabilities) + + def get_capabilities(self): + return vserverimpl.bcaps2text(vserverimpl.getbcaps(self.ctx)) + + def get_capabilities_config(self): + return self.config.get('bcapabilities') + def __do_chroot(self): os.chroot(self.dir) @@ -299,7 +312,7 @@ class VServer: print >>state_file, "%u" % self.ctx state_file.close() - if vserverimpl.chcontext(self.ctx): + if vserverimpl.chcontext(self.ctx, vserverimpl.text2bcaps(self.get_capabilities_config())): self.set_resources() vserverimpl.setup_done(self.ctx) diff --git a/python/vserverimpl.c b/python/vserverimpl.c index d16dfa3..5e4d491 100644 --- a/python/vserverimpl.c +++ b/python/vserverimpl.c @@ -57,10 +57,11 @@ vserver_chcontext(PyObject *self, PyObject *args) { int ctx_is_new; xid_t ctx; - uint_least64_t bcaps = ~vc_get_insecurebcaps(); + uint_least64_t bcaps = 0; - if (!PyArg_ParseTuple(args, "I", &ctx)) + if (!PyArg_ParseTuple(args, "I|K", &ctx, &bcaps)) return NULL; + bcaps |= ~vc_get_insecurebcaps(); if ((ctx_is_new = pl_chcontext(ctx, bcaps, 0)) < 0) return PyErr_SetFromErrno(PyExc_OSError); @@ -278,6 +279,82 @@ vserver_killall(PyObject *self, PyObject *args) return NONE; } +static PyObject * +vserver_set_bcaps(PyObject *self, PyObject *args) +{ + xid_t ctx; + struct vc_ctx_caps caps; + + if (!PyArg_ParseTuple(args, "IK", &ctx, &caps.bcaps)) + return NULL; + + caps.bmask = vc_get_insecurebcaps(); + caps.cmask = caps.ccaps = 0; + if (vc_set_ccaps(ctx, &caps) == -1 && errno != ESRCH) + return PyErr_SetFromErrno(PyExc_OSError); + + return NONE; +} + +static PyObject * +vserver_text2bcaps(PyObject *self, PyObject *args) +{ + struct vc_ctx_caps caps = { .bcaps = 0 }; + const char *list; + int len; + struct vc_err_listparser err; + + if (!PyArg_ParseTuple(args, "s#", &list, &len)) + return NULL; + + if (vc_list2bcap(list, len, &err, &caps) == -1) + return NULL; + + return Py_BuildValue("K", caps.bcaps); +} + +static PyObject * +vserver_get_bcaps(PyObject *self, PyObject *args) +{ + xid_t ctx; + struct vc_ctx_caps caps; + + if (!PyArg_ParseTuple(args, "I", &ctx)) + return NULL; + + if (vc_get_ccaps(ctx, &caps) == -1) { + if (errno != -ESRCH) + return PyErr_SetFromErrno(PyExc_OSError); + else + caps.bcaps = 0; + } + + return Py_BuildValue("K", caps.bcaps & vc_get_insecurebcaps()); +} + +static PyObject * +vserver_bcaps2text(PyObject *self, PyObject *args) +{ + struct vc_ctx_caps caps = { .bcaps = 0 }; + PyObject *list; + const char *cap; + + if (!PyArg_ParseTuple(args, "K", &caps.bcaps)) + return NULL; + + list = PyString_FromString(""); + + while ((cap = vc_lobcap2text(&caps.bcaps)) != NULL) { + if (list == NULL) + break; + PyString_ConcatAndDel(&list, PyString_FromFormat( + (PyString_Size(list) > 0 ? ",CAP_%s" : "CAP_%s" ), + cap)); + } + + return list; +} + static PyMethodDef methods[] = { { "chcontext", vserver_chcontext, METH_VARARGS, "chcontext to vserver with provided flags" }, @@ -299,6 +376,14 @@ static PyMethodDef methods[] = { "Send signal to all processes in vserver context" }, { "isrunning", vserver_isrunning, METH_VARARGS, "Check if vserver is running"}, + { "setbcaps", vserver_set_bcaps, METH_VARARGS, + "Set POSIX capabilities of a vserver context" }, + { "getbcaps", vserver_get_bcaps, METH_VARARGS, + "Get POSIX capabilities of a vserver context" }, + { "text2bcaps", vserver_text2bcaps, METH_VARARGS, + "Translate a string of capabilities to a bitmap" }, + { "bcaps2text", vserver_bcaps2text, METH_VARARGS, + "Translate a capability-bitmap into a string" }, { NULL, NULL, 0, NULL } }; -- 2.43.0