--- /dev/null
+# Copyright 2005 Princeton University
+
+import errno
+import fcntl
+import os
+import re
+
+import linuxcaps
+import passfdimpl
+
+from vserver_vars import *
+
+CAP_SAFE = (linuxcaps.CAP_CHOWN |
+ linuxcaps.CAP_DAC_OVERRIDE |
+ linuxcaps.CAP_DAC_READ_SEARCH |
+ linuxcaps.CAP_FOWNER |
+ linuxcaps.CAP_FSETID |
+ linuxcaps.CAP_KILL |
+ linuxcaps.CAP_SETGID |
+ linuxcaps.CAP_SETUID |
+ linuxcaps.CAP_SETPCAP |
+ linuxcaps.CAP_SYS_TTY_CONFIG |
+ linuxcaps.CAP_LEASE |
+ linuxcaps.CAP_SYS_CHROOT |
+ linuxcaps.CAP_SYS_PTRACE)
+
+#
+# XXX - these are the flags taken from chcontext.c, but they don't match
+# up with those apparently used by the kernel
+#
+FLAGS_LOCK = 1
+FLAGS_SCHED = 2
+FLAGS_NPROC = 4
+FLAGS_PRIVATE = 8
+FLAGS_FAKEINIT = 16
+FLAGS_HIDEINFO = 32
+FLAGS_ULIMIT = 64
+
+
+
+class VServer:
+
+ def __init__(self, name):
+
+ self.name = name
+ self.config = self.__read_config_file("/etc/vservers.conf")
+ self.config.update(self.__read_config_file("/etc/vservers/%s.conf" %
+ self.name))
+ self.flags = 0
+ flags = self.config["S_FLAGS"].split(" ")
+ if "lock" in flags:
+ self.flags |= FLAGS_LOCK
+ if "nproc" in flags:
+ self.flags |= FLAGS_NPROC
+ self.remove_caps = ~CAP_SAFE
+ print "%x %x" % (self.flags, ~self.remove_caps)
+
+ config_var_re = re.compile(r"^ *([A-Z_]+)=(.*)\n?$", re.MULTILINE)
+
+ def __read_config_file(self, filename):
+
+ f = open(filename, "r")
+ data = f.read()
+ f.close()
+ config = {}
+ for m in self.config_var_re.finditer(data):
+ (key, val) = m.groups()
+ config[key] = val.strip('"')
+ return config
+
+ def open(self, filename, mode = "r"):
+
+ (sendsock, recvsock) = passfdimpl.socketpair()
+ child_pid = os.fork()
+ if child_pid == 0:
+ try:
+ # child process
+ os.chroot("%s/%s" % (VROOTDIR, self.name))
+ f = open(filename, mode)
+ passfdimpl.sendmsg(f.fileno(), sendsock)
+ os._exit(0)
+ except EnvironmentError, ex:
+ (result, errmsg) = (ex.errno, ex.strerror)
+ except Exception, ex:
+ (result, errmsg) = (255, str(ex))
+ os.write(sendsock, errmsg)
+ os._exit(result)
+
+ # parent process
+
+ # XXX - need this since a lambda can't raise an exception
+ def __throw(ex):
+ raise ex
+
+ os.close(sendsock)
+ throw = lambda : __throw(Exception(errmsg))
+ while True:
+ try:
+ (pid, status) = os.waitpid(child_pid, 0)
+ if os.WIFEXITED(status):
+ result = os.WEXITSTATUS(status)
+ if result != 255:
+ errmsg = os.strerror(result)
+ throw = lambda : __throw(IOError(result, errmsg))
+ else:
+ errmsg = "unexpected exception in child"
+ else:
+ result = -1
+ errmsg = "child killed"
+ break
+ except OSError, ex:
+ if ex.errno != errno.EINTR:
+ os.close(recvsock)
+ raise ex
+ fcntl.fcntl(recvsock, fcntl.F_SETFL, os.O_NONBLOCK)
+ try:
+ (fd, errmsg) = passfdimpl.recvmsg(recvsock)
+ except OSError, ex:
+ if ex.errno != errno.EAGAIN:
+ throw = lambda : __throw(ex)
+ fd = 0
+ os.close(recvsock)
+ if not fd:
+ throw()
+
+ return os.fdopen(fd)
--- /dev/null
+/* Copyright 2005 Princeton University
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+
+ * Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL PRINCETON
+UNIVERSITY OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
+WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+*/
+
+#include <Python.h>
+
+#include "compat.h"
+#include "vserver.h"
+
+static PyObject *
+vserver_chcontext(PyObject *self, PyObject *args)
+{
+ unsigned xid;
+ unsigned caps_remove = 0;
+
+ if (!PyArg_ParseTuple(args, "I|I", &xid, &caps_remove))
+ return NULL;
+
+ if (vc_new_s_context(xid, caps_remove, 0) < 0)
+ return PyErr_SetFromErrno(PyExc_OSError);
+
+ return Py_None;
+}
+
+static PyMethodDef methods[] = {
+ { "chcontext", vserver_chcontext, METH_VARARGS,
+ "Change to the given vserver context" },
+ { NULL, NULL, 0, NULL }
+};
+
+PyMODINIT_FUNC
+initvserverimpl(void)
+{
+ Py_InitModule("vserverimpl", methods);
+}