add support for bcapabilities
authorDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Mon, 16 Jul 2007 15:21:31 +0000 (15:21 +0000)
committerDaniel Hokka Zakrisson <dhokka@cs.princeton.edu>
Mon, 16 Jul 2007 15:21:31 +0000 (15:21 +0000)
Makefile.in
lib/Makefile-files
lib/planetlab.c
lib/planetlab.h
lib/syscall_getccaps-v21.hc [new file with mode: 0644]
lib/syscall_getccaps.c
python/vserver.py
python/vserverimpl.c

index 7895288..7a927cb 100644 (file)
@@ -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 \
index 70262c7..e6a5acf 100644 (file)
@@ -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 \
index 218f675..902a721 100644 (file)
@@ -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;
index 739bac6..ef6aad4 100644 (file)
@@ -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 (file)
index 0000000..b6ba7ec
--- /dev/null
@@ -0,0 +1,43 @@
+// $Id$    --*- c -*--
+
+// Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+//  
+// 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 <config.h>
+#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;
+}
index 3084c10..661ed70 100644 (file)
 #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
index be76a50..5344cca 100644 (file)
@@ -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)
 
index d16dfa3..5e4d491 100644 (file)
@@ -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 }
 };