--- /dev/null
+.X_usr_local_etc-up-to-date
+.deps
+COPYING
+ChangeLog
+INSTALL
+aclocal.m4
+autom4te.cache
+compile
+config.h
+config.h.in
+config.log
+config.status
+depcomp
+install-sh
+missing
+mkinstalldirs
+stamp-h1
+stamp-h2
+util-vserver-*.tar.bz2*
+util-vserver-*.tar.gz
+vserver.spec
+vserverx-*.tar.*
--- /dev/null
+Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
--- /dev/null
+## $Id$
+
+# Copyright (C) 2003 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+#
+
+ACLOCAL_AMFLAGS = -I m4
+
+sysvdir = $(sysconfdir)/init.d
+vservercfgdir = $(sysconfdir)/vservers
+
+include_HEADERS = $(lib_HDRS)
+noinst_HEADERS = $(src_HDRS)
+
+lib_LIBRARIES = $(lib_lib_LIBS)
+
+pkglib_SCRIPTS = $(distrib_SCRPTS) $(scripts_SCRPTS)
+pkglib_DATA = $(distrib_DAT) $(scriptscfg_DATA)
+pkglib_PROGRAMS = $(src_pkglib_PRGS)
+
+sbin_SCRIPTS = $(scripts_PRGS)
+sbin_PROGRAMS = $(src_sbin_PRGS)
+noinst_PROGRAMS = $(test_PRGS)
+
+sysv_SCRIPTS = $(sysv_SCRPTS)
+sysconf_DATA = $(sysv_CFG)
+vservercfg_DATA = newvserver.defaults
+
+BUILT_SOURCES = linuxcaps.h
+
+man_MANS = $(man_DATMAN)
+
+EXTRA_DIST = $(distrib_SCRPTS) $(distrib_DAT) \
+ $(sysv_XTRAS) $(sysv_CFG) \
+ $(doc_DAT) $(man_DATMAN) \
+ $(scripts_SCRPTS) $(scripts_PRGS) $(scripts_XTRAS) \
+ vserver.spec newvserver.defaults \
+ m4/ensc_cflags.m4 \
+ THANKS
+
+AM_CPPFLAGS = -I $(top_srcdir)/lib -D VERSION=\"$(VERSION)\" -D PKGLIBDIR=\"$(pkglibdir)\" -D _GNU_SOURCE
+AM_CFLAGS = -Wall -pedantic
+
+CLEANFILES = $(sysv_GENSCRPTS) $(scripts_GENSCRPTS) linuxcaps.h
+
+
+linuxcaps.h:
+ ln -sf ${kernelincludedir}/linux/capability.h linuxcaps.h
+
+
+include $(top_srcdir)/lib/Makefile-files
+include $(top_srcdir)/src/Makefile-files
+include $(top_srcdir)/distrib/Makefile-files
+include $(top_srcdir)/doc/Makefile-files
+include $(top_srcdir)/man/Makefile-files
+include $(top_srcdir)/scripts/Makefile-files
+include $(top_srcdir)/tests/Makefile-files
+include $(top_srcdir)/sysv/Makefile-files
+
+include $(top_srcdir)/m4/gpgsig.am
+include $(top_srcdir)/m4/validate.am
+include $(top_srcdir)/m4/changelog.am
--- /dev/null
+I want to thank
+
+Jacques Gelinas <jack@solucorp.qc.ca>,
+ who wrote and maintains the 'vserver' package on which util-vserver
+ is based on
+
+all the other people, who contributed to the original 'vserver' package
--- /dev/null
+dnl $Id$
+
+dnl Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 2, or (at your option)
+dnl any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+dnl
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+dnl
+
+AC_PREREQ(2.57)
+AC_INIT(util-vserver, 0.23.5, enrico.scholz@informatik.tu-chemnitz.de)
+AC_CONFIG_SRCDIR([src/capchroot.c])
+AC_CONFIG_HEADER([config.h])
+
+AM_INIT_AUTOMAKE([gnu dist-bzip2 subdir-objects])
+AM_MAINTAINER_MODE
+
+
+# Checks for programs.
+AC_PROG_CXX
+AC_PROG_CC
+AC_PROG_INSTALL
+AC_PROG_LN_S
+AC_PROG_RANLIB
+AM_PROG_CC_C_O
+
+ENSC_CHECK_CC_FLAG([-std=c99])
+
+AC_ARG_VAR(CC, [The C compiler])
+AC_MSG_CHECKING([for linux kernel headers])
+AC_ARG_WITH([kerneldir],
+ [AC_HELP_STRING([--with-kerneldir=DIR],
+ [assume top-kernelsources in DIR (default: /lib/modules/<current>/build)])],
+ [case "$withval" in
+ yes|no) AC_MSG_ERROR(['$withval' is not a valid value for kerneldir]);;
+ *) kerneldir=$withval;;
+ esac],
+ [kerneldir=
+ for i in /lib/modules/$(uname -r)/build /usr/src/linux /usr; do
+ test -e $i/include/linux/version.h && { kerneldir=$i; break; }
+ done])
+
+test "$kerneldir" -a -e $i/include/linux/version.h || {
+ AC_MSG_ERROR([Can not find kernelsources])
+}
+
+kernelincludedir=$kerneldir/include
+AC_SUBST(kernelincludedir)
+AC_MSG_RESULT($kernelincludedir/linux)
+
+
+AC_CONFIG_FILES([vserver.spec Makefile])
+AC_OUTPUT
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+
+distrib_SCRPTS = distrib/install-mdk8.2 \
+ distrib/install-post.sh \
+ distrib/install-pre.sh \
+ distrib/install-rh7.2 \
+ distrib/install-rh7.3 \
+ distrib/install-rh8.0 \
+ distrib/install-rh9.0 \
+ distrib/sample.sh
+
+distrib_DAT = distrib/mdk8.2-minimum \
+ distrib/rh7.3-minimum \
+ distrib/rh8.0-minimum \
+ distrib/rh9.0-minimum \
+ distrib/sample.conf
+
--- /dev/null
+#!/bin/sh
+# $Id$ --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on install-mdk8.2 by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+
+# This script creates a vserver from Mandrake 8.2 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-mdk8.2 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+ echo install-mdk8.2 vserver-id [ type ]
+ echo type minimum means, minimum package for a server
+ echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+ echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/Mandrake/RPMS ] ; then
+ echo No rpms in /mnt/cdrom/Mandrake/RPMS. Is the CD mounted \?
+else
+ VROOT=/vservers/$1
+ $USR_LIB_VSERVER/install-pre.sh $1
+ mkdir -p $VROOT/proc
+ mount -t proc none $VROOT/proc
+ mkdir -p $VROOT/var/lib/rpm
+ rpm --root $VROOT --initdb
+ if [ "$2" = "minimum" ] ; then
+ echo `cat $USR_LIB_VSERVER/mdk8.2-minimum | wc -l` packages to install
+ cd /mnt/cdrom/Mandrake/RPMS
+ rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/mdk8.2-minimum`
+ else
+ PKGS=`ls /mnt/cdrom/Mandrake/RPMS/*.i586.rpm | grep -v LPRng- \
+ | grep -v lpr-`
+
+ echo `(ls /mnt/cdrom/Mandrake/RPMS/*.noarch.rpm \
+ ;echo $PKGS) | wc -w` packages to install
+ rpm --root $VROOT -Uvh \
+ /mnt/cdrom/Mandrake/RPMS/*.noarch.rpm \
+ $PKGS --nodeps
+ fi
+ $USR_LIB_VSERVER/install-post.sh $1
+ umount $VROOT/proc
+fi
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-post by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Complete the installation of a vserver
+USR_LIB_VSERVER=$(dirname $0)
+vserver_mknod()
+{
+ mknod $1 $2 $3 $4
+ chmod $5 $1
+}
+
+if [ $# != 1 ] ; then
+ echo install-post.sh vserver
+else
+ VROOT=/vservers/$1
+ rm -fr $VROOT/dev
+ mkdir $VROOT/dev && chmod 755 $VROOT/dev
+ mkdir $VROOT/dev/pts
+ vserver_mknod $VROOT/dev/null c 1 3 666
+ vserver_mknod $VROOT/dev/zero c 1 5 666
+ vserver_mknod $VROOT/dev/full c 1 7 666
+ vserver_mknod $VROOT/dev/random c 1 8 644
+ vserver_mknod $VROOT/dev/urandom c 1 9 644
+ vserver_mknod $VROOT/dev/tty c 5 0 666
+ vserver_mknod $VROOT/dev/ptmx c 5 2 666
+ test -f /etc/vservers/$1.conf || cp $USR_LIB_VSERVER/sample.conf /etc/vservers/$1.conf
+ test -f /etc/vservers/$1.sh || cp $USR_LIB_VSERVER/sample.sh /etc/vservers/$1.sh
+ echo NETWORKING=yes >$VROOT/etc/sysconfig/network
+ echo HOSTNAME=$1 >>$VROOT/etc/sysconfig/network
+ (
+ cd $VROOT/etc/rc.d/init.d || cd $VROOT/etc/init.d
+ for serv in *
+ do
+ case $serv in
+ *.bak|*~|functions|killall|halt|single)
+ ;;
+ *)
+ $USR_LIB_VSERVER/capchroot /vservers/$1 /sbin/chkconfig --level 2345 $serv off
+ ;;
+ esac
+ done
+ rm -f $VROOT/etc/rc.d/rc6.d/S*reboot
+ )
+ if [ ! -f $VROOT/etc/fstab ] ; then
+ echo /dev/hdv1 / ext2 defaults 1 1 >$VROOT/etc/fstab
+ echo /dev/hdv1 / ext2 rw 1 1 >$VROOT/etc/mtab
+ fi
+ cp -a $USR_LIB_VSERVER/vreboot $VROOT/sbin/.
+ ln -sf vreboot $VROOT/sbin/vhalt
+ if [ -x /etc/vservers/install-post.sh ]; then
+ /etc/vservers/install-post.sh $VROOT
+ fi
+fi
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-pre by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+vserver_mknod()
+{
+ mknod $1 $2 $3 $4
+ chmod $5 $1
+}
+
+if [ $# != 1 ] ; then
+ echo install-pre.sh vserver
+else
+ mkdir -p /etc/vservers
+ mkdir -p /vservers 2>/dev/null
+ VROOT=/vservers/$1
+ rm -fr $VROOT/dev
+ mkdir -p $VROOT/dev && chmod 755 $VROOT/dev
+ mkdir $VROOT/dev/pts
+ vserver_mknod $VROOT/dev/null c 1 3 666
+ vserver_mknod $VROOT/dev/zero c 1 5 666
+ vserver_mknod $VROOT/dev/full c 1 7 666
+ vserver_mknod $VROOT/dev/random c 1 8 644
+ vserver_mknod $VROOT/dev/urandom c 1 9 644
+ vserver_mknod $VROOT/dev/tty c 5 0 666
+ vserver_mknod $VROOT/dev/ptmx c 5 2 666
+ # We fake this device to help some package managers
+ touch $VROOT/dev/hdv1
+fi
+
--- /dev/null
+#!/bin/sh
+# $Id$ --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh7.2 by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This script creates a vserver from RedHat 7.2 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh7.2 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# != 1 ] ; then
+ echo install-rh7.2 vserver-id
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+ echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+ echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+ echo `ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+ /mnt/cdrom/RedHat/RPMS/*.i386.rpm | wc -l` packages to install
+ VROOT=/vservers/$1
+ mkdir -p $VROOT/proc
+ mount -t proc none $VROOT/proc
+ mkdir -p $VROOT/var/lib/rpm
+ rpm --root $VROOT --initdb
+ rpm --root $VROOT -Uvh \
+ /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+ /mnt/cdrom/RedHat/RPMS/*.i386.rpm
+ $USR_LIB_VSERVER/install-post.sh $1
+ umount $VROOT/proc
+fi
+
+
--- /dev/null
+#!/bin/sh
+# $Id$ --*- sh -*--
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh7.3 by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This script creates a vserver from RedHat 7.3 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh7.3 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+ echo install-rh7.3 vserver-id [ type ]
+ echo type minimum means, minimum package for a server
+ echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+ echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+ echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+ VROOT=/vservers/$1
+ mkdir -p $VROOT/proc
+ mount -t proc none $VROOT/proc
+ mkdir -p $VROOT/var/lib/rpm
+ rpm --root $VROOT --initdb
+ if [ "$2" = "minimum" ] ; then
+ echo `cat $USR_LIB_VSERVER/rh7.3-minimum | wc -l` packages to install
+ cd /mnt/cdrom/RedHat/RPMS
+ rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/rh7.3-minimum`
+ else
+ echo `ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+ /mnt/cdrom/RedHat/RPMS/*.i386.rpm | wc -l` packages to install
+ rpm --root $VROOT -Uvh \
+ /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+ /mnt/cdrom/RedHat/RPMS/*.i386.rpm --nodeps
+ fi
+ $USR_LIB_VSERVER/install-post.sh $1
+ umount $VROOT/proc
+fi
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh8.0 by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This script creates a vserver from RedHat 8.0 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh8.0 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+ echo install-rh8.0 vserver-id [ type ]
+ echo type minimum means, minimum package for a server
+ echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+ echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+ echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+ VROOT=/vservers/$1
+ $USR_LIB_VSERVER/install-pre.sh $1
+ mkdir -p $VROOT/proc
+ mount -t proc none $VROOT/proc
+ mount -t devpts none $VROOT/dev/pts
+ mkdir -p $VROOT/var/lib/rpm
+ rpm --root $VROOT --initdb
+ if [ "$2" = "minimum" ] ; then
+ echo `cat $USR_LIB_VSERVER/rh8.0-minimum | wc -l` packages to install
+ cd /mnt/cdrom/RedHat/RPMS
+ rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/rh8.0-minimum`
+ else
+ PKGS=`ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+ /mnt/cdrom/RedHat/RPMS/*.i386.rpm`
+ for except in control-center iptables kernel-pcmcia-cs\
+ nfs-utils pciutils quota rp-pppoe tcpdump \
+ lokkit kudzu-devel pciutils-devel
+ do
+ PKGS=`ls $PKGS | grep -v $except`
+ done
+ echo `echo $PKGS | wc -w` packages to install
+ rpm --root $VROOT -Uvh $PKGS
+ fi
+ umount $VROOT/proc
+ umount $VROOT/dev/pts
+ $USR_LIB_VSERVER/install-post.sh $1
+fi
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib/install-rh9.0 by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This script creates a vserver from RedHat 9.0 CD. Only
+# the first CD is used and must be mounted in /mnt/cdrom.
+# Specify the name of the vserver
+# "install-rh9.0 test" will create /vservers/test
+
+USR_LIB_VSERVER=$(dirname $0)
+if [ $# -lt 1 ] ; then
+ echo install-rh9.0 vserver-id [ type ]
+ echo type minimum means, minimum package for a server
+ echo type large means, all packages on the first CD
+elif [ -d /vservers/$1/var/lib/rpm ] ; then
+ echo /vservers/$1 already exist
+elif [ ! -d /mnt/cdrom/RedHat/RPMS ] ; then
+ echo No rpms in /mnt/cdrom/RedHat/RPMS. Is the CD mounted \?
+else
+ VROOT=/vservers/$1
+ $USR_LIB_VSERVER/install-pre.sh $1
+ mkdir -p $VROOT/proc
+ mount -t proc none $VROOT/proc
+ mount -t devpts none $VROOT/dev/pts
+ mkdir -p $VROOT/var/lib/rpm
+ rpm --root $VROOT --initdb
+ if [ "$2" = "minimum" ] ; then
+ echo `cat $USR_LIB_VSERVER/rh9.0-minimum | wc -l` packages to install
+ cd /mnt/cdrom/RedHat/RPMS
+ rpm --root $VROOT -Uvh `cat $USR_LIB_VSERVER/rh9.0-minimum`
+ else
+ PKGS=`ls /mnt/cdrom/RedHat/RPMS/*.noarch.rpm \
+ /mnt/cdrom/RedHat/RPMS/*.i386.rpm`
+ for except in control-center iptables kernel-pcmcia-cs\
+ nfs-utils pciutils quota rp-pppoe tcpdump \
+ lokkit kudzu-devel pciutils-devel \
+ redhat-config-securitylevel redhat-config-nfs
+ do
+ PKGS=`ls $PKGS | grep -v $except`
+ done
+ echo `echo $PKGS | wc -w` packages to install
+ rpm --root $VROOT -Uvh $PKGS --nodeps
+ fi
+ umount $VROOT/proc
+ umount $VROOT/dev/pts
+ $USR_LIB_VSERVER/install-post.sh $1
+fi
+
+
--- /dev/null
+4Suite-0.11.1-8.i386.rpm
+Canna-3.5b2-62.i386.rpm
+Canna-libs-3.5b2-62.i386.rpm
+Distutils-1.0.2-2.noarch.rpm
+MAKEDEV-3.3-4.i386.rpm
+PyXML-0.7-4.i386.rpm
+SysVinit-2.84-2.i386.rpm
+a2ps-4.13b-19.i386.rpm
+alchemist-1.0.23-1.i386.rpm
+anacron-2.3-17.i386.rpm
+ash-0.3.7-2.i386.rpm
+at-3.1.8-23.i386.rpm
+audiofile-0.2.3-1.i386.rpm
+authconfig-4.2.8-4.i386.rpm
+basesystem-7.0-2.noarch.rpm
+bash-2.05a-13.i386.rpm
+bdflush-1.5-17.i386.rpm
+bzip2-1.0.2-2.i386.rpm
+bzip2-libs-1.0.2-2.i386.rpm
+chkconfig-1.3.5-3.i386.rpm
+cpio-2.4.2-26.i386.rpm
+cracklib-2.7-15.i386.rpm
+cracklib-dicts-2.7-15.i386.rpm
+crontabs-1.10-1.noarch.rpm
+cyrus-sasl-1.5.24-25.i386.rpm
+cyrus-sasl-md5-1.5.24-25.i386.rpm
+cyrus-sasl-plain-1.5.24-25.i386.rpm
+db1-1.85-8.i386.rpm
+db2-2.4.14-10.i386.rpm
+db3-3.3.11-6.i386.rpm
+dev-3.3-4.i386.rpm
+diffutils-2.7.2-5.i386.rpm
+dosfstools-2.8-1.i386.rpm
+e2fsprogs-1.27-3.i386.rpm
+ed-0.2-25.i386.rpm
+fam-2.6.7-6.i386.rpm
+file-3.37-5.i386.rpm
+filesystem-2.1.6-2.noarch.rpm
+fileutils-4.1-10.i386.rpm
+findutils-4.1.7-4.i386.rpm
+freetype-2.0.9-2.i386.rpm
+gawk-3.1.0-4.i386.rpm
+gdbm-1.8.0-14.i386.rpm
+glib-1.2.10-5.i386.rpm
+glib2-2.0.1-2.i386.rpm
+glibc-2.2.5-34.i386.rpm
+glibc-common-2.2.5-34.i386.rpm
+gnupg-1.0.6-5.i386.rpm
+grep-2.5.1-1.i386.rpm
+groff-1.17.2-12.i386.rpm
+groff-perl-1.17.2-12.i386.rpm
+gzip-1.3.3-1.i386.rpm
+htdig-3.2.0-2.011302.i386.rpm
+indexhtml-7.3-3.noarch.rpm
+info-4.1-1.i386.rpm
+initscripts-6.67-1.i386.rpm
+iputils-20020124-3.i386.rpm
+less-358-24.i386.rpm
+libcap-1.10-8.i386.rpm
+libghttp-1.0.9-2.i386.rpm
+libjpeg-6b-19.i386.rpm
+libmng-1.0.3-2.i386.rpm
+libogg-1.0rc3-1.i386.rpm
+libpng-1.0.12-2.i386.rpm
+libstdc++-2.96-110.i386.rpm
+libtermcap-2.0.8-28.i386.rpm
+libtiff-3.5.7-2.i386.rpm
+libtool-libs-1.4.2-7.i386.rpm
+libunicode-0.4-6.i386.rpm
+libuser-0.50.2-1.i386.rpm
+libvorbis-1.0rc3-1.i386.rpm
+libxml-1.8.17-3.i386.rpm
+libxml2-2.4.19-4.i386.rpm
+libxslt-1.0.15-1.i386.rpm
+logrotate-3.6.4-1.i386.rpm
+losetup-2.11n-12.i386.rpm
+m4-1.4.1-7.i386.rpm
+mailcap-2.1.9-2.noarch.rpm
+mailx-8.1.1-22.i386.rpm
+make-3.79.1-8.i386.rpm
+man-1.5j-6.i386.rpm
+man-pages-1.48-2.noarch.rpm
+mktemp-1.5-14.i386.rpm
+mount-2.11n-12.i386.rpm
+mpage-2.5.1-9.i386.rpm
+ncurses-5.2-26.i386.rpm
+netpbm-9.24-3.i386.rpm
+netpbm-progs-9.24-3.i386.rpm
+newt-0.50.35-1.i386.rpm
+nhpf-1.42-2.i386.rpm
+ntsysv-1.3.5-3.i386.rpm
+openldap-2.0.23-4.i386.rpm
+openssh-3.1p1-3.i386.rpm
+openssh-clients-3.1p1-3.i386.rpm
+openssl-0.9.6b-18.i386.rpm
+pam-0.75-32.i386.rpm
+passwd-0.67-1.i386.rpm
+patch-2.5.4-12.i386.rpm
+pcre-3.9-2.i386.rpm
+perl-5.6.1-34.99.6.i386.rpm
+perl-CGI-2.752-34.99.6.i386.rpm
+perl-CPAN-1.59_54-34.99.6.i386.rpm
+perl-DB_File-1.75-34.99.6.i386.rpm
+perl-DateManip-5.40-15.i386.rpm
+perl-Digest-MD5-2.16-15.i386.rpm
+perl-File-MMagic-1.13-14.i386.rpm
+perl-HTML-Parser-3.26-2.i386.rpm
+perl-HTML-Tagset-3.03-14.i386.rpm
+perl-MIME-Base64-2.12-14.i386.rpm
+perl-NDBM_File-1.75-34.99.6.i386.rpm
+perl-NKF-1.71-2.i386.rpm
+perl-Parse-Yapp-1.05-15.i386.rpm
+perl-Storable-1.0.14-15.i386.rpm
+perl-URI-1.17-16.i386.rpm
+perl-XML-Dumper-0.4-12.noarch.rpm
+perl-XML-Encoding-1.01-9.noarch.rpm
+perl-XML-Grove-0.46alpha-11.noarch.rpm
+perl-XML-Parser-2.30-15.i386.rpm
+perl-XML-Twig-2.02-9.noarch.rpm
+perl-libnet-1.0901-17.i386.rpm
+perl-libwww-perl-5.63-9.i386.rpm
+perl-libxml-enno-1.02-15.i386.rpm
+perl-libxml-perl-0.07-14.noarch.rpm
+pnm2ppa-1.04-2.i386.rpm
+popt-1.6.4-7x.18.i386.rpm
+portmap-4.0-41.i386.rpm
+procmail-3.22-5.i386.rpm
+procps-2.0.7-12.i386.rpm
+psmisc-20.2-2.i386.rpm
+pspell-0.12.2-8.i386.rpm
+psutils-1.17-13.i386.rpm
+pwdb-0.61.2-2.i386.rpm
+python-1.5.2-38.i386.rpm
+python-clap-1.0.0-3.noarch.rpm
+python-popt-0.8.8-7.x.2.i386.rpm
+python-xmlrpc-1.5.1-7.x.3.i386.rpm
+python2-2.2-16.i386.rpm
+readline-4.2a-4.i386.rpm
+redhat-release-7.3-1.noarch.rpm
+rootfiles-7.2-1.noarch.rpm
+rpm-4.0.4-7x.18.i386.rpm
+rpm-python-4.0.4-7x.18.i386.rpm
+sed-3.02-11.i386.rpm
+sendmail-8.11.6-15.i386.rpm
+setup-2.5.12-1.noarch.rpm
+sgml-common-0.6.3-9.noarch.rpm
+sh-utils-2.0.11-14.i386.rpm
+shadow-utils-20000902-7.i386.rpm
+slang-1.4.5-2.i386.rpm
+slocate-2.6-1.i386.rpm
+specspo-7.3-4.noarch.rpm
+sysklogd-1.4.1-8.i386.rpm
+tar-1.13.25-4.i386.rpm
+tcl-8.3.3-67.i386.rpm
+tcsh-6.10-6.i386.rpm
+termcap-11.0.1-10.noarch.rpm
+textutils-2.0.21-1.i386.rpm
+time-1.7-16.i386.rpm
+tmpwatch-2.8.3-1.i386.rpm
+umb-scheme-3.2-21.i386.rpm
+unzip-5.50-2.i386.rpm
+usermode-1.53-2.i386.rpm
+utempter-0.5.2-6.i386.rpm
+util-linux-2.11n-12.i386.rpm
+vim-common-6.1-2.i386.rpm
+vim-minimal-6.1-2.i386.rpm
+vixie-cron-3.0.1-64.i386.rpm
+which-2.13-3.i386.rpm
+words-2-18.noarch.rpm
+xinetd-2.3.4-0.8.i386.rpm
+xml-common-0.6.3-9.noarch.rpm
+zip-2.3-12.i386.rpm
+zlib-1.1.3-25.7.i386.rpm
+mingetty-1.00-1.i386.rpm
+iproute-2.4.7-1.i386.rpm
+modutils-2.4.14-3.i386.rpm
+gmp-4.0.1-3.i386.rpm
+expat-1.95.2-2.i386.rpm
+net-tools-1.60-4.i386.rpm
--- /dev/null
+4Suite-0.11.1-8.i386.rpm
+Canna-3.5b2-62.i386.rpm
+Canna-libs-3.5b2-62.i386.rpm
+Distutils-1.0.2-2.noarch.rpm
+MAKEDEV-3.3-4.i386.rpm
+PyXML-0.7-4.i386.rpm
+SysVinit-2.84-2.i386.rpm
+a2ps-4.13b-19.i386.rpm
+alchemist-1.0.23-1.i386.rpm
+anacron-2.3-17.i386.rpm
+ash-0.3.7-2.i386.rpm
+at-3.1.8-23.i386.rpm
+audiofile-0.2.3-1.i386.rpm
+authconfig-4.2.8-4.i386.rpm
+basesystem-7.0-2.noarch.rpm
+bash-2.05a-13.i386.rpm
+bdflush-1.5-17.i386.rpm
+bzip2-1.0.2-2.i386.rpm
+bzip2-libs-1.0.2-2.i386.rpm
+chkconfig-1.3.5-3.i386.rpm
+cpio-2.4.2-26.i386.rpm
+cracklib-2.7-15.i386.rpm
+cracklib-dicts-2.7-15.i386.rpm
+crontabs-1.10-1.noarch.rpm
+cyrus-sasl-1.5.24-25.i386.rpm
+cyrus-sasl-md5-1.5.24-25.i386.rpm
+cyrus-sasl-plain-1.5.24-25.i386.rpm
+db1-1.85-8.i386.rpm
+db2-2.4.14-10.i386.rpm
+db3-3.3.11-6.i386.rpm
+dev-3.3-4.i386.rpm
+diffutils-2.7.2-5.i386.rpm
+dosfstools-2.8-1.i386.rpm
+e2fsprogs-1.27-3.i386.rpm
+ed-0.2-25.i386.rpm
+fam-2.6.7-6.i386.rpm
+file-3.37-5.i386.rpm
+filesystem-2.1.6-2.noarch.rpm
+fileutils-4.1-10.i386.rpm
+findutils-4.1.7-4.i386.rpm
+freetype-2.0.9-2.i386.rpm
+gawk-3.1.0-4.i386.rpm
+gdbm-1.8.0-14.i386.rpm
+glib-1.2.10-5.i386.rpm
+glib2-2.0.1-2.i386.rpm
+glibc-2.2.5-34.i386.rpm
+glibc-common-2.2.5-34.i386.rpm
+gnupg-1.0.6-5.i386.rpm
+grep-2.5.1-1.i386.rpm
+groff-1.17.2-12.i386.rpm
+groff-perl-1.17.2-12.i386.rpm
+gzip-1.3.3-1.i386.rpm
+htdig-3.2.0-2.011302.i386.rpm
+indexhtml-7.3-3.noarch.rpm
+info-4.1-1.i386.rpm
+initscripts-6.67-1.i386.rpm
+iputils-20020124-3.i386.rpm
+less-358-24.i386.rpm
+libcap-1.10-8.i386.rpm
+libghttp-1.0.9-2.i386.rpm
+libjpeg-6b-19.i386.rpm
+libmng-1.0.3-2.i386.rpm
+libogg-1.0rc3-1.i386.rpm
+libpng-1.0.12-2.i386.rpm
+libstdc++-2.96-110.i386.rpm
+libtermcap-2.0.8-28.i386.rpm
+libtiff-3.5.7-2.i386.rpm
+libtool-libs-1.4.2-7.i386.rpm
+libunicode-0.4-6.i386.rpm
+libuser-0.50.2-1.i386.rpm
+libvorbis-1.0rc3-1.i386.rpm
+libxml-1.8.17-3.i386.rpm
+libxml2-2.4.19-4.i386.rpm
+libxslt-1.0.15-1.i386.rpm
+logrotate-3.6.4-1.i386.rpm
+losetup-2.11n-12.i386.rpm
+m4-1.4.1-7.i386.rpm
+mailcap-2.1.9-2.noarch.rpm
+mailx-8.1.1-22.i386.rpm
+make-3.79.1-8.i386.rpm
+man-1.5j-6.i386.rpm
+man-pages-1.48-2.noarch.rpm
+mktemp-1.5-14.i386.rpm
+mount-2.11n-12.i386.rpm
+mpage-2.5.1-9.i386.rpm
+ncurses-5.2-26.i386.rpm
+netpbm-9.24-3.i386.rpm
+netpbm-progs-9.24-3.i386.rpm
+newt-0.50.35-1.i386.rpm
+nhpf-1.42-2.i386.rpm
+ntsysv-1.3.5-3.i386.rpm
+openldap-2.0.23-4.i386.rpm
+openssh-3.1p1-3.i386.rpm
+openssh-clients-3.1p1-3.i386.rpm
+openssl-0.9.6b-18.i386.rpm
+pam-0.75-32.i386.rpm
+passwd-0.67-1.i386.rpm
+patch-2.5.4-12.i386.rpm
+pcre-3.9-2.i386.rpm
+perl-5.6.1-34.99.6.i386.rpm
+perl-CGI-2.752-34.99.6.i386.rpm
+perl-CPAN-1.59_54-34.99.6.i386.rpm
+perl-DB_File-1.75-34.99.6.i386.rpm
+perl-DateManip-5.40-15.i386.rpm
+perl-Digest-MD5-2.16-15.i386.rpm
+perl-File-MMagic-1.13-14.i386.rpm
+perl-HTML-Parser-3.26-2.i386.rpm
+perl-HTML-Tagset-3.03-14.i386.rpm
+perl-MIME-Base64-2.12-14.i386.rpm
+perl-NDBM_File-1.75-34.99.6.i386.rpm
+perl-NKF-1.71-2.i386.rpm
+perl-Parse-Yapp-1.05-15.i386.rpm
+perl-Storable-1.0.14-15.i386.rpm
+perl-URI-1.17-16.i386.rpm
+perl-XML-Dumper-0.4-12.noarch.rpm
+perl-XML-Encoding-1.01-9.noarch.rpm
+perl-XML-Grove-0.46alpha-11.noarch.rpm
+perl-XML-Parser-2.30-15.i386.rpm
+perl-XML-Twig-2.02-9.noarch.rpm
+perl-libnet-1.0901-17.i386.rpm
+perl-libwww-perl-5.63-9.i386.rpm
+perl-libxml-enno-1.02-15.i386.rpm
+perl-libxml-perl-0.07-14.noarch.rpm
+pnm2ppa-1.04-2.i386.rpm
+popt-1.6.4-7x.18.i386.rpm
+portmap-4.0-41.i386.rpm
+procmail-3.22-5.i386.rpm
+procps-2.0.7-12.i386.rpm
+psmisc-20.2-2.i386.rpm
+pspell-0.12.2-8.i386.rpm
+psutils-1.17-13.i386.rpm
+pwdb-0.61.2-2.i386.rpm
+python-1.5.2-38.i386.rpm
+python-clap-1.0.0-3.noarch.rpm
+python-popt-0.8.8-7.x.2.i386.rpm
+python-xmlrpc-1.5.1-7.x.3.i386.rpm
+python2-2.2-16.i386.rpm
+readline-4.2a-4.i386.rpm
+redhat-release-7.3-1.noarch.rpm
+rootfiles-7.2-1.noarch.rpm
+rpm-4.0.4-7x.18.i386.rpm
+rpm-python-4.0.4-7x.18.i386.rpm
+sed-3.02-11.i386.rpm
+sendmail-8.11.6-15.i386.rpm
+setup-2.5.12-1.noarch.rpm
+sgml-common-0.6.3-9.noarch.rpm
+sh-utils-2.0.11-14.i386.rpm
+shadow-utils-20000902-7.i386.rpm
+slang-1.4.5-2.i386.rpm
+slocate-2.6-1.i386.rpm
+specspo-7.3-4.noarch.rpm
+sysklogd-1.4.1-8.i386.rpm
+tar-1.13.25-4.i386.rpm
+tcl-8.3.3-67.i386.rpm
+tcsh-6.10-6.i386.rpm
+termcap-11.0.1-10.noarch.rpm
+textutils-2.0.21-1.i386.rpm
+time-1.7-16.i386.rpm
+tmpwatch-2.8.3-1.i386.rpm
+umb-scheme-3.2-21.i386.rpm
+unzip-5.50-2.i386.rpm
+usermode-1.53-2.i386.rpm
+utempter-0.5.2-6.i386.rpm
+util-linux-2.11n-12.i386.rpm
+vim-common-6.1-2.i386.rpm
+vim-minimal-6.1-2.i386.rpm
+vixie-cron-3.0.1-64.i386.rpm
+which-2.13-3.i386.rpm
+words-2-18.noarch.rpm
+xinetd-2.3.4-0.8.i386.rpm
+xml-common-0.6.3-9.noarch.rpm
+zip-2.3-12.i386.rpm
+zlib-1.1.3-25.7.i386.rpm
+mingetty-1.00-1.i386.rpm
+iproute-2.4.7-1.i386.rpm
+modutils-2.4.14-3.i386.rpm
+gmp-4.0.1-3.i386.rpm
+expat-1.95.2-2.i386.rpm
+net-tools-1.60-4.i386.rpm
--- /dev/null
+4Suite-[0-9]*.i386.rpm
+Canna-[0-9]*.i386.rpm
+Canna-libs-[0-9]*.i386.rpm
+Distutils-*.noarch.rpm
+MAKEDEV-[0-9]*.i386.rpm
+PyXML-[0-9]*.i386.rpm
+SysVinit-[0-9]*.i386.rpm
+a2ps-[0-9]*.i386.rpm
+alchemist-[0-9]*.i386.rpm
+anacron-[0-9]*.i386.rpm
+ash-[0-9]*.i386.rpm
+at-[0-9]*.i386.rpm
+audiofile-[0-9]*.i386.rpm
+authconfig-[0-9]*.i386.rpm
+basesystem-*.noarch.rpm
+bash-[0-9]*.i386.rpm
+bdflush-[0-9]*.i386.rpm
+bzip2-[0-9]*.i386.rpm
+bzip2-libs-[0-9]*.i386.rpm
+chkconfig-[0-9]*.i386.rpm
+cpio-[0-9]*.i386.rpm
+cracklib-[0-9]*.i386.rpm
+cracklib-dicts-[0-9]*.i386.rpm
+crontabs-*.noarch.rpm
+cyrus-sasl-[0-9]*.i386.rpm
+cyrus-sasl-md5-[0-9]*.i386.rpm
+db1-[0-9]*.i386.rpm
+db2-[0-9]*.i386.rpm
+db3-[0-9]*.i386.rpm
+db4-[0-9]*.i386.rpm
+libelf-[0-9]*.i386.rpm
+dev-[0-9]*.i386.rpm
+diffutils-[0-9]*.i386.rpm
+dosfstools-[0-9]*.i386.rpm
+e2fsprogs-[0-9]*.i386.rpm
+ed-[0-9]*.i386.rpm
+fam-[0-9]*.i386.rpm
+file-[0-9]*.i386.rpm
+filesystem-[0-9]*.noarch.rpm
+fileutils-[0-9]*.i386.rpm
+findutils-[0-9]*.i386.rpm
+libacl-[0-9]*.i386.rpm
+libgcc-[0-9]*.i386.rpm
+freetype-[0-9]*.i386.rpm
+gawk-[0-9]*.i386.rpm
+gdbm-[0-9]*.i386.rpm
+glib-[0-9]*.i386.rpm
+glib2-[0-9]*.i386.rpm
+glibc-[0-9]*.i386.rpm
+glibc-common-[0-9]*.i386.rpm
+gnupg-[0-9]*.i386.rpm
+grep-[0-9]*.i386.rpm
+groff-[0-9]*.i386.rpm
+groff-perl-[0-9]*.i386.rpm
+gzip-[0-9]*.i386.rpm
+htdig-[0-9]*.i386.rpm
+indexhtml-*.noarch.rpm
+info-[0-9]*.i386.rpm
+initscripts-[0-9]*.i386.rpm
+iputils-[0-9]*.i386.rpm
+less-[0-9]*.i386.rpm
+libcap-[0-9]*.i386.rpm
+libghttp-[0-9]*.i386.rpm
+libjpeg-[0-9]*.i386.rpm
+libmng-[0-9]*.i386.rpm
+libogg-[0-9]*.i386.rpm
+libpng-[0-9]*.i386.rpm
+libstdc++-[0-9]*.i386.rpm
+libtermcap-[0-9]*.i386.rpm
+libtiff-[0-9]*.i386.rpm
+libtool-libs-[0-9]*.i386.rpm
+libunicode-[0-9]*.i386.rpm
+libuser-[0-9]*.i386.rpm
+libvorbis-[0-9]*.i386.rpm
+libxml-[0-9]*.i386.rpm
+libxml2-[0-9]*.i386.rpm
+libxslt-[0-9]*.i386.rpm
+logrotate-[0-9]*.i386.rpm
+losetup-[0-9]*.i386.rpm
+m4-[0-9]*.i386.rpm
+mailcap-*.noarch.rpm
+mailx-[0-9]*.i386.rpm
+make-[0-9]*.i386.rpm
+man-[0-9]*.i386.rpm
+man-pages-*.noarch.rpm
+mktemp-[0-9]*.i386.rpm
+mount-[0-9]*.i386.rpm
+mpage-[0-9]*.i386.rpm
+ncurses-[0-9]*.i386.rpm
+netpbm-[0-9]*.i386.rpm
+newt-[0-9]*.i386.rpm
+nhpf-[0-9]*.i386.rpm
+ntsysv-[0-9]*.i386.rpm
+openldap-[0-9]*.i386.rpm
+openssh-[0-9]*.i386.rpm
+openssh-clients-[0-9]*.i386.rpm
+openssh-server-[0-9]*.i386.rpm
+openssl-[0-9]*.i386.rpm
+pam-[0-9]*.i386.rpm
+passwd-[0-9]*.i386.rpm
+patch-[0-9]*.i386.rpm
+pcre-[0-9]*.i386.rpm
+perl-[0-9]*.i386.rpm
+perl-Filter-[0-9]*.i386.rpm
+krb5-libs-[0-9]*.i386.rpm
+libattr-[0-9]*.i386.rpm
+hesiod-[0-9]*.i386.rpm
+pnm2ppa-[0-9]*.i386.rpm
+popt-[0-9]*.i386.rpm
+portmap-[0-9]*.i386.rpm
+procmail-[0-9]*.i386.rpm
+procps-[0-9]*.i386.rpm
+psmisc-[0-9]*.i386.rpm
+pspell-[0-9]*.i386.rpm
+psutils-[0-9]*.i386.rpm
+pwdb-[0-9]*.i386.rpm
+python-[0-9]*.i386.rpm
+python-clap-*.noarch.rpm
+python-popt-[0-9]*.i386.rpm
+python-xmlrpc-[0-9]*.i386.rpm
+python2-[0-9]*.i386.rpm
+readline-[0-9]*.i386.rpm
+redhat-release-*.noarch.rpm
+rootfiles-*.noarch.rpm
+rpm-[0-9]*.i386.rpm
+sed-[0-9]*.i386.rpm
+sendmail-[0-9]*.i386.rpm
+setup-*.noarch.rpm
+sgml-common-*.noarch.rpm
+sh-utils-[0-9]*.i386.rpm
+shadow-utils-[0-9]*.i386.rpm
+slang-[0-9]*.i386.rpm
+slocate-[0-9]*.i386.rpm
+specspo-*.noarch.rpm
+sysklogd-[0-9]*.i386.rpm
+tar-[0-9]*.i386.rpm
+tcl-[0-9]*.i386.rpm
+tcsh-[0-9]*.i386.rpm
+termcap-*.noarch.rpm
+textutils-[0-9]*.i386.rpm
+time-[0-9]*.i386.rpm
+tmpwatch-[0-9]*.i386.rpm
+umb-scheme-[0-9]*.i386.rpm
+unzip-[0-9]*.i386.rpm
+usermode-[0-9]*.i386.rpm
+utempter-[0-9]*.i386.rpm
+util-linux-[0-9]*.i386.rpm
+vim-common-[0-9]*.i386.rpm
+vim-minimal-[0-9]*.i386.rpm
+vixie-cron-[0-9]*.i386.rpm
+which-[0-9]*.i386.rpm
+words-*.noarch.rpm
+xinetd-[0-9]*.i386.rpm
+xml-common-*.noarch.rpm
+zip-[0-9]*.i386.rpm
+zlib-[0-9]*.i386.rpm
+mingetty-[0-9]*.i386.rpm
+iproute-[0-9]*.i386.rpm
+modutils-[0-9]*.i386.rpm
+gmp-[0-9]*.i386.rpm
+expat-[0-9]*.i386.rpm
+net-tools-[0-9]*.i386.rpm
+
--- /dev/null
+4Suite-[0-9]*.i386.rpm
+Canna-[0-9]*.i386.rpm
+Canna-libs-[0-9]*.i386.rpm
+Distutils-*.noarch.rpm
+MAKEDEV-[0-9]*.i386.rpm
+PyXML-[0-9]*.i386.rpm
+SysVinit-[0-9]*.i386.rpm
+a2ps-[0-9]*.i386.rpm
+alchemist-[0-9]*.i386.rpm
+anacron-[0-9]*.i386.rpm
+ash-[0-9]*.i386.rpm
+at-[0-9]*.i386.rpm
+audiofile-[0-9]*.i386.rpm
+authconfig-[0-9]*.i386.rpm
+basesystem-*.noarch.rpm
+bash-[0-9]*.i386.rpm
+bdflush-[0-9]*.i386.rpm
+bzip2-[0-9]*.i386.rpm
+bzip2-libs-[0-9]*.i386.rpm
+chkconfig-[0-9]*.i386.rpm
+cpio-[0-9]*.i386.rpm
+cracklib-[0-9]*.i386.rpm
+cracklib-dicts-[0-9]*.i386.rpm
+crontabs-*.noarch.rpm
+cyrus-sasl-[0-9]*.i386.rpm
+cyrus-sasl-md5-[0-9]*.i386.rpm
+db1-[0-9]*.i386.rpm
+db2-[0-9]*.i386.rpm
+db3-[0-9]*.i386.rpm
+db4-[0-9]*.i386.rpm
+libelf-[0-9]*.i386.rpm
+dev-[0-9]*.i386.rpm
+diffutils-[0-9]*.i386.rpm
+dosfstools-[0-9]*.i386.rpm
+e2fsprogs-[0-9]*.i386.rpm
+ed-[0-9]*.i386.rpm
+fam-[0-9]*.i386.rpm
+file-[0-9]*.i386.rpm
+filesystem-[0-9]*.noarch.rpm
+fileutils-[0-9]*.i386.rpm
+findutils-[0-9]*.i386.rpm
+libacl-[0-9]*.i386.rpm
+libgcc-[0-9]*.i386.rpm
+freetype-[0-9]*.i386.rpm
+gawk-[0-9]*.i386.rpm
+gdbm-[0-9]*.i386.rpm
+glib-[0-9]*.i386.rpm
+glib2-[0-9]*.i386.rpm
+glibc-[0-9]*.i386.rpm
+glibc-common-[0-9]*.i386.rpm
+gnupg-[0-9]*.i386.rpm
+grep-[0-9]*.i386.rpm
+groff-[0-9]*.i386.rpm
+groff-perl-[0-9]*.i386.rpm
+gzip-[0-9]*.i386.rpm
+htdig-[0-9]*.i386.rpm
+indexhtml-*.noarch.rpm
+info-[0-9]*.i386.rpm
+initscripts-[0-9]*.i386.rpm
+iputils-[0-9]*.i386.rpm
+less-[0-9]*.i386.rpm
+libcap-[0-9]*.i386.rpm
+libghttp-[0-9]*.i386.rpm
+libjpeg-[0-9]*.i386.rpm
+libmng-[0-9]*.i386.rpm
+libogg-[0-9]*.i386.rpm
+libpng-[0-9]*.i386.rpm
+libstdc++-[0-9]*.i386.rpm
+libtermcap-[0-9]*.i386.rpm
+libtiff-[0-9]*.i386.rpm
+libtool-libs-[0-9]*.i386.rpm
+libunicode-[0-9]*.i386.rpm
+libuser-[0-9]*.i386.rpm
+libvorbis-[0-9]*.i386.rpm
+libxml-[0-9]*.i386.rpm
+libxml2-[0-9]*.i386.rpm
+libxslt-[0-9]*.i386.rpm
+logrotate-[0-9]*.i386.rpm
+losetup-[0-9]*.i386.rpm
+m4-[0-9]*.i386.rpm
+mailcap-*.noarch.rpm
+mailx-[0-9]*.i386.rpm
+make-[0-9]*.i386.rpm
+man-[0-9]*.i386.rpm
+man-pages-*.noarch.rpm
+mktemp-[0-9]*.i386.rpm
+mount-[0-9]*.i386.rpm
+mpage-[0-9]*.i386.rpm
+ncurses-[0-9]*.i386.rpm
+netpbm-[0-9]*.i386.rpm
+newt-[0-9]*.i386.rpm
+nhpf-[0-9]*.i386.rpm
+ntsysv-[0-9]*.i386.rpm
+openldap-[0-9]*.i386.rpm
+openssh-[0-9]*.i386.rpm
+openssh-clients-[0-9]*.i386.rpm
+openssh-server-[0-9]*.i386.rpm
+openssl-[0-9]*.i386.rpm
+pam-[0-9]*.i386.rpm
+passwd-[0-9]*.i386.rpm
+patch-[0-9]*.i386.rpm
+pcre-[0-9]*.i386.rpm
+perl-[0-9]*.i386.rpm
+perl-Filter-[0-9]*.i386.rpm
+krb5-libs-[0-9]*.i386.rpm
+libattr-[0-9]*.i386.rpm
+hesiod-[0-9]*.i386.rpm
+pnm2ppa-[0-9]*.i386.rpm
+popt-[0-9]*.i386.rpm
+portmap-[0-9]*.i386.rpm
+procmail-[0-9]*.i386.rpm
+procps-[0-9]*.i386.rpm
+psmisc-[0-9]*.i386.rpm
+pspell-[0-9]*.i386.rpm
+psutils-[0-9]*.i386.rpm
+pwdb-[0-9]*.i386.rpm
+python-[0-9]*.i386.rpm
+python-clap-*.noarch.rpm
+python-popt-[0-9]*.i386.rpm
+python-xmlrpc-[0-9]*.i386.rpm
+python2-[0-9]*.i386.rpm
+readline-[0-9]*.i386.rpm
+redhat-release-*.noarch.rpm
+rootfiles-*.noarch.rpm
+rpm-[0-9]*.i386.rpm
+sed-[0-9]*.i386.rpm
+sendmail-[0-9]*.i386.rpm
+setup-*.noarch.rpm
+sgml-common-*.noarch.rpm
+sh-utils-[0-9]*.i386.rpm
+shadow-utils-[0-9]*.i386.rpm
+slang-[0-9]*.i386.rpm
+slocate-[0-9]*.i386.rpm
+specspo-*.noarch.rpm
+sysklogd-[0-9]*.i386.rpm
+tar-[0-9]*.i386.rpm
+tcl-[0-9]*.i386.rpm
+tcsh-[0-9]*.i386.rpm
+termcap-*.noarch.rpm
+textutils-[0-9]*.i386.rpm
+time-[0-9]*.i386.rpm
+tmpwatch-[0-9]*.i386.rpm
+umb-scheme-[0-9]*.i386.rpm
+unzip-[0-9]*.i386.rpm
+usermode-[0-9]*.i386.rpm
+utempter-[0-9]*.i386.rpm
+util-linux-[0-9]*.i386.rpm
+vim-common-[0-9]*.i386.rpm
+vim-minimal-[0-9]*.i386.rpm
+vixie-cron-[0-9]*.i386.rpm
+which-[0-9]*.i386.rpm
+words-*.noarch.rpm
+xinetd-[0-9]*.i386.rpm
+xml-common-*.noarch.rpm
+zip-[0-9]*.i386.rpm
+zlib-[0-9]*.i386.rpm
+mingetty-[0-9]*.i386.rpm
+iproute-[0-9]*.i386.rpm
+modutils-[0-9]*.i386.rpm
+gmp-[0-9]*.i386.rpm
+expat-[0-9]*.i386.rpm
+net-tools-[0-9]*.i386.rpm
+
--- /dev/null
+# Select an unused context (this is optional)
+# The default is to allocate a free context on the fly
+# In general you don't need to force a context
+#S_CONTEXT=
+# Select the IP number assigned to the virtual server
+# This IP must be one IP of the server, either an interface
+# or an IP alias
+IPROOT=1.2.3.4
+# The netmask and broadcast are computed by default from IPROOTDEV
+#IPROOTMASK=
+#IPROOTBCAST=
+# You can define on which device the IP alias will be done
+# The IP alias will be set when the server is started and unset
+# when the server is stopped
+IPROOTDEV=eth0
+# Uncomment the onboot line if you want to enable this
+# virtual server at boot time
+#ONBOOT=yes
+# You can set a different host name for the vserver
+# If empty, the host name of the main server is used
+S_HOSTNAME=somename.somedomain.com
+# You can set a different NIS domain for the vserver
+# If empty, the current on is kept
+# Set it to "none" to have no NIS domain set
+S_DOMAINNAME=
+# You can set the priority level (nice) of all process in the vserver
+# Even root won't be able to raise it
+S_NICE=
+# You can set various flags for the new security context
+# lock: Prevent the vserver from setting new security context
+# sched: Merge scheduler priority of all processes in the vserver
+# so that it acts a like a single one.
+# nproc: Limit the number of processes in the vserver according to ulimit
+# (instead of a per user limit, this becomes a per vserver limit)
+# private: No other process can join this security context. Even root
+# Do not forget the quotes around the flags
+S_FLAGS="lock nproc"
+# You can set various ulimit flags and they will be inherited by the
+# vserver. You enter here various command line argument of ulimit
+# ULIMIT="-H -u 200"
+# The example above, combined with the nproc S_FLAGS will limit the
+# vserver to a maximum of 200 processes
+ULIMIT="-H -u 1000"
+# You can set various capabilities. By default, the vserver are run
+# with a limited set, so you can let root run in a vserver and not
+# worry about it. He can't take over the machine. In some cases
+# you can to give a little more capabilities (such as CAP_NET_RAW)
+# S_CAPS="CAP_NET_RAW"
+S_CAPS=""
--- /dev/null
+#!/bin/sh
+case $1 in
+pre-start)
+ ;;
+post-start)
+ ;;
+pre-stop)
+ ;;
+post-stop)
+ ;;
+*)
+ echo $0 pre-start
+ echo $0 pre-stop
+ echo $0 post-start
+ echo $0 post-stop
+ ;;
+esac
--- /dev/null
+
+ Object not found!
+
+ The requested URL was not found on this server. If you entered
+ the URL manually please check your spelling and try again.
+
+ If you think this is a server error, please contact the
+ [1]webmaster
+
+Error 404
+
+
+ [2]remtk
+ ven 18 jui 2003 11:41:32 EDT
+ Apache/2.0.40 (Red Hat Linux)
+
+Références
+
+ 1. mailto:root@localhost
+ 2. http://remtk/
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+doc_DAT = doc/FAQ.txt \
+ doc/changelog.txt \
+ doc/intro.txt
--- /dev/null
+
+ Object not found!
+
+ The requested URL was not found on this server. If you entered
+ the URL manually please check your spelling and try again.
+
+ If you think this is a server error, please contact the
+ [1]webmaster
+
+Error 404
+
+
+ [2]remtk
+ ven 18 jui 2003 11:41:32 EDT
+ Apache/2.0.40 (Red Hat Linux)
+
+Références
+
+ 1. mailto:root@localhost
+ 2. http://remtk/
--- /dev/null
+
+ 1. [1]Introduction [new.gif]
+ 1.1 [2]Who needs that [new.gif]
+ 2. [3]Principles [new.gif]
+ 2.1 [4]Non reversible isolation [new.gif]
+ 2.2 [5]Isolation areas [new.gif]
+ 2.3 [6]New system calls [new.gif]
+ 2.4 [7]Limiting super-user: The capabilities system [new.gif]
+ 2.5 [8]Enhancing the capability system [new.gif]
+ 2.6 [9]Playing with the new system calls [new.gif]
+ 2.6.1 [10]Playing with /usr/sbin/chcontext [new.gif]
+ 2.6.2 [11]Playing with /usr/sbin/chcontext as root [new.gif]
+ 2.6.3 [12]Playing with /usr/sbin/chbind [new.gif]
+ 2.6.4 [13]Playing with /usr/sbin/reducecap [new.gif]
+ 2.7 [14]Unification [new.gif]
+ 3. [15]Applications [new.gif]
+ 3.1 [16]Virtual server [new.gif]
+ 3.2 [17]Per user fire-wall [new.gif]
+ 3.3 [18]Secure server/Intrusion detection [new.gif]
+ 3.4 [19]Fail over servers [new.gif]
+ 4. [20]Installation [new.gif]
+ 4.1 [21]The packages [new.gif]
+ 4.2 [22]Setting a virtual server [new.gif]
+ 4.3 [23]Basic configuration of the virtual server [new.gif]
+ 4.4 [24]Entering the virtual server [new.gif]
+ 4.5 [25]Configuring the services [new.gif]
+ 4.6 [26]Starting/Stopping the virtual server [new.gif]
+ 4.7 [27]Starting/Stopping all the virtual servers [new.gif]
+ 4.8 [28]Restarting a virtual server from inside [new.gif]
+ 4.9 [29]Executing tasks at vserver start/stop time [new.gif]
+ 4.10 [30]Issues [new.gif]
+ 4.11 [31]How real is it ? [new.gif]
+ 5. [32]Features [new.gif]
+ 6. [33]Future directions [new.gif]
+ 6.1 [34]User controlled security box [new.gif]
+ 6.2 [35]Kernel enhancements [new.gif]
+ 6.2.1 [36]Per context disk quota [new.gif]
+ 6.2.2 [37]Global limits [new.gif]
+ 6.2.3 [38]Scheduler [new.gif]
+ 6.2.4 [39]Security issues [new.gif]
+ 6.2.4.1 [40]/dev/random [new.gif]
+ 6.2.4.2 [41]/dev/pts [new.gif]
+ 6.2.4.3 [42]Network devices [new.gif]
+ 7. [43]Alternative technologies [new.gif]
+ 7.1 [44]Virtual machines [new.gif]
+ 7.2 [45]Partitioning [new.gif]
+ 7.3 [46]Limitation of those technologies [new.gif]
+ 8. [47]Conclusion [new.gif]
+ 9. [48]Download [new.gif]
+ 10. [49]References [new.gif]
+
+ Virtual private servers and security contexts
+
+ Running independent Linux servers inside a single PC is now possible.
+ They offer many advantages, including higher security, flexibility and
+ cost reduction.
+
+ NEW
+
+Introduction
+
+ Linux computers are getting faster every day. So we should probably
+ end up with less, more powerful servers. Instead we are seeing more
+ and more servers. While there are many reasons for this trend (more
+ services offered), the major issue is more related to security and
+ administrative concerns.
+
+ Is it possible to split a Linux server into virtual ones with as much
+ isolation as possible between each one, looking like real servers, yet
+ sharing some common tasks (monitoring, backup, ups, hardware
+ configuration, ...) ?
+
+ We think so ... NEW
+
+Who needs that
+
+ The short answer is everybody, or everybody managing a server. Here
+ are some applications:
+
+ * Hosting: Complete general purpose hosting (Running many
+ independent servers in one box).
+ * Experimentation: You are toying with a new services and do not
+ want to impact the production services on the same machine.
+ * Education: Each student has its own server with root password.
+ * Personal security box: Run un-trusted applications with complete
+ control over their interaction with the rest of the computer and
+ the network.
+ * Managing several "versions" of the same server/project and turning
+ on/off each version independantly.
+
+ Just think about all the viruses and worms out there, you end up with
+ a big everybody using a computer needs this. :-) NEW
+
+Principles
+
+ NEW
+
+Non reversible isolation
+
+ Unix and Linux have always had the chroot() system call. This call was
+ used to trap a process into a sub-directory. After the system-call,
+ the process is led to believe that the sub-directory is now the root
+ directory. This system call can't be reversed. In fact, the only thing
+ a process can do is trap itself further and further in the file-system
+ (calling chroot() again).
+
+ The strategy is to introduce new system calls trapping the processes
+ in other areas within the server. NEW
+
+Isolation areas
+
+ A virtual server is isolated from the rest of the server in 5 areas:
+
+ * File system
+ The vserver is trapped into a sub-directory of the main server and
+ can't escape. This is done by the standard chroot() system call
+ found on all Unix and Linux boxes.
+ * Processes
+ The vserver can only see the processes in the same security
+ context. Even the root server can't see the processes in vservers,
+ making the root server less "dangerous" to use. A special
+ mechanism (context number 1) exists to view all processes though
+ (Limited to root in the root server).
+ * Networking
+ The vserver is assigned a host name and an IP number. The server
+ can only use this IP number to establish services and client
+ connection. Further, this restriction is transparent.
+ * Super user capabilities
+ The super user running in a vserver has less privileges than the
+ normal Linux root user. For example, it can't reconfigure the
+ networking and many aspect of the system. It can't mount devices,
+ can't access block devices and so on.
+ Roughly. the vserver super-user has full control over all files
+ and processes in the vserver and that's pretty much it.
+ * System V inter process communications
+ Sysv IPC resources are private to each vserver. The security
+ context is used as an extra key to select and assign resources.
+
+ Those facilities are used together to create a runtime environment for
+ virtual servers. But they can be used independently to achieve various
+ goals. NEW
+
+New system calls
+
+ The new system calls, as well as the existing chroot() system call are
+ sharing one common feature: Their effect can't be reversed. Once you
+ have executed one of those system call (chroot, new_s_context,
+ set_ipv4root), you can't get back. This affects the current process
+ and all the child processes. The parent process is not influenced.
+
+ * new_s_context (int ctx)
+ This system call sets a new security context for the current
+ process. It will be inherited by all child processes. The security
+ context is just an id, but the system call makes sure a new unused
+ one is allocated.
+ A process can only see other processes sharing the same security
+ context. When the system boot, the original security context is 0.
+ But this one is not privileged in anyway. Processes member of the
+ security context 0 can only interact (and see) processes member of
+ context 0.
+ This system call isolates the processes space.
+ * Setting the capabilities ceiling
+ This is handle by the new_s_context system call as well. This
+ reduces the ceiling capabilities of the current process. Even
+ setuid sub-process can't grab more capabilities. The capability
+ system found since Linux 2.2 is explained later in this document.
+ * set_ipv4root(unsigned long ip)
+ This system call locks the process (and children) into using a
+ single IP when they communicate and when they installs a service.
+ This system call is a one shot. Once a process have set its IPV4
+ (Internet Protocol Version 4) address to something different from
+ 0.0.0.0, it can't change it anymore. Children can't change it
+ either.
+ If a process tries to bind a specific IP number, it will succeed
+ only if this corresponds to the ipv4root (if different from
+ 0.0.0.0). If the process bind to any address, it will get the
+ ipv4root.
+ Basically, once a process is locked to a given ipv4root it is
+ forced to use this IP address to establish a service and
+ communicate. The restriction on services is handy: Most service
+ (Web servers, SQL servers) are binding to address 0.0.0.0. With
+ the ipv4root sets to a given IP you can have two virtual servers
+ using the exact same general/vanilla configuration for a given
+ services and running without any conflict.
+ This system calls isolate the IP network space.
+
+ Those system calls are not privileged. Any user may issue them. NEW
+
+Limiting super-user: The capabilities system
+
+ Once you have created a virtual environment where processes have a
+ limited view of the file-system, can't see processes outside of their
+ world and can only use a single IP number, you still must limit the
+ damages those processes can do. The goal is to run virtual
+ environments and provide some root privileges.
+
+ How do you limit those root processes from taking over the system, or
+ even just re-booting it. Enter the capability system. This is not new,
+ but we suspect many people have never heard of it.
+
+ In the old Unix/Linux days, user root (user ID 0) could do things
+ other user ID could not. All over the place in the kernel, system
+ calls were denying access to some resources unless the user ID of the
+ process (effective ID in fact) was 0. Plain zero.
+
+ The only way a process with user ID 0 could loose some privileges was
+ by changing to another ID. Unfortunately this was an all or nothing
+ deal. Enter the capabilities.
+
+ Today, the difference between root and the other users is the
+ capability set. User root has all capabilities and the other users
+ have none. The user ID 0 does not mean anything special anymore. There
+ are around 30 capabilities defined currently. A process may request to
+ loose a capability forever. It won't be able to get it back.
+
+ Capabilities allows a root process to diminish its power. This is
+ exactly what we need to create custom super-user. A super-user process
+ in a virtual server would have some privileges such as binding port
+ below 1024, but would not be able to reconfigure the network or reboot
+ the machine. Check the file /usr/include/linux/capability.h to learn
+ which one are available.
+
+ Note that the new system calls (new_s_context and set_ipv4root) are
+ not controlled by capabilities. They are by nature irreversible. Once
+ a virtual server is trapped in a chroot/s_context/ipv4root box, it
+ can't escape from the parameters of this trap.
+
+ NEW
+
+Enhancing the capability system
+
+ The Linux capability system, is still a work in progress. At some
+ point, we expect to see capabilities attached to programs,
+ generalizing the setuid concept. A setuid program would become a
+ program with all capability granted.
+
+ For now, this is not available. As explained above a process may
+ request to loose capabilities and its child process will be trapped
+ with a smaller capability set.
+
+ Well, ..., it does not work that way. Unfortunately, until
+ capabilities could be assigned to program, we still need a way to get
+ back capabilities even in a child process. So the irreversible logic
+ of the capabilities is kind of short circuited in the kernel.
+
+ To solve this, we have introduced a new per-process capability ceiling
+ (cap_bset). This one represents the capability set inherited by child
+ process, including setuid root child process. Lowering this ceiling is
+ irreversible for a process and all its child.
+
+ This ceiling is handled by the new_s_context system call and the
+ reducecap and chcontext utilities (part of the vserver package).
+
+ Using this, we can setup a virtual server environment where root has
+ less capabilities, so can't reconfigure the main server.
+
+ NEW
+
+Playing with the new system calls
+
+ The vserver package provides 3 utilities to make use of the new system
+ calls. We will describe shortly how they work and provide few example.
+ We invite the reader to try those example, so it has a better feel and
+ trust.
+
+ After re-booting with a kernel implementing the new system calls, and
+ installing the vserver package, one is ready to do experiment. You do
+ not need to be root to test those new utilities. None of them is
+ setuid either. NEW
+
+Playing with /usr/sbin/chcontext
+
+ The /usr/sbin/chcontext utility is used to enter into a new security
+ context. The utility switch the security context and execute a
+ program, specified on the command line. This program is now isolated
+ and can't see the other processes running on the server.
+
+ The experiment with this, start two command windows (xterm), as the
+ same user ID. In each window execute the following commands:
+
+ xterm
+
+ Using chcontext: first window
+
+/usr/sbin/chcontext /bin/sh
+pstree
+killall xterm
+exit
+
+ Using chcontext: second window
+ In the first window, you start the xterm command (or any command you
+ like). In the second window you execute chcontext. This starts a new
+ shell. You execute pstree and see very little. You attempt to kill the
+ xterm and you fail. You exit this shell and you are back seeing all
+ processes.
+
+ Here is another example. You switch context and you get a new shell.
+ In this shell you start an xterm. Then you switch context again and
+ start another sub-shell. Now the sub-shell is again isolated.
+
+/usr/sbin/chcontext /bin/sh
+pstree
+xterm &
+pstree
+# Ok now you see your xterm
+/usr/sbin/chcontext /bin/sh
+pstree
+# the xterm is not there, killall will fail
+killall xterm
+# Now we exit the shell
+exit
+pstree
+# the xterm is there
+killall xterm
+# Ok, it is gone
+exit
+# We are back to the initial security context
+
+ Using chcontext several times
+ Processes isolated using chcontext are doubly isolated: They can't see
+ the other processes on the server, but the other processes can't see
+ them either. The original security context (0) when you boot is no
+ better than the other: It sees only process in security context 0.
+
+ While playing with chcontext, you will notice an exception. The
+ process 1 is visible from every security context. It is visible to
+ please utilities like pstree. But only root processes in security
+ context 0 are allowed to interact with it. NEW
+
+Playing with /usr/sbin/chcontext as root
+
+ The new_s_context system call has a special semantic for root
+ processes running in security context 0 and having the CAP_SYS_ADMIN
+ capability: They can switch to any context they want.
+
+ Normally, new_s_context allocates a new security context by selecting
+ an unused one. It walks all processes and find an ID (an integer) not
+ currently in use.
+
+ But root in security context 0 is allowed to select the context it
+ wants. This allow the main server to control the virtual server. The
+ chcontext utility has the --ctx option to specify the context ID you
+ want.
+
+ To help manage several virtual server, given that the security context
+ 0 can't see processes in other security context, it is a good thing
+ root in the main server (security context 0) is allowed to select a
+ specific context. Cool. But we also need a way to have a global
+ picture showing all processes in all security context. The security
+ context 1 is reserved for this. Security context 1 is allowed to see
+ all processes on the server but is not allowed to interact with them
+ (kill them).
+
+ This special feature was allocated to security context 1 and not 0
+ (the default when you boot) to isolate virtual servers from the main.
+ This way, while maintaining services on the main server, you won't
+ kill service in vservers accidentally.
+
+ Here is an example showing those concepts:
+
+# You must be root, running X
+# We start an xterm in another security context
+/usr/sbin/chcontext xterm &
+# We check, there is no xterm running, yet we can
+# see it.
+ps ax | grep xterm
+# Are we running in security context 0
+# We check the s_context line in /proc/self/status
+cat /proc/self/status
+# Ok we in security context 0
+# Try the security context 1
+/usr/sbin/chcontext --ctx 1 ps ax | grep xterm
+# Ok, we see the xterm, we try to kill it
+/usr/sbin/chcontext --ctx 1 killall xterm
+# No, security context 1 can see, but can't kill
+# let's find out in which security context this
+# xterm is running
+/usr/sbin/chcontext --ctx 1 ps ax | grep xterm
+# Ok, this is PID XX. We need the security context
+/usr/sbin/chcontext --ctx 1 cat /proc/XX/status
+# We see the s_context, this is SS.
+# We want to kill this process
+/usr/sbin/chcontext --ctx SS killall xterm
+
+ chcontext as root
+ The /usr/sbin/vpstree and /usr/sbin/vps commands are supplied by the
+ vserver package. They simply runs ps and pstree in security context 1.
+ NEW
+
+Playing with /usr/sbin/chbind
+
+ The chbind utility is used to lock a process and its children into
+ using a specific IP number. This applies to services and client
+ connection as well. Here are few examples. Execute them as root:
+
+# httpd is running
+netstat -atn | grep ":80 "
+# We see a line like this
+# tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
+# Now we restart httpd, but we lock it so it
+# uses only the main IP of eth0
+/usr/sbin/chbind --ip eth0 /etc/rc.d/init.d/httpd restart
+netstat -atn | grep ":80 "
+# Now we see a line like
+# tcp 0 192.168.1.1:80 0.0.0.0:* LISTEN
+# httpd.conf was not changed.
+# Now, restart it normally
+/etc/rc.d/init.d/httpd restart
+# Now we experiment with client socket
+# Log using telnet
+telnet localhost
+# Once logged in
+netstat -atn | grep ":23 "
+# You should see a line showing a connection from
+# 127.0.0.1 to 127.0.0.1 like this
+# tcp 0 0 127.0.0.1:23 127.0.0.1:32881 ESTABLISHED
+exit
+# Now we do the telnet again, bug forcing it to select a specific IP
+/usr/sbin/chbind --ip eth0 telnet localhost
+# Log in and then execute
+netstat -atn | grep ":23 "
+# You will get something like
+# tcp 0 0 127.0.0.1:23 192.168.3.9:32883 ESTABLISHED
+
+ Using /usr/sbin/chbind
+ NEW
+
+Playing with /usr/sbin/reducecap
+
+ The reducecap utility is used to lower the capability ceiling of a
+ process and child process. Even setuid program won't be able to grab
+ more capabilities.
+
+# You are not root now
+# What is the current capability ceiling
+cat /proc/self/status
+# The capBset line presents mostly 1s.
+/usr/sbin/reducecap --secure /bin/sh
+cat /proc/self/status
+# The capBset now shows many more 0s.
+# The capEff shows all 0s, you have no privilege now
+# We su to root
+su
+cat /proc/self/status
+# capEff is much better now, but there are still many 0s
+# Now we try to see if we are really root
+tail /var/log/messages
+# So far so good, we see the content
+/sbin/ifconfig eth0
+/sbin/ifconfig eth0 down
+# No way, we can't configure the interface. In fact
+# we have lost most privilege normally assigned to root
+exit
+
+ Using /usr/sbin/reducecap
+ NEW
+
+Unification
+
+ Installing a virtual private server copies a linux installation inside
+ a sub-directory. It is a linux inside linux. If you intend to run
+ several vservers on the same box (which you will certainly do :-) ),
+ you will end up using a lot of disk space needlessly: Each vserver is
+ made up hundreds of megabytes of the same stuff. This is a big waste
+ of disk space.
+
+ A solution is to use hard links to connect together common files.
+ Using the package information, we can tell which packages are shared
+ between various vservers, which files are configuration files and
+ which are not (binaries, libraries, resource files, ...). Non
+ configuration files may be linked together saving a huge amount of
+ disk space: A 2 GIG rh7.2 installation shrinks to 38megs.
+
+ Using hard links is cool, but may be a problem. If one vserver
+ overwrite one file, say /bin/ls, then every vserver will inherit that
+ change. Not fun! The solution is to set the immutable bit on every
+ linked file. A file with such a bit on can't be modified, even by
+ root. The only way to modify it is to turn off the bit first. But
+ within a vserver environment, even root is not allowed to perform this
+ task. So linked file, turned immutable, are now safe: They can be
+ shared between vservers without side effects: Cool!
+
+ Well, there is still another side effect. All vservers are now locked
+ with the same files. We are saving a lot of disk space, but we pay a
+ very heavy price for that: Vservers can't evolve independantly.
+
+ A solution was found. A new bit call immutable-linkage-invert was
+ added. Combined with the immutable bit, a file may not be modified,
+ but may be unlinked. Unlinking a file in Unix/Linux means
+ disconnecting the name from the data and removing the name from the
+ directory. If the data is still referenced by one or more vservers, it
+ continue to exist on disk. So doing "rm /bin/ls" on a vserver, removes
+ the file /bin/ls for that vserver and that's all. If all vservers
+ perform this task, then /bin/ls (the data) will be forgotten completly
+ and the disk space will be recovered.
+
+ Using this trick, a vserver gets back its independance. It becomes
+ possible to update packages by using the unlink/update sequence:
+ Unlink /bin/ls first and then put a new copy in place. Luckily,
+ package manager works this way.
+
+ To keep this story short (probably too late :-) ), a unified vserver:
+ * Uses little disk space
+ * Can't interfere with other vservers by changing one of its file.
+ * Can perform package update/deletion normally using standard
+ practice.
+
+ NEW
+
+Applications
+
+ NEW
+
+Virtual server
+
+ The first goal of this project is to create virtual servers sharing
+ the same machine. A virtual server operate like a normal Linux server.
+ It runs normal services such as telnet, mail servers, web servers, SQL
+ servers. In most cases, the services run using standard configuration:
+ The services are running unaware of the virtual server concept.
+
+ Normal system administration is performed with ordinary admin tool.
+ Virtual servers have users account and a root account.
+
+ Packages are installed using standard packages (RPMs for example).
+
+ There are few exceptions. Some configuration can't be done inside a
+ virtual server. Notably the network configuration and the file-system
+ (mount/umount) can't be performed from a virtual server.
+
+ NEW
+
+Per user fire-wall
+
+ The set_ipv4root() system call may be used to differentiate the
+ various users running on an application server. If you want to setup a
+ fire-wall limiting what each user is doing, you have to assign one IP
+ per user, even if they are running application on the same server. The
+ chbind utility may be used to achieve that. NEW
+
+Secure server/Intrusion detection
+
+ While it can be interesting to run several virtual servers in one box,
+ there is one concept potentially more generally useful. Imagine a
+ physical server running a single virtual server. The goal is isolate
+ the main environment from any service, any network. You boot in the
+ main environment, start very few services and then continue in the
+ virtual server. The service in the main environment could be
+
+ * Un-reachable from the network.
+ * The system log daemon. While virtual server could log messages,
+ they would be unable to change/erase the logs. So even a cracked
+ virtual server would not be able the edit the log.
+ * Some intrusion detection facilities, potentially spying the state
+ of the virtual server. For example tripwire could run there and it
+ would be impossible to circumvent its operation or trick it.
+
+ NEW
+
+Fail over servers
+
+ One key feature of a virtual server is the independence from the
+ actual hardware. Most hardware issues are irrelevant for the virtual
+ server installation. For example:
+
+ * Disk layout, partitions and the /etc/fstab configuration. The
+ virtual server has a dummy /etc/fstab.
+ * Network devices.
+ * Processor type, number of processor (kernel selection).
+
+ The main server acts as a host and takes care of all those details.
+ The virtual server is just a client and ignores all the details. As
+ such, the client can be moved to another physical server will very few
+ manipulations. For example, to move the virtual server v1 from one
+ physical one computer to another, you do
+
+ * Turn it off
+ /usr/sbin/vserver v1 stop
+ * Copy the file /etc/vservers/v1.conf to the new server.
+ * Copy all files in /vservers/v1 to the new server
+ * On the new server, start the vserver v1
+ /usr/sbin/vserver v1 start
+
+ As you see, there is no adjustment to do:
+
+ * No user account merging.
+ * No hardware configuration to fix.
+
+ This opens the door to fail over servers. Imagine a backup server
+ having a copy of many virtual servers. It can take over their tasks
+ with a single command. Various options exists for managing this backup
+ server:
+
+ * rsync to synchronize the data.
+ * Network block devices to synchronize the data in real time.
+ * Sharing the installation over a SAN (storage area network).
+ * Heartbeat for automatic monitoring/fail over.
+
+ NEW
+
+Installation
+
+ NEW
+
+The packages
+
+ * The kernel
+ We are supplying a patched 2.4.20 kernel. You will find [50]here
+ the kernel, the .config and the patch.
+ To install the kernel, just untar it. This will create a file
+ /boot/kernel-2.4.20ctx-17 (ctx stands for security context) and a
+ directory /lib/modules/2.4.20ctx-17.
+ Then, you need to update your boot loader. For lilo, you add a
+ section like this at the end of the file /etc/lilo.conf
+
+
+image=/boot/vmlinuz-2.4.20ctx-17
+ label=linux2.4.20ctx-17
+ read-only
+ root=current
+
+ lilo.conf section to add
+ Change the /dev/XXXX to your root partition. Then execute
+ /sbin/lilo.
+ Reboot and select the proper kernel. This kernel is fully
+ compatible with a normal 2.4.20 and will perform without any new
+ configuration. Note that the supplied kernel does not carry all
+ the features and modules found on the various distributions.
+ * The vserver package
+ This package provides the various utilities to make use of those
+ new system calls. The package also provides a complete solution to
+ implement virtual servers. We describe the major components here.
+ + /usr/sbin/chcontext
+ This is the utility to request a new security context. It can
+ be used to lower the capability ceiling. Execute it to learn
+ more.
+ + /usr/sbin/chbind
+ This is the utility to select one IP number and assign it to
+ a process and its children.
+ + /usr/sbin/newvserver (in vserver-admin)
+ Front-end to help create new virtual servers.
+ + /usr/sbin/reducecap
+ This utility is used to lower the capability ceiling of
+ children processes.
+ + /usr/sbin/vdu
+ A trimmed down "du" command reporting space usage of files
+ with a single link. Useful to tell how much space a unified
+ vserver is using.
+ + /usr/sbin/vkill
+ Locate the security context associated with a process, enter
+ it and kill the process. Generally used after you have
+ located a process with vtop, vpstree or vps.
+ + /usr/sbin/vps
+ Execute the ps command in security context 1 so all processes
+ in all vservers are shown. The security context and vserver
+ name are mapped inside the report.
+ + /usr/sbin/vpstree
+ Execute the pstree command in security context 1 so all
+ processes in all vservers are shown.
+ + /usr/sbin/vrpm
+ Apply an rpm command in several (or all) vservers. Useful
+ when you wish to update many vservers with the same package.
+ /usr/sbin/vrpm server1 server2 -- -Uvh /tmp/*.rpm
+ /usr/sbin/vrpm ALL -- -Uvh /tmp/*.rpm
+ After updating many packages in different vservers you may
+ want to re-unify them to recover disk space (and increase
+ cache effectivity). You can do this using the vunify command,
+ or simply by using the --unify option to the vrpm command.
+ After performing the rpm updates, vrpm will trigger the
+ vunify utility on the vservers for the updated packages.
+ /usr/sbin/vrpm --unify server1 server2 -- -Uvh /tmp/*.rpm
+ + /usr/sbin/vserver
+ This is the wrapper to start, stop and administer virtual
+ servers.
+ + /usr/sbin/vserver-stat
+ Produce a small report showing the activity in active
+ security context. The report presents the number of process
+ in each active security context as well as the name of the
+ vserver associated with this context.
+ + /usr/sbin/vtop
+ Execute the top command in security context 1 so all
+ processes in all vservers are shown.
+ + /etc/rc.d/init.d/vservers
+ This is an init script used to start all virtual servers at
+ boot time and stop them at shutdown time. Only virtual
+ servers with ONBOOT=yes are started at boot time. All
+ vservers are stopped at shutdown time.
+ + /etc/rc.d/init.d/rebootmgr
+ This is a daemon listening to requests from virtual servers.
+ It can either restart or stop a virtual server. The
+ /sbin/vreboot and /sbin/vhalt utilities are used to send
+ request to the reboot manager.
+ + /sbin/vreboot and /sbin/vhalt
+ Those utilities are copied in each virtual server. They
+ connect to the reboot manager (rebootmgr) server using the
+ /dev/reboot Unix domain socket and request either a restart
+ or a stop of the virtual server. The reboot manager issue
+ either a "/usr/sbin/vserver vserver restart" or
+ "/usr/sbin/vserver vserver stop" command. This allows the
+ virtual server administrator to test if all automatic service
+ are properly restarted at boot time.
+ + /usr/lib/vserver/vdu
+ This is a limited clone of the du command. It skips file with
+ more than one link. It is used to evaluate the disk usage of
+ an unified vserver. Using the normal du for this task is
+ misleading since it will count all unified files.
+
+ NEW
+
+Setting a virtual server
+
+ To set a virtual server, you need to copy in a sub-directory a Linux
+ installation. One way to achieve that is to copy some parts of the the
+ current server by issuing the command vserver XX build, where XX is
+ the name of the virtual server (pick one). This basically does (Well,
+ it does a little more than that, but this give you an idea):
+
+mkdir /vservers/XX
+cd /vservers/XX
+cp -ax /sbin /bin /etc /usr /var /dev /lib .
+mkdir proc tmp home
+chmod 1777 tmp
+
+ Building a virtual server
+
+ This is normally done using the command /usr/sbin/newvserver. This is
+ a text mode/graphical front-end allowing to setup the vserver runtime
+ and configure it. NEW
+
+Basic configuration of the virtual server
+
+ A virtual private server has a few settings. They are defined in the
+ file /etc/vservers/XX.conf where XX is the name of the virtual server.
+ This is a simple script like configuration. Here are the various
+ parameters:
+
+ * IPROOT
+ In general, each virtual server is tied to one IP using the new
+ set_ipv4root system call. This way several servers may run the
+ same services without conflict. Enter the IP number (a name is
+ also valid if defined in the DNS).
+ Since kernel ctx-12, you can assign more than one IP number to a
+ vserver. Enter them separated by spaces and don't forget to
+ enclose them with quotes.
+ Bu default, all IPs are configured as an IP alias on the IPROOTDEV
+ device (if defined). If you want to attach the various IP numbers
+ to different devices, specify the device as a prefix to the IP
+ number like this:
+
+IPROOT="eth0:192.168.1.2 eth1:192.168.3.1 192.168.1.4"
+
+ IPROOT using multiple devices
+ In the example above, the IP 192.168.1.4 will be installed as an
+ IP alias on the device IPROOTDEV.
+ Use "IPROOT=0.0.0.0" or "IPROOT=" if you do not want to tie the
+ vserver at all. It will be allowed to use any IP available on the
+ server.
+ * IPROOTDEV
+ This is the network device use to setup the IP alias defined by
+ IPROOT. This is generally eth0. If you define this variable, the
+ IP alias will be configured when you start the virtual server and
+ un-configure when you stop it.
+ * IPROOTMASK
+ Netmask used to setup the IP alias. Uses the netmask of the
+ IPROOTDEV device by default. Seldom used.
+ If you have several IPs on one vserver and want to have different
+ netmask for each, use the following syntax:
+
+IPROOT="eth0:192.168.1.2 eth1:192.168.3.1/255.255.255.192"
+
+ IPROOT using different netmask
+ 192.168.1.2 will use the netmask of eth0, while 192.168.3.1 will
+ use the specified netmask: 255.255.255.192.
+ * IPROOTBCAST
+ Broadcast address used to setup the IP alias. Uses the broadcast
+ of the IPROOTDEV device by default. Seldom used.
+ * ONBOOT
+ The vserver package supplies the vservers service. This service is
+ installed in the main server. It is used to start and stop the
+ virtual server at boot and shutdown time.
+ Virtual server with ONBOOT=yes will be started and stopped
+ properly like any other services of the main server.
+ Once a virtual server is properly configured, it is a good idea to
+ set this parameter to yes.
+ * S_CAPS
+ You enter here the various capability you want to grant to the
+ vserver. By default, a vserver is left with much less capabilities
+ than the root server. For example, a vserver is not allowed to use
+ raw socket. This explains why the ping command fails. S_CAPS lets
+ you enumerate the capability you want to keep in the vserver.
+ CAP_NET_RAW will give back ping ability for example.
+ * S_CONTEXT
+ This is optional. In general the security context ID is selected
+ by the kernel. An unused one is selected. If you select an ID (an
+ integer greater than 1), make sure you select a different one for
+ each server. Again, in most cases, you do not need to select one.
+ Leave the line commented.
+ * S_DOMAINNAME
+ A virtual server may have a different NIS domainname than the main
+ server. You set it here. If you leave the field empty, the vserver
+ will inherit the same NIS domain as the root server. Enter "none"
+ to reset the NIS domain name for this vserver.
+ * S_HOSTNAME
+ Many services (Apache for one) use the host name to setup some
+ defaults. A virtual server may have a different host name than the
+ main server. It is a good idea to fill this line.
+ * S_NICE
+ The is an optional priority level. It is an integer ranging
+ between from -20 to 19. Well it is the nice level in fact, so -20
+ means the highest priority and 19 the lowest (the highest nice
+ level). All processes in the virtual server will be locked to this
+ level (or higher niceness).
+ Event root is locked and can't get more priority.
+ Note that this has limited usefulness. The kernel does not
+ differentiate processes running in different security context for
+ scheduling (for now :-) ). This means that a virtual servers
+ running many low priority processes may nevertheless claim a large
+ share of CPU.
+ * S_FLAGS
+ This is used to set various flags. Here are the supported flags:
+ + lock
+ This flags prevents the vserver from setting new security
+ contexts.
+ + sched
+ It kind of unifies the processes in a vserver from a
+ scheduler view point. All processes are weighted as single
+ one when compared to other processes in the real server. This
+ prevents a vserver from taking to much CPU resources.
+ + nproc
+ Make the ulimit maximum user process global to the vserver.
+ + private
+ Once set on a vserver security context, no other process can
+ enter it. Even the root server is unable to enter the
+ context. It can see the process list using security context
+ 1, but can't signal or trace the process.
+ + fakeinit
+ This assigned the current process so it works like the
+ process number 1. Using this trick, a normal /sbin/init may
+ be run in a vserver. The /usr/sbin/vserver command will use
+ /sbin/init to start and stop a vserver. A properly configured
+ /etc/inittab is needed though.
+ o Processes loosing their parent are reparent to this
+ process.
+ o getppid() done by child process of this process returns
+ 1.
+ o getpid() done by this process returns 1.
+ o This process is not shown in /proc since process number
+ 1 is always shown.
+ o An "initpid" entry is available in /proc/*/status to
+ tell which process is the fake init process.
+ * ULIMIT
+ This contains the command line option to the ulimit shell command.
+ You enter here whatever parameters accepted by ulimit. Here is the
+ default when you create a new vserver:
+
+ULIMIT="-H -u 1000"
+
+ Default vserver ulimit
+ Normally ulimit settings only affects users independantly. So
+ limiting a vserver this way, limit each user processes
+ independantly in the vserver. Using special flags in the S_FLAGS
+ option, you can make those ulimit settings global to the vserver.
+ The example above used with the nproc parameter make the maximum
+ number of process global. In this case, a maximum of 1000
+ processes is available to all users in the vserver.
+
+ NEW
+
+Entering the virtual server
+
+ It is possible to enter a virtual server context from the main server
+ just by executing /usr/sbin/vserver XX enter (where XX is the virtual
+ server name).
+
+ This creates a shell. From there you can execute anything
+ administrative you normally do on a Linux server.
+
+ NEW
+
+Configuring the services
+
+ The virtual server can run pretty much any services. Many pseudo
+ services, such as network configuration are useless (the server is
+ already configured). After building the environment, enter it (without
+ starting the virtual server) using the vserver name enter command.
+ Then using a tool like Linuxconf (control/control service activity) ,
+ or ntsysv, browse all service and keep only the needed ones.
+
+ So after building the server, you enter it and you select the service
+ you need in that server. Many services such as network, and apmd are
+ either useless or won't run at all in the virtual server. They will
+ fail to start completely. NEW
+
+Starting/Stopping the virtual server
+
+ Virtual server with ONBOOT=yes will be started and stopped like any
+ other services of the main server. But you can stop and start a
+ virtual server at any time. Starting a server means that all
+ configured service will be started. Stopping it means that all
+ configured services will be stopped and then all remaining process
+ will be killed.
+
+ Oddly, starting a virtual server does not mean much. There is no
+ overhead. No monitoring process or proxy or emulator. Starting a
+ virtual server with 4 services is the same as running those 4 services
+ in the main server, at least performance wise (the service inside a
+ virtual server are locked inside the security context).
+
+ The following commands may be used to control a virtual server:
+
+ * /usr/sbin/vserver server start
+ * /usr/sbin/vserver server stop
+ * /usr/sbin/vserver server restart
+ * /usr/sbin/vserver server running
+ * /usr/sbin/vserver server enter
+ * /usr/sbin/vserver server exec some commands ...
+ * /usr/sbin/vserver server suexec user some commands ...
+ * /usr/sbin/vserver server service service-name
+ start/stop/restart/status
+ * /usr/sbin/vserver server status
+
+ The running command prints if there are any processes running in the
+ virtual server context.
+
+ Please note
+
+ The processes running in a virtual server are invisible from the main
+ server. The opposite is true. This is very important. Managing the
+ main server must not cause problems to the various virtual servers.
+ For example, doing killall httpd will kill all the httpd processes in
+ the current context ( the main server or a virtual one).
+
+ NEW
+
+Starting/Stopping all the virtual servers
+
+ The sysv script /etc/rc.d/init.d/vserver is used to start and stop the
+ virtual server at boot and shutdown time. It may be used at any time
+ to operate all virtual servers. The following commands are supported:
+
+ * /etc/rc.d/init.d/vservers start
+ * /etc/rc.d/init.d/vservers stop
+ * /etc/rc.d/init.d/vservers restart
+ * /etc/rc.d/init.d/vservers status
+
+ The status command reports the running status of every virtual server.
+ NEW
+
+Restarting a virtual server from inside
+
+ A virtual server administrator is not allowed to reboot the machine
+ (the kernel). But it is useful to restart his virtual server from
+ scratch. This allow him to make sure all the services are properly
+ configured to start at boot time.
+
+ The /sbin/vreboot and /sbin/vhalt utilities are installed in each
+ virtual server so they can request a restart or stop.
+
+ The rebootmgr service must be enabled in the main server.
+
+ NEW
+
+Executing tasks at vserver start/stop time
+
+ You can setup a script called /etc/vservers/XX.sh where XX is the name
+ of the virtual server. This script will be called four time:
+
+ * Before starting the vserver
+ * After starting it.
+ * Before stopping it.
+ * After stopping it.
+
+ You generally perform tasks such as mounting file system (mapping some
+ directory in the vserver root using "mount --bind").
+
+ Here is an example where you map the /home directory as the vserver
+ /home directory.
+
+#!/bin/sh
+case $1 in
+pre-start)
+ mount --bind /home /vservers/$2/home
+ ;;
+post-start)
+ ;;
+pre-stop)
+ ;;
+post-stop)
+ umount /vservers/$2/home
+ ;;
+esac
+
+ /etc/vservers/XX.sh
+ NEW
+
+Issues
+
+ There are some common problem you may encounter. Here they are.
+
+ * The main server is not tied (by default) to any ipv4root. So if
+ the main server has already some service running they are probably
+ binding some UDP or TCP ports using the address 0.0.0.0. Once a
+ process has bound a service with the address 0.0.0.0 (see the
+ LISTEN lines when executing the "netstat -a" command), no other
+ process can bind the same port, even with a specific address.
+ The solution is to start the services of the main server using the
+ chbind utility to trap them in one ipv4root. For example
+
+/sbin/chbind --ip eth0 /etc/rc.d/init.d/httpd start
+
+ Assigning on IP to a service
+ will limit Apache to the IP address of the eth0 interface. without
+ configuration changes (in httpd.conf). It is probably a good idea
+ to start the following services in the main server this way,
+ because they will be run by virtual servers as well.
+
+ * httpd
+ * sshd
+ * xinetd
+
+ To ease this, the vserver package supplies the following services:
+ v_httpd, v_sshd, v_smb and v_xinetd. Disable the corresponding
+ services and enable the v_ services and you will lock those services
+ on a single IP.
+
+ Cleanup rc.local. This is probably not doing anything useful.
+
+ NEW
+
+How real is it ?
+
+ The project is new. So far, experiments have shown very little
+ restrictions. Service works the same in a virtual server. Further,
+ performance is the same. And there is a high level of isolation
+ between the various virtual servers and the main server. NEW
+
+Features
+
+ There are various tricks one can use to make the virtual servers more
+ secure.
+
+ * Putting a fire-wall on the box and limiting access to a virtual
+ services from another one.
+ * Using port redirection to allow one virtual server to logically
+ bind several IPs. One virtual server could run several web virtual
+ host this way.
+
+ NEW
+
+Future directions
+
+ NEW
+
+User controlled security box
+
+ By combining the capabilities, the s_context, the ipv4root and the
+ AclFS (component of the [51]virtualfs package), we can produce a user
+ level tool allowing controlled access to the user own resources. For
+ example the user may download any program he wants and execute them
+ under control. Whenever the program tries to access something not
+ specified by the user, a popup is presented and the user may choose to
+ terminate the program or allow the access.
+
+ NEW
+
+Kernel enhancements
+
+ We expect to see some wider usage of the virtual servers. As usage
+ grow, we expect to see needs for more control. Here are some ideas.
+
+ NEW
+
+Per context disk quota
+
+ If one installs virtual servers and grant access to less trusted
+ users, he may want to limit the disk space used. Since a virtual
+ server may create new user accounts and run processes with any user ID
+ it wants, the current kernel disk quota is not powerful enough. First,
+ it can't differentiate between user ID 100 in one virtual server and
+ user ID 100 in another one.
+
+ Further, the main administrator may want to control disk space
+ allocated to the virtual server on a server per server basis,
+ unrelated to the various user ID in use in those virtual servers.
+
+ The kernel has already user and group disk quota. Adding security
+ context disk quota should be easily done.
+
+ To differentiate between user IDs in virtual servers, the kernel could
+ coin together the security context and the user id to create a unique
+ ID. The kernel 2.4 now supports 32 user ID, so combining security
+ context and user ID in a single 32 bits number should be acceptable.
+
+ NEW
+
+Global limits
+
+ The kernel has supports for user limit (memory, processes file
+ handles). With virtual server, we may want to limit the resources used
+ by all processes in the virtual server. The security context would be
+ used as the key here. The following resources could be limited on a
+ security context basis (as opposed to user or process basis)
+
+ * Memory used
+ * Processes number
+ (Done: This is now supported with the nproc flag in the kernel
+ 2.4.16ctx-4. By default a new vserver is limited to 1000 processes
+ maximum, configurable).
+ * File handles
+
+ NEW
+
+Scheduler
+
+ The scheduler may become security context aware. It could potentially
+ use this to provide some fairness and control priority based on
+ context. Currently the scheduler is process oriented and does not
+ group process together to qualify their priorities. For example, a
+ user running 10 compilations will get more CPU than another user
+ running a single compilation.
+
+ Currently, it is possible to raise the nice (lower priority) for all
+ processes in a virtual server. This can't be reversed, so you are
+ setting an upper limit on priority (Just set the S_NICE variable in
+ the vserver configuration file). Note that a virtual server may still
+ start many low priority processes and this can grab significant share
+ of the CPU. A global per security context might be needed to really
+ provide more control and fairness between the various virtual servers.
+
+ Done: The sched security context flag group all process in a vserver
+ so their priority is kind of unified. If you have 50 processes running
+ full speed in one vserver, they will take as much CPU resource than a
+ single process in the root server. A vserver can't starve the other...
+ NEW
+
+Security issues
+
+ The current kernel + patch provides a fair level of isolation between
+ the virtual servers. User root can't take over the system: He sees
+ only his processes, has only access to his area of the file system
+ (chroot) and can't reconfigure the kernel. Yet there are some
+ potential problems. They are fixable. As usage grows, we will know if
+ they are real problems. Comments are welcome:
+
+ NEW
+
+/dev/random
+
+ Writing to /dev/random is not limited by any capability. Any root user
+ (virtual included) is allowed to write there. Is this a problem ?
+
+ (kernel expert think it is ok) NEW
+
+/dev/pts
+
+ /dev/pts is a virtual file-system used to allocate pseudo-tty. It
+ presents all the pseudo-tty in use on the server (including all
+ virtual server). User root is allowed to read and write to any
+ pseudo-tty, potentially causing problems on other vservers.
+
+ Starting with the ctx-6 patch, /dev/pts is virtualised. Although the
+ file numbers are allocated from a single pool, a vserver only see the
+ pseudo-tty it owns. NEW
+
+Network devices
+
+ Anyone can list the network devices configurations. This may inform a
+ virtual user that another vserver is on the same physical server. By
+ using as much resources as possible in his own vservers, a malicious
+ user could slow down the other server. Modification to the scheduler
+ explained above could stop this.
+
+ Starting with the ctx-6 patch, a vserver only see the device
+ corresponding to its IP number. NEW
+
+Alternative technologies
+
+ Using virtual servers may be a cost effective alternative to several
+ independent real servers. You get the administrative independence of
+ independent servers, but share some costs including operation costs.
+
+ Other technologies exist offering some of the advantages talked in
+ this document as well as other. Two technologies are available on
+ various hardware platform: Virtual machines and partitioning, NEW
+
+Virtual machines
+
+ This has been available for mainframes for a while now. You can boot
+ several different OS at once on the same server. This is mainly used
+ to isolate environments. For example, you can install the new version
+ of an OS on the same server, even while the server is running the
+ current version. This allows you to test and do a roll-out gracefully.
+
+ The advantages of virtual machines are:
+
+ * Total flexibility. You can run many different OS and different
+ version of the same OS, all at once.
+ * Robustness. You have total isolation. One OS may crash without
+ affecting the other.
+ * Resource management. You can effectively limit the resources taken
+ by one OS.
+ * Hardware Independence. The client OS is using virtual disks
+ provided by the host OS.
+
+ This technology is not directly available on PCs. The Intel x86
+ architecture does not support visualization natively. Some products
+ nevertheless have appeared and provide this. You can run Linux inside
+ Linux, or this other OS (Which BTW has a logo showing a window flying
+ in pieces, which quite frankly tells everything about it).
+
+ The solutions available on PCs carry most of the advantages of the
+ virtual machines found on mainframe, except for performance. You can't
+ run that many virtual Linux's using this technology and expect it to
+ fly. One example of this technology is [52]vmware, which is quite
+ useful, especially if you must run this other OS... vmware may be used
+ to run Linux inside Linux, even test Linux installation while running
+ linux... NEW
+
+Partitioning
+
+ Partitioning (domains ?) is a way to split the resources of a large
+ server so you end up with independent servers. For example, you can
+ take a 20 CPUs server and create 3 servers, two with 4 CPUs and one
+ with 12. You can very easily re-assign CPUs to servers in case you
+ need more for a given tasks.
+
+ This technology provides full Independence, but much less flexibility.
+ If your 12 CPUs server is not working much, the 4 CPUs one can't
+ borrow some CPUs for 5 minutes. NEW
+
+Limitation of those technologies
+
+ Oddly, one disadvantage of those technologies is a side effect of
+ their major advantage: Total Independence. Each virtual server is
+ running its own kernel. Cool. This makes the following tasks more
+ difficult or impossible:
+
+ * Sharing administrative tasks such as backup. The virtual servers
+ are using volumes in the host server. The host server can't handle
+ the files in those volumes directly without interfering with the
+ client OS. It has to use some services of the client OS to access
+ the file.
+ The vserver solution does not have this limitation since the
+ virtual servers are living in the same file-system, sharing the
+ same kernel.
+ * Task monitoring. The virtual servers run their own kernel. As
+ such, the host OS can't spy on the tasks and check for intrusion
+ for example.
+ * Disk space. Virtual servers are using either volumes or full
+ devices in the host server. This space is pre-allocated to the
+ maximum needed by the server. You end up with a lot of wasted disk
+ space. Imagine running 100 virtual servers this way and allocating
+ say 10 gigs to each. You get the picture. The vserver solution is
+ sharing a common file-system so the free disk space is available
+ to all.
+ Further, if you are running the same Linux distribution in the
+ virtual servers, you can unify the disk space using hard link and
+ immutable attributes. The /usr/lib/vserver/vunify was created to
+ test that. Using information found in the rpm package the script
+ links the files, except configuration ones.
+ Testing vunify on a vserver installed with a RedHat 6.2
+ distribution, unifying the packages glibc, binutils, perl, and
+ bash saved 60 megs. Quite a few packages are not changing often
+ and could be unified.
+ Vservers do not need kernel packages and hardware configuration
+ tools. This also contribute to save disk space.
+ * File system sharing
+ A little the same as above. You can't share file system easily
+ between vservers unless you use network services (often slower).
+ Using "mount --bind", it is very easy to "map" any directory of
+ the root server in several vservers, providing raw speed access
+ (and even sharing the disk cache).
+
+ NEW
+
+Conclusion
+
+ Virtual servers are interesting because they can provide a higher
+ level of security while potentially reducing the administration task.
+ Common operation such as backup, are shared between all servers.
+ Services such as monitoring may be configured once.
+
+ A Linux server can run many services at once with a high level of
+ reliability. As servers are evolving, more and more services are
+ added, often unrelated. Unfortunately there are few details here and
+ there, making the server more complex than it is in reality. When one
+ wants to move one service to another server, it is always a little
+ pain: Some user accounts have to be moved and some configuration
+ files. A lot of hand tweaking.
+
+ By installing services in separate virtual servers, it becomes much
+ easier to move services around (just by moving a directory although a
+ big one).
+
+ Virtual servers may become a preferred way to install common Linux
+ servers. NEW
+
+Download
+
+ The ftp site for this project is
+ [53]ftp://ftp.solucorp.qc.ca/pub/vserver . You will find there the
+ following components.
+
+ * [54]kernel-2.4.20ctx-17.tar.gz
+ [55]kernel-2.4.20ctxsmp-17.tar.gz
+ A pre-compiled kernel for Pentium class machine and up. An SMP
+ kernel is also supplied.
+ * [56]vserver-0.22-1.src.rpm
+ The source RPM for the vserver utilities
+ * [57]vserver-0.22-1.i386.rpm
+ A compiled rpm for RedHat 7.x and up. Should work on any recent
+ distribution (glibc 2.2). You need a recent distribution to
+ operate a kernel 2.4 anyway.
+ * [58]vserver-admin-0.22-1.i386.rpm
+ Contains the command /usr/sbin/newvserver. It is a GUI to create
+ vservers. It requires the linuxconf-utils and linuxconf-lib
+ packages. You can get them from [59]here. linuxconf itself is not
+ needed though.
+ * [60]vserver-0.22.src.tar.gz
+ The vserver utilities source
+ * [61]patch-2.4.20ctx-17.gz
+ The patch against Linux 2.4.20
+ * [62]patches
+ The various relative patches (ctxN-ctxN+1)
+
+ NEW
+
+References
+
+ This project is maintained by Jacques Gelinas [63]jack@solucorp.qc.ca
+
+ The vserver package is licensed under the GNU PUBLIC LICENSE.
+
+ A FAQ can be found at
+ [64]http://www.solucorp.qc.ca/howto.hc?projet=vserver
+
+ A mailing list has been created to exchange about this project. It is
+ [65]vserver@solucorp.qc.ca .You can subscribe [66]here
+
+ The mailing list is archived [67]here.
+
+ The change logs for the vserver package are [68]here .
+
+ The official copy of this document is found at
+ [69]http://www.solucorp.qc.ca/miscprj/s_context.hc
+
+ This document was produced using the [70]TLMP documentation system
+
+ [71]Top
+ [72]Back to project page
+ [73]About tlmpdoc and cookies
+ Document maintained by Jacques Gélinas ([74]jack@solucorp.qc.ca)
+ Last update: Wed Apr 16 11:22:22 2003
+
+Références
+
+ 1. http://remtk/solucor/miscprj/s_context.hc?s1=1&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 2. http://remtk/solucor/miscprj/s_context.hc?s1=1&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 3. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 4. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 5. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 6. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 7. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=4&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 8. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=5&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 9. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 10. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=1&s4=0&full=0&prjstate=1&nodoc=0
+ 11. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=2&s4=0&full=0&prjstate=1&nodoc=0
+ 12. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=3&s4=0&full=0&prjstate=1&nodoc=0
+ 13. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=6&s3=4&s4=0&full=0&prjstate=1&nodoc=0
+ 14. http://remtk/solucor/miscprj/s_context.hc?s1=2&s2=7&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 15. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 16. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 17. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 18. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 19. http://remtk/solucor/miscprj/s_context.hc?s1=3&s2=4&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 20. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 21. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 22. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 23. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 24. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=4&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 25. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=5&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 26. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=6&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 27. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=7&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 28. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=8&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 29. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=9&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 30. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=10&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 31. http://remtk/solucor/miscprj/s_context.hc?s1=4&s2=11&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 32. http://remtk/solucor/miscprj/s_context.hc?s1=5&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 33. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 34. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 35. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 36. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=1&s4=0&full=0&prjstate=1&nodoc=0
+ 37. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=2&s4=0&full=0&prjstate=1&nodoc=0
+ 38. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=3&s4=0&full=0&prjstate=1&nodoc=0
+ 39. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=0&full=0&prjstate=1&nodoc=0
+ 40. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=1&full=0&prjstate=1&nodoc=0
+ 41. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=2&full=0&prjstate=1&nodoc=0
+ 42. http://remtk/solucor/miscprj/s_context.hc?s1=6&s2=2&s3=4&s4=3&full=0&prjstate=1&nodoc=0
+ 43. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 44. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=1&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 45. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=2&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 46. http://remtk/solucor/miscprj/s_context.hc?s1=7&s2=3&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 47. http://remtk/solucor/miscprj/s_context.hc?s1=8&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 48. http://remtk/solucor/miscprj/s_context.hc?s1=9&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 49. http://remtk/solucor/miscprj/s_context.hc?s1=10&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 50. ftp://ftp.solucorp.qc.ca/pub/vserver
+ 51. http://www.solucorp.qc.ca/virtualfs
+ 52. http://www.vmware.com/
+ 53. ftp://ftp.solucorp.qc.ca/pub/vserver
+ 54. ftp://ftp.solucorp.qc.ca/pub/vserver/kernel-2.4.20ctx-17.tar.gz
+ 55. ftp://ftp.solucorp.qc.ca/pub/vserver/kernel-2.4.20ctxsmp-17.tar.gz
+ 56. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-0.22-1.src.rpm
+ 57. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-0.22-1.i386.rpm
+ 58. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-admin-0.22-1.i386.rpm
+ 59. http://www.solucorp.qc.ca/linuxconf/download.hc
+ 60. ftp://ftp.solucorp.qc.ca/pub/vserver/vserver-0.22.src.tar.gz
+ 61. ftp://ftp.solucorp.qc.ca/pub/vserver/patch-2.4.20ctx-17.gz
+ 62. ftp://ftp.solucorp.qc.ca/pub/vserver/patches
+ 63. mailto:jack@solucorp.qc.ca
+ 64. http://www.solucorp.qc.ca/howto.hc?projet=vserver
+ 65. mailto:vserver@solucorp.qc.ca
+ 66. http://www.solucorp.qc.ca/mlist/index.hc?list=vserver
+ 67. http://www.paul.sladen.org/vserver/archives/
+ 68. http://www.solucorp.qc.ca/changes.hc?projet=vserver
+ 69. http://www.solucorp.qc.ca/miscprj/s_context.hc
+ 70. http://www.solucorp.qc.ca/tlmp
+ 71. http://remtk/solucor/miscprj/s_context.hc?s1=0&s2=0&s3=0&s4=0&full=0&prjstate=1&nodoc=0
+ 72. http://remtk/solucor/miscprj/s_context.hc
+ 73. http://www.solucorp.qc.ca/tlmp/tlmpdoc.hc
+ 74. mailto:jack@solucorp.qc.ca
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+lib_SRCS = lib/syscall.c
+lib_HDRS = lib/vserver.h
+
+lib_lib_LIBS = lib/libvserver.a
+
+lib_libvserver_a_SOURCES = lib/syscall.c
+lib_libvserver_a_CPPFLAGS = -I$(kernelincludedir)
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on syscall.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This tells the system call number for new_s_context and set_ipv4root
+ using /proc/self/status. This helps until the vserver project is
+ included officially in the kernel (and has its own syscall).
+
+ We rely on /proc/self/status to find the syscall number.
+
+ If it is not there, we rely on adm/unistd.h.
+
+ If this file does not have those system calls (not a patched kernel source)
+ we rely on static values in this file.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <syscall.h>
+#include <asm/unistd.h>
+
+#include "vserver.h"
+
+// Here is the trick. We keep a copy of the define, then undef it
+// and then later, we try to locate the value reading /proc/self/status
+// If this fails, we have the old preserved copy.
+static int def_NR_set_ipv4root = 227;
+#undef __NR_set_ipv4root
+
+static int __NR_set_ipv4root_rev0;
+static int __NR_set_ipv4root_rev1;
+static int __NR_set_ipv4root_rev2;
+static int __NR_set_ipv4root_rev3;
+static int rev_ipv4root=0;
+
+
+static _syscall1(int, set_ipv4root_rev0, unsigned long, ip)
+static _syscall2(int, set_ipv4root_rev1, unsigned long, ip, unsigned long, bcast)
+static _syscall3(int, set_ipv4root_rev2, unsigned long *, ip, int, nb, unsigned long, bcast)
+static _syscall4(int, set_ipv4root_rev3, unsigned long *, ip, int, nb, unsigned long, bcast, unsigned long *, mask)
+
+static int def_NR_new_s_context = 226;
+#undef __NR_new_s_context
+static int __NR_new_s_context_rev0;
+static int __NR_new_s_context_rev1;
+static int rev_s_context=0;
+
+static _syscall3(int, new_s_context_rev0, int, newctx, int, remove_cap, int, flags)
+static _syscall4(int, new_s_context_rev1, int, nbctx, int *, ctxs, int, remove_cap, int, flags)
+
+#undef __NR_set_ctxlimit
+static int __NR_set_ctxlimit=-1;
+static int rev_set_ctxlimit=-1;
+
+static _syscall2 (int, set_ctxlimit, int, resource, long, limit)
+
+#undef __NR_chrootsafe
+static int __NR_chrootsafe=-1;
+static int rev_chrootsafe=-1;
+
+static _syscall1 (int, chrootsafe, const char *, dir)
+
+static void init()
+{
+ static int is_init = 0;
+ if (!is_init){
+ FILE *fin = fopen ("/proc/self/status","r");
+ __NR_set_ipv4root_rev0 = def_NR_set_ipv4root;
+ __NR_set_ipv4root_rev1 = def_NR_set_ipv4root;
+ __NR_set_ipv4root_rev2 = def_NR_set_ipv4root;
+ __NR_set_ipv4root_rev3 = def_NR_set_ipv4root;
+ __NR_new_s_context_rev1 = def_NR_new_s_context;
+ if (fin != NULL){
+ char line[100];
+ while (fgets(line,sizeof(line)-1,fin)!=NULL){
+ int num;
+ char title[100],rev[100];
+ rev[0] = '\0';
+ if (sscanf(line,"%s %d %s",title,&num,rev)>=2){
+ if (strcmp(title,"__NR_set_ipv4root:")==0){
+ __NR_set_ipv4root_rev0 = num;
+ __NR_set_ipv4root_rev1 = num;
+ __NR_set_ipv4root_rev2 = num;
+ __NR_set_ipv4root_rev3 = num;
+ if (strncmp(rev,"rev",3)==0){
+ rev_ipv4root = atoi(rev+3);
+ }
+ }else if (strcmp(title,"__NR_set_ctxlimit:")==0){
+ __NR_set_ctxlimit = num;
+ if (strncmp(rev,"rev",3)==0){
+ rev_set_ctxlimit = atoi(rev+3);
+ }
+ }else if (strcmp(title,"__NR_chrootsafe:")==0){
+ __NR_chrootsafe = num;
+ if (strncmp(rev,"rev",3)==0){
+ rev_chrootsafe = atoi(rev+3);
+ }
+ }else if (strcmp(title,"__NR_new_s_context:")==0){
+ __NR_new_s_context_rev0 = num;
+ __NR_new_s_context_rev1 = num;
+ if (strncmp(rev,"rev",3)==0){
+ rev_s_context = atoi(rev+3);
+ }
+ }
+ }
+ }
+ fclose (fin);
+ }
+ is_init = 1;
+ }
+}
+
+void vserver_init()
+{
+ init();
+}
+
+int call_new_s_context(int nbctx, int ctxs[], int remove_cap, int flags)
+{
+ int ret = -1;
+ init();
+ if (rev_s_context == 0){
+ if (nbctx > 1){
+ errno = EINVAL;
+ fprintf (stderr,"The current kernel does not support new_s_context revision 1\n");
+ }else if (nbctx == 0){
+ ret = new_s_context_rev0(-2,remove_cap,flags);
+ }else if (nbctx == 1){
+ ret = new_s_context_rev0(ctxs[0],remove_cap,flags);
+ }
+ }else{
+fprintf (stderr,"new_s_context rev1 %d %d\n",nbctx,ctxs[0]);
+ ret = new_s_context_rev1(nbctx,ctxs,remove_cap,flags);
+ }
+ return ret;
+}
+
+int call_set_ipv4root (
+ unsigned long ip[],
+ int nb,
+ unsigned long bcast,
+ unsigned long mask[])
+{
+ init();
+ if (rev_ipv4root == 0){
+ if (nb > 1){
+ fprintf (stderr,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n");
+ }
+ return set_ipv4root_rev0 (ip[0]);
+ }else if (rev_ipv4root == 1){
+ if (nb > 1){
+ fprintf (stderr,"set_ipv4root: Several IP number specified, but this kernel only supports one. Ignored\n");
+ }
+ return set_ipv4root_rev1 (ip[0],bcast);
+ }else if (rev_ipv4root == 2){
+ return set_ipv4root_rev2 (ip,nb,bcast);
+ }else if (rev_ipv4root == 3){
+ return set_ipv4root_rev3 (ip,nb,bcast,mask);
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+int call_chrootsafe (const char *dir)
+{
+ init();
+ if (rev_chrootsafe == -1){
+ fprintf (stderr,"chrootsafe: Unsupported system call, update kernel\n");
+ }else if (rev_chrootsafe == 0){
+ return chrootsafe (dir);
+ }else{
+ fprintf (stderr,"chrootsafe: kernel support version %d, application expects version 0\n"
+ ,rev_chrootsafe);
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+/*
+ Return != 0 if chrootsafe is available
+*/
+int has_chrootsafe()
+{
+ init();
+ return rev_chrootsafe != -1;
+}
+
+int call_set_ctxlimit (int res, long limit)
+{
+ init();
+ if (rev_set_ctxlimit == -1){
+ fprintf (stderr,"set_ctxlimit: Unsupported system call, update kernel\n");
+ }else if (rev_set_ctxlimit == 0){
+ return set_ctxlimit (res,limit);
+ }else{
+ fprintf (stderr,"set_ctxlimit: kernel support version %d, application expects version 0\n"
+ ,rev_set_ctxlimit);
+ }
+ errno = EINVAL;
+ return -1;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#ifndef H_VSERVER_SYSCALL_H
+#define H_VSERVER_SYSCALL_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int call_new_s_context(int nbctx, int ctxs[], int remove_cap, int flags);
+int call_set_ipv4root (unsigned long ip[], int nb,
+ unsigned long bcast, unsigned long mask[]);
+int call_chrootsafe (const char *dir);
+int has_chrootsafe();
+int call_set_ctxlimit (int res, long limit);
+
+void vserver_init();
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+## $Id$ ---*- makefile -*---
+
+## Copyright (C) 2002 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.
+##
+
+ChangeLog.sed:
+ test "$(srcdir)" != "."
+
+ChangeLog: ChangeLog.sed Makefile
+ if test "$(srcdir)" = "." -a -d CVS; then \
+ rcs2log -l 0 -c /dev/stdout | sed -f $< >$@; \
+ fi
+
+.PHONY: ChangeLog
--- /dev/null
+dnl $Id$
+
+dnl Copyright (C) 2002 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; version 2 of the License.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+AC_DEFUN([__ENSC_CHECK_WARNFLAGS],
+[
+ warn_flags="-Werror -W"
+ AC_MSG_CHECKING([whether the $1-compiler accepts ${warn_flags}])
+ AC_LANG_PUSH($1)
+ old_CFLAGS="${$3}"
+ $3="$warn_flags"
+ AC_TRY_COMPILE([inline static void f(){}],
+ [],
+ [ensc_sys_compilerwarnflags_$2=${warn_flags}],
+ [ensc_sys_compilerwarnflags_$2=])
+ AC_LANG_POP($1)
+ $3="$old_CFLAGS"
+
+ if test x"${ensc_sys_compilerwarnflags_$2}" = x; then
+ AC_MSG_RESULT([no])
+ else
+ AC_MSG_RESULT([yes])
+ fi
+])
+
+AC_DEFUN([__ENSC_CHECK_WARNFLAGS_C],
+[
+ __ENSC_CHECK_WARNFLAGS(C, C, CFLAGS)
+])
+
+AC_DEFUN([__ENSC_CHECK_WARNFLAGS_CXX],
+[
+ __ENSC_CHECK_WARNFLAGS(C++, CXX, CXXFLAGS)
+])
+
+
+# --------------------------------------------------------------------------
+# Check whether the C++ compiler accepts a certain flag
+# If it does it adds the flag to CXXFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# ENSC_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN(ENSC_CHECK_CXX_FLAG,
+[
+ AC_REQUIRE([__ENSC_CHECK_WARNFLAGS_CXX])
+
+ echo 'void f(){}' > conftest.cc
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CXX accepts $i])
+ if test -z "`${CXX} ${ensc_sys_compilerwarnflags_CXX} $i -c conftest.cc 2>&1`"
+ then
+ CXXFLAGS="${CXXFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.cc conftest.o
+])
+
+# --------------------------------------------------------------------------
+# Check whether the C compiler accepts a certain flag
+# If it does it adds the flag to CFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# ENSC_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN(ENSC_CHECK_CC_FLAG,[
+ AC_REQUIRE([__ENSC_CHECK_WARNFLAGS_C])
+
+echo 'void f(){}' > conftest.c
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CC accepts $i])
+ if test -z "`${CC} ${ensc_sys_compilerwarnflags_C} $i -c conftest.c 2>&1`"
+ then
+ CFLAGS="${CFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.c conftest.o
+])
+
+AC_DEFUN(ENSC_CHECK_DEFAULT_FLAG,
+[
+ if test x"${ensc_sys_default_flag}" = x; then
+ ENSC_CHECK_CC_FLAG([-fmessage-length=0])
+ ENSC_CHECK_CXX_FLAG([-fmessage-length=0])
+
+ ensc_sys_default_flag=set
+ fi
+])
--- /dev/null
+## $Id$
+
+## Copyright (C) 2002 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.
+
+gpgsig:
+ gpg --armor --detach-sign $(distdir).tar.bz2
--- /dev/null
+## $Id$ ---*- makefile -*---
+
+## Copyright (C) 2002 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.
+##
+
+$(BUILT_SOURCES) config.h: .X$(subst /,_,$(sysconfdir))-up-to-date
+
+distclean-local: distclean-uptodate
+
+distclean-uptodate:
+ @rm -f .*-up-to-date
+
+.%-up-to-date:
+ @rm -f .*-up-to-date
+ @touch -t 197001020000 '$@'
+ @$(MAKE) clean
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+man_DATMAN = man/chbind.8 \
+ man/chcontext.8 \
+ man/distrib-info.8 \
+ man/newvserver.8 \
+ man/rebootmgr.8 \
+ man/reducecap.8 \
+ man/vps.8 \
+ man/vpstree.8 \
+ man/vrpm.8 \
+ man/vserver-copy.8 \
+ man/vserver-stat.8 \
+ man/vserver.8 \
+ man/vtop.8
--- /dev/null
+.TH "chbind" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+chbind \- The chbind utility is used to lock a process and its children into using a specific IP number/Interface.
+.SH "SYNTAX"
+.LP
+chbind [\fI\-\-silent\fP] [\fI\-\-ip ip_number/interface\fP] <\fIcommand arguments\fP>
+.SH "DESCRIPTION"
+.LP
+The chbind utility executes a command, and locks the resulting process and its children into using a specific IP number/Interface, no matter what it is told in it's configuration. This applies to services and client connection as well.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-\-ip\fR ip_number/interface
+Binds the process to the given IP number or Interface. If an interface
+is supplied (for example eth0), both the IP number and broadcast address
+are extracted.
+.TP
+\fB\-\-bcast\fR broadcast address
+Binds the process to the given broadcast IP number.
+.TP
+\fB\-\-silent\fR
+Do not complain.
+
+.SH "FILES"
+.LP
+\fI/usr/sbin/chbind\fP
+
+
+.SH "EXAMPLES"
+.LP
+If I wanted to ensure my httpd listened only on my eth0 interface, I could do:
+chbind \-\-ip eth0 /etc/rc.d/init.d/httpd start
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) reducecap(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
--- /dev/null
+.TH "chcontext" "1" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+chcontext \- chcontext allocates a new security context and executes a command in that context.
+.SH "SYNTAX"
+.LP
+chcontext [\fIoptions\fP] <\fIcommand arguments\fP>
+.SH "DESCRIPTION"
+.LP
+chcontext allocates a new security context and executes a command in that context.
+By default, a new/unused context is allocated
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-\-cap\fR CAP_NAME
+Add a capability from the command. This option may be repeated several time. See /usr/include/linux/capability.h In general, this option is used with the \-\-secure option. \-\-secure removes most critical capabilities and \-\-cap adds specific ones.
+.TP
+\fB\-\-cap\fR !CAP_NAME
+Remove a capability from the command. This option may be repeated several time. See /usr/include/linux/capability.h
+.TP
+\fB\-\-ctx\fR num
+Select the context. Only root in context 0 is allowed to select a specific context.
+Context number 1 is special. It can see all processes in any contexts, but can't kill them though.
+.TP
+\fB\-\-disconnect\fR
+Start the command in background and make the process a child of process 1.
+.TP
+\fB\-\-domainname\fR new_domainname
+Set the domainname (NIS) in the new security context.
+Use "none" to unset the domainname.
+.TP
+\fB\-\-flag\fR
+Set one flag in the new or current security context. The following flags are supported. The option may be used several time.
+ lock: The new process is trapped and can't use
+ chcontext anymore.
+ sched: The new process and its children will
+ share a common execution priority.
+ nproc: Limit the number of process in the
+ vserver according to ulimit setting.
+ Normally, ulimit is a per user thing.
+ With this flag, it becomes a per vserver
+ thing.
+ private: No one can join this security context
+ once created.
+.TP
+\fB\-\-hostname\fR new_hostname
+Set the hostname in the new security context.
+This is needed because if you create a less privileged security context, it may be unable to change its hostname.
+.TP
+\fB\-\-secure\fR
+Remove all the capabilities to make a virtual server trustable.
+.TP
+\fB\-\-silent\fR
+Do not print the allocated context number.
+.LP
+Information about context is found in /proc/self/status
+.SH "FILES"
+.LP
+\fI/usr/sbin/chcontext\fP
+
+
+.SH "EXAMPLES"
+.LP
+# You must be root, running X.
+# We start an xterm in another security context
+/usr/sbin/chcontext xterm &
+
+# We check, there is no xterm running, yet we can
+# see it.
+ps ax | grep xterm
+
+# Are we running in security context 0
+# We check the s_context line in /proc/self/status
+cat /proc/self/status
+
+# Ok we in security context 0
+# Try the security context 1
+/usr/sbin/chcontext \-\-ctx 1 ps ax | grep xterm
+
+# Ok, we see the xterm, we try to kill it
+/usr/sbin/chcontext \-\-ctx 1 killall xterm
+
+# No, security context 1 can see, but can't kill
+# let's find out in which security context this
+# xterm is running
+/usr/sbin/chcontext \-\-ctx 1 ps ax | grep xterm
+
+# Ok, this is PID XX. We need the security context
+/usr/sbin/chcontext \-\-ctx 1 cat /proc/XX/status
+
+# We see the s_context, this is SS.
+# We want to kill this process
+/usr/sbin/chcontext \-\-ctx SS killall xterm
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chbind(8) rebootmgr(8) reducecap(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
--- /dev/null
+.TH "distrib-info" "8" "0.1.0" "Jacques Gelinas <jack@solucorp.qc.ca>" "System Administration"
+.SH "NAME"
+.LP
+distrib-info \- A distribution independant utility to retrieve package information.
+.SH "SYNTAX"
+.LP
+distrib-info vserver-name command [options]
+
+.SH "DESCRIPTION"
+.LP
+distrib-info \- This utility provides a solution to hide some differences
+between Linux distributions. The various utilities (vunify, vbuild, ...)
+need package information to perform their task. They call distrib-info
+to retrieve this information. distrib-info is the only one understanding
+the various distribution out there.
+.TP
+This utility is only used as a back-end for other utilities such as
+vunify and vbuild.
+.SH "OPTIONS"
+.LP
+.TP
+\fBdumpfiles\fR reports all files owned by a package.
+.TP
+\fBpkgversion\fR reports all packages and version.
+.TP
+\fBunifiles\fR reports the files of a package which may be shared by
+several virtual servers. Generally, this excludes all configuration files.
+
+.SH "EXAMPLES"
+.LP
+The following command will report all packages in the vserver ref80.
+The package will be presented with the version/release.
+
+ distrib-info ref80 pkgversion
+
+To get the list of unify-able (sharable) file in package sendmail
+of the vserver ref80, we do
+
+ distrib-info ref80 unifiles sendmail
+.SH "FILES"
+.LP
+ /usr/lib/vservers/distrib-info
+.SH "AUTHORS"
+.LP
+This Man page was written by Jacques Gelinas <jack@solucorp.qc.ca>.
+.SH "SEE ALSO"
+.LP
+vbuild(8) vfiles(8) vunify(8)
+newvserver(8)
+
--- /dev/null
+.TH "newvserver" "8" "0.1.0" "Jacques Gelinas <jack@solucorp.qc.ca>" "System Administration"
+.SH "NAME"
+.LP
+newvserver \- The newvserver is an interactive tool to create new vservers.
+.SH "SYNTAX"
+.LP
+newvserver [ options ]
+
+.SH "DESCRIPTION"
+.LP
+newvserver \- The newvserver creates new vservers interactivly. It provides
+a graphical user interface as well as a text user interface. You can
+configure most aspect of the vserver (name, description, hostname, IP number,
+root password, ...), select a source and then perform the creation.
+
+A vserver may be created by cloning another one, cloning the root server
+or by performing a minimal installation from a distribution CD (RedHat
+supported so far).
+
+.SH "Default values"
+.LP
+The file /etc/vservers/newvserver.defaults is sourced to get default
+input value for many fields. If you are creating many vservers
+(you will :-) ), you may want to edit this file and enter suitable
+values such as your domain name, IP network, etc...
+
+
+.SH "OPTIONS"
+.LP
+.TP
+.I --help:
+Presents a summary of the options.
+.TP
+.I --name:
+Set the name of the new vserver.
+.TP
+.I --desc:
+Set the description.
+.TP
+.I --unify 1/0:
+Turn on unification on and off.
+.TP
+.I --hostname:
+Set the host name of the new vserver
+.TP
+.I --ip:
+Set the IP number(s)
+.TP
+.I --ondev:
+Install the IP numbers as IP aliases on device.
+.TP
+.I --clone:
+Create the vserver from another one or a distribution CD.
+.TP
+The distribution CD are identified by special strings:
+ #rh8.0m: RedHat 8 minimal
+ #rh8.0f: RedHat 8 complete first CD
+ #rh7.3m: RedHat 7.3 minimal
+ #rh7.3f: RedHat 7.3 complete first CD
+ #rh7.2m: RedHat 7.2 minimal
+ #rh7.2f: RedHat 7.2 complete first CD
+
+.SH "FILES"
+.LP
+\fI/etc/vservers/*.conf\fP
+.P
+\fI/etc/vservers/*.sh\fP
+.P
+\fI/etc/vservers/newvserver.defaults\fP
+.P
+\fI/vservers/*\fP
+
+.SH "AUTHORS"
+.LP
+This Man page was written by Jacques Gelinas.
+.SH "SEE ALSO"
+.LP
+vserver(8)
+vserver\-stat(8)
+distrib-info(8)
+vbuild(8)
+
--- /dev/null
+.TH "rebootmgr" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+rebootmgr \- rebootmgr stops and starts one or more vservers at your command.
+.SH "SYNTAX"
+.LP
+rebootmgr \fIvserver\-name\fP [\fIvserver\-name\fP ...] \fICommand\fP
+.SH "DESCRIPTION"
+.LP
+The chbind utility executes a command, and locks the resulting process and its children into using a specific IP number/Interface, no matter what it is told in it's configuration. This applies to services and client connection as well.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-\-ip\fR ip_number/interface
+Binds the process to the given IP number or Interface.
+.TP
+\fB\-\-silent\fR
+Do not complain.
+
+.SH "FILES"
+.LP
+\fI/usr/sbin/rebootmgr\fP
+
+
+.SH "EXAMPLES"
+.LP
+If I wanted to ensure my httpd listened only on my eth0 interface, I could do:
+chbind \-\-ip eth0 /etc/rc.d/init.d/httpd start
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) chbind(8) reducecap(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
--- /dev/null
+.TH "reducecap" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+reducecap \- The reducecap utility is used to lower the capability ceiling of a process and child process.
+.SH "SYNTAX"
+.LP
+reducecap [\fIoptions\fP] <\fIcommand arguments\fP>
+.SH "DESCRIPTION"
+.LP
+The reducecap utility is used to lower the capability ceiling of a process and child process. Even setuid program won't be able to grab more capabilities.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-\-secure\fR Removes all dangerous capabilities from the process executed.Specificly it removes:
+CAP_LINUX_IMMUTABLE CAP_NET_BROADCAST CAP_NET_ADMIN, CAP_NET_RAW CAP_IPC_LOCK CAP_IPC_OWNER CAP_SYS_MODULE CAP_SYS_RAWIO CAP_SYS_PACCT CAP_SYS_ADMIN CAP_SYS_BOOT CAP_SYS_NICE CAP_SYS_RESOURCE CAP_SYS_TIME CAP_MKNOD.
+
+Leaving the following capabilities:
+CAP_CHOWN CAP_DAC_OVERRIDE CAP_DAC_READ_SEARCH CAP_FOWNER CAP_FSETID CAP_KILL CAP_SETGID CAP_SETUID CAP_NET_BIND_SERVICE CAP_SYS_CHROOT CAP_SYS_PTRACE CAP_SYS_TTY_CONFIG CAP_LEASE CAP_OPENDEV
+.TP
+\fB\-\-show\fR Shows the current process capabilities.
+.TP
+\fB\-\-flag\fR
+sets the security context flags. The option may be repeated
+several times. Here are the values:
+
+lock: The security context can't be changed. The process is trapped
+ in this context. This is generally used for vservers because yoy
+ do not want them to hide in new security context.
+
+sched: Each process in a security context contribute (lower) to the general
+ priority of every processes in the context. Mostly, all processes
+ in a security context take as much CPU together as one process
+ not bound to this flag. Said again differently, a vserver having
+ 100 active processes won't get more CPU than another vserver
+ with a single active process.
+
+
+nproc: The "ulimit -u N" setting becomes global to the security context. It means
+ the security context is not allowed to have more than N processes.
+
+private: No other processes, even root in security context 0, is allowed to
+ enter this security context. Once a security context is setup
+ with this flag, it is on its own. This also means that root
+ in security context 0 won't be able to kill or interact with those
+ processes.
+
+hideinfo: Hides various information in /proc.
+
+.TP
+\fB--LINUX_IMMUTABLE\fR
+.TP
+\fB--NET_BIND_SERVICE\fR
+.TP
+\fB--NET_BROADCAST\fR
+.TP
+\fB--NET_ADMIN\fR
+.TP
+\fB--NET_RAW\fR
+.TP
+\fB--IPC_LOCK\fR
+.TP
+\fB--IPC_OWNER\fR
+.TP
+\fB--SYS_MODULE\fR
+.TP
+\fB--SYS_RAWIO\fR
+.TP
+\fB--SYS_PACCT\fR
+.TP
+\fB--SYS_ADMIN\fR
+.TP
+\fB--SYS_BOOT\fR
+.TP
+\fB--SYS_NICE\fR
+.TP
+\fB--SYS_RESOURCE\fR
+.TP
+\fB--SYS_TIME\fR
+.TP
+\fB--MKNOD\fR
+
+All these options remove one capability. These options may be used
+after the
+\fB--secure\fR
+option to remove more capabilities.
+
+
+.SH "FILES"
+.LP
+\fI/usr/sbin/reducecap\fP
+
+
+.SH "EXAMPLES"
+.LP
+# You are not root now
+# What is the current capability ceiling
+cat /proc/self/status
+# The capBset line presents mostly 1s.
+/usr/sbin/reducecap \-\-secure /bin/sh
+cat /proc/self/status
+# The capBset now shows many more 0s.
+# The capEff shows all 0s, you have no privilege now
+# We su to root
+su
+cat /proc/self/status
+# capEff is much better now, but there are still many 0s
+# Now we try to see if we are really root
+tail /var/log/messages
+# So far so good, we see the content
+/sbin/ifconfig eth0
+/sbin/ifconfig eth0 down
+# No way, we can't configure the interface. In fact
+# we have lost most privilege normally assigned to root
+exit
+.LP
+Please contribute some more, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) chbind(8)
+vps(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
--- /dev/null
+.TH "vps" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+vps \- The vps utility is simply a wrapper for the ps program.
+.SH "SYNTAX"
+.LP
+vps [\fIoptions\fP]
+
+.SH "DESCRIPTION"
+.LP
+vps \- The vps utility is simply a wrapper for the ps program, that enables ps to show you the all the processes on the system, instead of only the ones in the current s_context (see cat /proc/self/status).
+.SH "OPTIONS"
+.LP
+.TP
+See man ps.
+.SH "FILES"
+.LP
+\fI/usr/sbin/vps\fP
+
+
+.SH "EXAMPLES"
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vpstree(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
--- /dev/null
+.TH "vpstree" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+vpstree \- The vpstree utility is simply a wrapper for the pstree program.
+.SH "SYNTAX"
+.LP
+vpstree [\fIoptions\fP]
+
+.SH "DESCRIPTION"
+.LP
+vpstree \- The vpstree utility is simply a wrapper for the pstree program, that enables pstree to show you the all the processes on the system, instead of only the ones in the current s_context (see cat /proc/self/status).
+.SH "OPTIONS"
+.LP
+.TP
+See man pstree.
+.SH "FILES"
+.LP
+\fI/usr/sbin/vpstree\fP
+
+
+.SH "EXAMPLES"
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vrpm(8) vserver(8)
+vserver\-stat(8) vtop(8)
--- /dev/null
+.TH "vrpm" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+vrpm \- is simply a wrapper for the rpm utility.
+.SH "SYNTAX"
+.LP
+vrpm [--unify] [ALL | vserver1 vserver2 ...] \-\- [rpm options]
+
+.SH "DESCRIPTION"
+.LP
+vrpm \- is simply a wrapper for the rpm utility. It enables rpm to manage a specific, several or all virtual server(s) with one command.
+vrpm is executed in the root server.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-\-\fR All commands after this, is given to the rpm utility (see man rpm).
+.TP
+The
+\fB--unify\fR option triggers the vunify utility on the vservers and the
+supplied packages.
+.SH "FILES"
+.LP
+\fI/usr/sbin/vrpm\fP
+
+
+.SH "EXAMPLES"
+.TP
+verifies the gcc package on all vservers.
+.LP
+vrpm ALL \-\- \-\-verify gcc
+.TP
+Updates package.rpm on vserver1 and vserver2 if
+the package exists in a earlier version
+(the F flag for rpm).
+.LP
+vrpm vserver1 vserver2 \-\- \-Fvh package.rpm
+.TP
+vrpm is executed in the root server
+.LP
+Please contribute some more, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vtop(8) vserver(8)
+vserver\-stat(8) vpstree(8)
--- /dev/null
+.TH "vserver-copy" "8" "0.3" "Mark Lawrence <nomad@null.net>" "System Administration"
+.SH "NAME"
+.LP
+vserver-copy \- copy/move a virtual server.
+.SH "SYNTAX"
+.LP
+vserver-copy [\fIoptions\fP] \fIvserver\fP \fInewname\fP
+.LP
+vserver-copy [\fIoptions\fP] \fIvserver\fP \fIhost\fP:[\fInewname\fP]
+.SH "DESCRIPTION"
+.LP
+vserver-copy makes a copy of a virtual server using rsync. It will
+rewrite the vserver.conf configuration file with the new hostname and
+IP information when given. If the destination name contains a host
+specification then ssh/rsh will be used for the data transfer.
+
+vserver-copy can used on a running vserver, although naturally the
+consistency of open database files and the like cannot be guaranteed.
+A running vserver can however be safely moved from one root host to another
+using the \-s flag.
+
+If downtime is an issue when moving a virtual server across hosts you
+should first run vserver without the \-s flag. This will pre\-populate the
+destination filesystem requiring only updates to be made on the next
+invocation.
+.SH "OPTIONS"
+.LP
+.TP
+\fB\-h\fR,\fB-\-help\fR
+output usage information and exit
+.TP
+\fB\-V\fR,\fB-\-version\fR
+output version information and exit
+.TP
+\fB\-v\fR,\fB-\-verbose\fR
+show all output (normally only informational messages and warnings)
+.TP
+\fB\-q\fR,\fB-\-quiet\fR
+suppress all output
+.TP
+\fB\-d\fR,\fB-\-domain\fR domain
+the new DNS domain when changing name. Overwrites /etc/hosts. Must be
+used with \-i
+.TP
+\fB\-i\fR,\fB-\-ip\fR address
+the new IP address when changing name. Overwrites /etc/hosts. Must be
+used with \-d
+.TP
+\fB\-r\fR,\fB-\-vsroot\fR
+directory containing virtual servers. Defaults to "/vserver"
+.TP
+\fB\-R\fR,\fB-\-rsh\fR
+use rsh instead of the default ssh for network transfer
+.TP
+\fB\-s\fR,\fB-\-stopstart\fR
+stop the virtual server before copying and start the new vserver afterwards.
+This really only makes sense if you are copying across root hosts and not
+changing names or IP addresses.
+.SH "FILES"
+.LP
+\fI/etc/vservers/vserver.conf\fP
+.SH "EXAMPLES"
+.LP
+# Copy a template vserver (same IP addresses etc)
+
+/usr/sbin/vserver-copy template web01
+
+# Copy webserver with change in configuration
+
+/usr/sbin/vserver-copy -i 192.168.5.62 -d example.com template web62
+
+# Move a running vserver to another roothost
+
+/usr/sbin/vserver-copy -s web62 roothost02:
+
+.SH "BUGS"
+.LP
+If a virtual server is moved from one root host to another a gratuitious
+ping should be sent to inform other devices on the local area network
+of the change in MAC address.
+
+Without this ping the devices will continue to attempt to reach the old
+MAC address for the length of their arp-cache timeout (10 minute default
+on Suns!).
+
+This functionality should probably be implmemented during the
+"vserver <name> start" process.
+.SH "AUTHOR"
+.LP
+Mark Lawrence <nomad@null.net>
+.SH "SEE ALSO"
+.LP
+vserver(8)
--- /dev/null
+.TH "vserver-stat" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+vserver\-stat
+.SH "SYNTAX"
+.LP
+vserver\-stat
+
+.SH "DESCRIPTION"
+.LP
+vserver\-stat \- The vserver\-stat utility shows informations about all the active contexts.
+
+ CTX# Context number
+ #0 = root context
+ #1 = monitoring context
+ PROC QTY Quantity of processes in each
+ context
+ VSZ Number of pages of virtual
+ memory
+ RSS Resident set size
+ utime User\-mode CPU time
+ accumulated
+ ctime Kernel\-mode CPU time
+ accumulated
+.SH "FILES"
+.LP
+\fI/usr/sbin/vserver\-stat\fP
+
+
+.SH "EXAMPLES"
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vrpm(8) vserver(8)
+vtop(8) vpstree(8)
--- /dev/null
+.TH "vserver" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+vserver \- The vserver utility enables you to control different aspects of your vservers.
+.SH "SYNTAX"
+.LP
+vserver [ options ] [vserver name] [options]
+
+.SH "DESCRIPTION"
+.LP
+vserver \- The vserver utility enables you to control different aspects of your vservers, such as stopping and starting them, and services within them.
+.SH "OPTIONS"
+.LP
+.TP
+\fBbuild\fR Create a virtual server by copying the packages of the root server
+.TP
+\fBenter\fR Enter in the virtual server context and starts a shell. Same as "vserver name exec /bin/sh\".
+.TP
+\fBexec\fR Exec a command in the virtual server context as root.
+syntax: vserver name exec command ...
+.TP
+\fBsuexec\fR Exec a command in the virtual server context under some user id.
+syntax: vserver name suexec userid command ...
+.TP
+\fBservice\fR Control a service inside a vserver.
+syntax: vserver name service service\-name (start/stop/restart etc.)
+.TP
+\fBstart\fR Starts the various services in the vserver.
+It uses the default runlevel found in the
+.B /etc/inittab
+file of the vserver.
+.TP
+\fBstop\fR Ends all services and kills the remaining processes.
+.TP
+\fBrunning\fR Tells if a virtual server is running. It returns proper exit code, so you can use it as a test.
+.TP
+\fBstatus\fR Tells various information about the state of a virtual server:
+running status, number of running processes and uptime.
+.TP
+.I --nodev
+do not configure the IP devices associated with the vserver. This
+is useful to execute some commands on the vserver (or enter it)
+without making it active on the network. Especially useful if you
+have an active copy of the vserver moved to another server on the
+network.
+.TP
+.I --silent
+cuts most informative messages.
+
+.SH "FILES"
+.LP
+\fI/usr/sbin/vserver\fP
+.P
+\fI/etc/vservers/*.conf\fP
+.P
+\fI/etc/vservers/*.sh\fP
+.P
+\fI/vservers/*\fP
+
+.SH "EXAMPLES"
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chbind(8) chcontext(8)
+newvserver(8)
+rebootmgr(8) reducecap(8)
+vps(8) vpstree(8)
+vrpm(8)
+vserver\-stat(8)
+vtop(8)
--- /dev/null
+.TH "vtop" "8" "0.1.0" "Klavs Klavsen <kl@vsen.dk>" "System Administration"
+.SH "NAME"
+.LP
+vtop \- The vtop utility is simply a wrapper for the top program.
+.SH "SYNTAX"
+.LP
+vtop [\fIoptions\fP]
+
+.SH "DESCRIPTION"
+.LP
+vtop \- The vtop utility is simply a wrapper for the top program, that enables top to show you the all the processes on the system, instead of only the ones in the current s_context (see cat /proc/self/status).
+.SH "OPTIONS"
+.LP
+.TP
+See man top.
+.SH "FILES"
+.LP
+\fI/usr/sbin/vtop\fP
+
+
+.SH "EXAMPLES"
+.LP
+Please contribute some, if you feel it's important.
+.SH "AUTHORS"
+.LP
+This Man page was written by Klavs Klavsen <kl@vsen.dk> and based upon the helpful output from the program itself and the documentation on the Virtual Server site <http://www.solucorp.qc.ca/miscprj/s_context.hc?prjstate=1&nodoc=0>
+.SH "SEE ALSO"
+.LP
+chcontext(8) rebootmgr(8) reducecap(8)
+chbind(8) vps(8) vrpm(8) vserver(8)
+vserver\-stat(8) vpstree(8)
--- /dev/null
+# This script is sourced by newvserver to set the dialog default values
+# Uncomment only the line you want to override.
+# Name of the vserver
+# name=
+# Description
+# desc=
+# Reference vserver to clone
+# clone=/
+# Use unification
+# unify=1
+# Host name. Put the default domain if you want
+# hostname=.mydomain.com
+# List of IP
+# Put the prefix of your network to save some typing
+# ip=
+# Network device for IP aliases setup
+# ondev=eth0
+
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+scriptscfgdir = $(sbindir)
+
+scripts_SCRPTS = scripts/distrib-info \
+ scripts/rootshell \
+ scripts/save_s_context \
+ scripts/vprofile \
+ scripts/vserverkillall \
+ scripts/vservers.grabinfo.sh \
+ scripts/vsysvwrapper \
+ scripts/vunify.old.sh
+
+scripts_PRGS = scripts/vkill \
+ scripts/vps \
+ scripts/vpstree \
+ scripts/vrpm \
+ scripts/vserver \
+ scripts/vserver-copy \
+ scripts/vtop
+
+scriptscfg_DATA = scripts/util-vserver-vars
+
+scripts_XTRAS = scripts/util-vserver-vars.subst
+scripts_GENSCRPTS = scripts/util-vserver-vars
+
+scripts/%: scripts/%.subst
+ @mkdir -p $$(dirname '$@')
+ sed -e 's!@'PKGLIBDIR'@!$(pkglibdir)!g; \
+ s!@'SBINDIR'@!$(sbindir)!g' '$<' >'$@.tmp'
+ @-rm -f '$@'
+ mv '$@.tmp' '$@'
+ @chmod a-w '$@'
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on distrib-info by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+
+# This scripts knows about every possible distribution (well, it should)
+# It is passed a vserver name and a key (a command). The key represent a task.
+# It executes the command and output on stdout.
+# For example
+# distrib-info vserver1 pkgversion
+# If vserver1 is a redhat system, it executes
+# rpm -qa --queryformat "%{name}=%{version}-%{release}
+USR_LIB_VSERVER=$(dirname $0)
+
+if [ "$1" = "" ] ; then
+ echo distrib-info vserver-name command [ args ... ] >&2
+ echo Commands are: >&2
+ echo dumpfiles: Shows all files owned by a package >&2
+ echo pkgversion: reports all packages and their version/release >&2
+ echo unifiles: reports all unify-able file of a package >&2
+ exit 1
+fi
+if [ "$1" = "/" ] ; then
+ DISTDIR=/
+ CHROOTCMD=
+elif [ -d "$1" ] ; then
+ DISTDIR=$1
+ CHROOTCMD="/usr/sbin/chroot $DISTDIR"
+else
+ DISTDIR=/vservers/$1
+ CHROOTCMD="/usr/sbin/chroot $DISTDIR"
+fi
+KEY=$2
+shift
+shift
+if [ -f $DIRDIR/etc/redhat-release -o -f $DISTDIR/etc/mandrake-release ] ; then
+ case $KEY in
+ pkgversion)
+ $CHROOTCMD /bin/rpm -qa --queryformat "%{name}=%{version}-%{release}\n"
+ ;;
+ unifiles)
+ # We remove /etc and /var/log to make sure no special file
+ # there will be unified
+ $CHROOTCMD /bin/rpm -ql --dump $* \
+ | $USR_LIB_VSERVER/parserpmdump /etc/
+ ;;
+ dumpfiles)
+ $CHROOTCMD /bin/rpm -ql $*
+ ;;
+ *)
+ echo unknown request $KEY >&2
+ ;;
+ esac
+else
+ echo Distribution not supported yet >&2
+fi
+
--- /dev/null
+#!/bin/sh
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on rootshell by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+
+echo $* >/tmp/log
+OPTIONS=$@
+if [ "$OPTIONS" = "" ] ; then
+ OPTIONS=--login
+fi
+exec /usr/sbin/chbind --silent --ip 0.0.0.0 /bin/bash $OPTIONS
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on save_s_context by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+if [ $# -lt 1 ] ;then
+ echo save_s_context file command
+ echo Save the security context in file and execute a command
+else
+ CTX=`grep ^s_context: /proc/self/status | sed s/s_context:// | (read a b; echo $a)`
+ CTX=`eval expr $CTX + 0`
+ echo S_CONTEXT=$CTX >$1
+ echo S_PROFILE=$PROFILE >>$1
+ shift
+ exec "$@"
+fi
+
+
--- /dev/null
+PKGLIBDIR='@PKGLIBDIR@'
+SBINDIR='@SBINDIR@'
--- /dev/null
+#!/usr/bin/perl -w
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vkill by Philip Snyder
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# kill wrapper for vserver.
+# Philip Snyder <psnyder@vizional.com>
+# 2002/02/06 19:00 PST
+
+
+$PROC = $ARGV[0];
+
+# Grab the output from a context query against this process id
+open(PH, "/usr/sbin/chcontext --silent --ctx 1 cat /proc/$PROC/status 2>&1 |");
+
+# Loop through the output
+while (<PH>) {
+
+ # Searching for a line that looks like this:
+ # s_context: #
+ if (/^s_context: ([0-9]+)/) {
+
+ print "Process id $PROC was found in security context $1.\n";
+
+ # Make sure the process is in a vserver context
+ if ($1 > 0) {
+
+ # Since we have the context and the process id, we can kill it
+ print " + Killing... ";
+ `/usr/sbin/chcontext --ctx $1 kill $PROC`;
+ print "[done]\n";
+
+ } else {
+
+ # Not in vserver context, so its a process on the actual server
+ print " + Killing... ";
+ `kill $PROC`;
+ print "[done]\n";
+
+ }
+ exit;
+ }
+}
+
+print "Process id $PROC not found.\n";
+exit
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vprofile by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Prints or select the active profile for a vserver
+if [ $# != 1 -a $# != 2 ] ; then
+ echo vprofile vserver [ profile-name ]
+else
+ if [ ! -f /etc/vservers/$1.conf ] ; then
+ echo vserver $1 does not exist >&2
+ else
+ unset PROFILE
+ . /etc/vservers/$1.conf
+ if [ $# = 1 ] ; then
+ echo PROFILE=$PROFILE
+ elif [ $# = 2 ] ; then
+ grep .\*\) /etc/vservers/$1.conf
+ fi
+ fi
+fi
+
+
--- /dev/null
+#!/usr/bin/perl
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vps by Krischan Jodies
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Wrapper for ps. Adds security context number and name
+# to the PID column.
+#
+# (c) 2002 krischan.jodies@sernet.de
+# version 1.0
+
+# 1.1 Added error messages
+
+if ($ARGV[0] eq "--help") {
+ exec("ps @ARGV");
+ exit;
+}
+
+
+$lockdir = "/var/run/vservers";
+
+$pid_length = 5;
+get_server_names();
+$context=get_context("self");
+
+if ($context == -1) {
+ print "Can not find my security context. Is this a ctx kernel?\n";
+ exit;
+}
+if ($context != 1) {
+ exec("/usr/sbin/chcontext --silent --ctx 1 $0 @ARGV");
+ print "Can not execute chcontext\n";
+ exit; # not reached
+}
+
+
+if (! open PS, "ps $ARGV[0]|") {
+ print "Can not execute ps\n";
+ exit;
+}
+while (<PS>) {
+ chomp;
+ push @ps,$_;
+}
+
+$header = shift @ps;
+$header =~ /(.*) PID(.+)/;
+$left = $1;
+$right = $2;
+$left_length = length($left);
+print "${left} PID CONTEXT ${right}\n";
+foreach $line (@ps) {
+ $pid = substr $line,$left_length,$pid_length;
+ print substr $line,0,$left_length;
+ print "$pid";
+ $context = get_context($pid);
+ $context_name = getcontextname($context);
+ printf " %-3s %-10s",$context,$context_name;
+ print substr $line,$left_length + $pid_length;
+ print "\n";
+
+}
+
+exit;
+
+sub get_context
+{
+ my $pid = $_[0];
+ $pid =~ s/ //g;
+ open STATUS, "/proc/$pid/status";
+ while (<STATUS>)
+ {
+ chomp;
+ if (/s_context: (\d+)/) {
+ close STATUS;
+ return $1;
+ }
+ }
+ close STATUS;
+ return -1;
+}
+
+sub getcontextname {
+ if (exists $name{$_[0]}) {
+ return $name{$_[0]};
+ }
+ if ($_[0] == 1) {
+ return "ALL_PROCS";
+ }
+ elsif ($_[0] == 0) {
+ return "MAIN";
+ }
+ return "UNKNOWN";
+}
+
+
+sub get_server_names
+{
+ opendir LOCKDIR, "$lockdir";
+ while ($file=readdir(LOCKDIR)) {
+ if (-f "$lockdir/$file") {
+ open FILE, "$lockdir/$file";
+ $file =~ s/(.+)\.ctx/$1/;
+ while (<FILE>) {
+ if (/S_CONTEXT=(\d+)/) {
+ $name{$1} = $file;
+ }
+ }
+ }
+ }
+}
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vpstree by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+#Presents the processes running in all virtual servers
+exec /usr/sbin/chcontext --silent --ctx 1 pstree $*
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vrpm by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Wrapper to update/install package in many vservers at once
+
+: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+ echo "Can not find util-vserver installation; aborting..."
+ exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+usage(){
+ echo vrpm: Install/Updates packages in several vservers at once
+ echo vrpm vservers ... -- rpm options and packages
+ echo vrpm \[--unify\] ALL -- rpm options and packages
+ echo vrpm \[--unify\] server1 server2 -- -Uvh package.rpm
+ echo
+ echo vrpm is executed in the root server
+ echo "--unify run vunify on the vserver for the updated packages"
+}
+UNIFY=no
+if [ "$1" = "--unify" ] ; then
+ UNIFY=yes
+ shift
+fi
+if [ $# = 0 ] ; then
+ usage
+else
+ SERVERS=
+ while [ $# -gt 0 -a "$1" != "--" ]
+ do
+ if [ "$1" = "ALL" ] ; then
+ SERVERS=`cd /vservers && ls`
+ else
+ SERVERS="$SERVERS $1"
+ fi
+ shift
+ done
+ if [ "$1" != "--" ] ; then
+ usage
+ elif [ "$SERVERS" = "" ] ; then
+ echo no server specified
+ echo
+ usage
+ else
+ shift
+ for serv in $SERVERS
+ do
+ # We try to run the rpm command in the same security
+ # context than the vserver, if running.
+ # This way, process operations will be done in the proper
+ # context
+ # If the vserver is not running, chcontext will
+ # pick an unused one.
+ CTXOPT=""
+ CTXFILE=/var/run/vservers/$serv.ctx
+ if [ -f $CTXFILE ] ; then
+ source $CTXFILE
+ CTXOPT="--ctx $S_CONTEXT"
+ fi
+ #echo rpm --root /vservers/$serv $*
+ echo Updating server $serv
+ /usr/sbin/chcontext --silent $CTXOPT rpm --root /vservers/$serv $*
+ done
+ if [ "$UNIFY" = "yes" ] ; then
+ PACKAGES=
+ for pkg in $*
+ do
+ case $pkg in
+ -*)
+ # RPM options ?
+ ;;
+ --*)
+ # RPM options ?
+ ;;
+ *)
+ pkg=`rpm -qp $pkg --queryformat %{name}`
+ PACKAGES="$PACKAGES $pkg"
+ ;;
+ esac
+ done
+ echo Unification
+ $PKGLIBDIR/vunify --excldir /var/log $SERVERS -- $PACKAGES
+ fi
+ fi
+fi
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserver by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This is a script to control a virtual server
+
+: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+ echo "Can not find util-vserver installation; aborting..."
+ exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+USR_SBIN=$SBINDIR
+USR_LIB_VSERVER=$PKGLIBDIR
+
+VSERVER_CMD=$USR_SBIN/vserver
+CHBIND_CMD=$USR_SBIN/chbind
+CHCONTEXT_CMD=$USR_SBIN/chcontext
+SAVE_S_CONTEXT_CMD=$USR_LIB_VSERVER/save_s_context
+CAPCHROOT_CMD=$USR_LIB_VSERVER/capchroot
+VSERVERKILLALL_CMD=$USR_LIB_VSERVER/vserverkillall
+DEFAULTPATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/X11R6/bin
+vserver_mknod(){
+ mknod $1 $2 $3 $4
+ chmod $5 $1
+}
+
+mountproc()
+{
+ mkdir -p $1/proc $1/dev/pts
+ if [ ! -d $1/proc/1 ] ; then
+ mount -t proc none $1/proc
+ mount -t devpts none $1/dev/pts
+ fi
+}
+umountproc()
+{
+ umount $1/proc 2>/dev/null
+ umount $1/dev/pts 2>/dev/null
+}
+
+# Check that the vservers parent directory has permission 000
+# This is the key to avoid chroot escape
+testperm()
+{
+ return
+ PERM=`$USR_LIB_VSERVER/showperm /vservers/$1/..`
+ if [ "$PERM" != 000 ] ; then
+ echo
+ echo "**********************************************************"
+ echo /vservers/$1/.. has insecure permissions.
+ echo A vserver administrator may be able to visit the root server.
+ echo To fix this, do
+ echo " " chmod 000 /vservers/$1/..
+ echo do it anytime you want, even if vservers are running.
+ echo "**********************************************************"
+ echo
+ fi
+}
+# Set the IP alias needed by a vserver
+ifconfig_iproot()
+{
+ if [ "$NODEV" = "" -a "$IPROOT" != "" -a "$IPROOT" != "0.0.0.0" -a "$IPROOT" != "ALL" ] ;then
+ # A vserver may have more than one IP
+ # The first alias is dev:vserver
+ # and the other are dev:vserver1,2,3 and so on
+ # An IP may hold the device. The following is valid
+ # IPROOT="1.2.4.5 eth1:1.2.3.5"
+ # IPROOTDEV=eth0
+ # The first IP 1.2.3.4 will go on eth0 and the other on eth1
+ # VLAN devices are also supported (eth0.231 for vlan 231)
+ SUFFIX=
+ for oneip in $IPROOT
+ do
+ IPDEV=$IPROOTDEV
+ MASK=$IPROOTMASK
+ BCAST=$IPROOTBCAST
+ # Split the device and IP if available
+ case $oneip in
+ *:*)
+ eval `echo $oneip | tr : ' ' | (read dev ip; echo oneip=$ip; echo IPDEV=$dev)`
+ ;;
+ esac
+ # Split the IP and the netmask if available
+ case $oneip in
+ */*)
+ eval `echo $oneip | tr / ' ' | (read ip msk; echo oneip=$ip; echo MASK=$msk)`
+ eval `$USR_LIB_VSERVER/ifspec "" "$oneip" "$MASK" "$BCAST"`
+ ;;
+ esac
+ if [ "$IPDEV" != "" ] ; then
+ case $IPDEV in
+ *.*)
+ if [ ! -f /proc/net/vlan/$IPDEV ] ; then
+ /sbin/vconfig add `echo $IPDEV | tr . ' '`
+ # Put a dummy IP
+ /sbin/ifconfig $IPDEV 127.0.0.1
+ fi
+ ;;
+ esac
+ # Compute the default netmask, if missing
+ eval `$USR_LIB_VSERVER/ifspec $IPDEV "$oneip" "$MASK" "$BCAST"`
+ IPROOTMASK=$NETMASK
+ IPROOTBCAST=$BCAST
+ #echo /sbin/ifconfig $IPDEV:$1$SUFFIX $oneip netmask $IPROOTMASK broadcast $IPROOTBCAST
+ /sbin/ifconfig $IPDEV:$1$SUFFIX $oneip netmask $IPROOTMASK broadcast $IPROOTBCAST
+ fi
+ if [ "$SUFFIX" = "" ] ; then
+ SUFFIX=1
+ else
+ SUFFIX=`expr $SUFFIX + 1`
+ fi
+ done
+ fi
+ if [ "$IPROOTBCAST" = "" ] ; then
+ IPROOTBCAST=255.255.255.255
+ fi
+}
+ifconfig_iproot_off()
+{
+ if [ "$NODEV" = "" -a "$IPROOT" != "" -a "$IPROOT" != "0.0.0.0" -a "$IPROOT" != "ALL" -a "$IPROOTDEV" != "" ] ;then
+ SUFFIX=
+ for oneip in $IPROOT
+ do
+ IPDEV=$IPROOTDEV
+ # Split the device and IP if available
+ case $oneip in
+ *:*)
+ eval `echo $oneip | tr : ' ' | (read dev ip; echo IPDEV=$dev)`
+ ;;
+ esac
+ /sbin/ifconfig $IPDEV:$1$SUFFIX down 2>/dev/null
+ if [ "$SUFFIX" = "" ] ; then
+ SUFFIX=1
+ else
+ SUFFIX=`expr $SUFFIX + 1`
+ fi
+ done
+ fi
+}
+# Split an IPROOT definition, trash the devices and
+# compose a set of --ip option for chbind
+setipopt(){
+ RET=
+ IPS="$*"
+ if [ "$IPS" = "" ] ; then
+ IPS=0.0.0.0
+ fi
+ if [ "$1" = "ALL" ] ; then
+ IPS=`$USR_LIB_VSERVER/listdevip`
+ fi
+ for oneip in $IPS
+ do
+ # Split the device and IP if available
+ case $oneip in
+ *:*)
+ eval `echo $oneip | tr : ' ' | (read dev ip; echo oneip=$ip)`
+ ;;
+ esac
+ #case $oneip in
+ #*/*)
+ # eval `echo $oneip | tr / ' ' | (read ip msk; echo oneip=$ip)`
+ # ;;
+ #esac
+ echo --ip $oneip
+ done
+}
+
+# Extract the initial runlevel from the vserver inittab
+get_initdefault()
+{
+ INITDEFAULT=`grep :initdefault /vservers/$1/etc/inittab | sed 's/:/ /g' | ( read a level b; echo $level)`
+}
+
+# Read the vserver configuration file, reusing the PROFILE value
+# found in /var/run/vservers
+readlastconf()
+{
+ if [ -f /var/run/vservers/$1.ctx ] ; then
+ . /var/run/vservers/$1.ctx
+ if [ "$S_PROFILE" != "" ] ; then
+ export PROFILE=$S_PROFILE
+ fi
+ fi
+ export PROFILE
+ . /etc/vservers/$1.conf
+}
+usage()
+{
+ echo vserver [ options ] server-name command ...
+ echo
+ echo server-name is a directory in /vservers
+ echo
+ echo The commands are:
+ echo " build : Create a virtual server by copying the packages"
+ echo " of the root server"
+ echo " enter : Enter in the virtual server context and starts a shell"
+ echo " Same as \"vserver name exec /bin/sh\""
+ echo " exec : Exec a command in the virtual server context"
+ echo " suexec : Exec a command in the virtual server context uid"
+ echo " service : Control a service inside a vserver"
+ echo " vserver name service service-name start/stop/restart/status"
+ echo " start : Starts the various services in the vserver, runlevel 3"
+ echo " stop : Ends all services and kills the remaining processes"
+ echo " running : Tells if a virtual server is running"
+ echo " It returns proper exit code, so you can use it as a test"
+ echo " status : Tells some information about a vserver"
+ echo " chkconfig : It turns a server on or off in a vserver"
+ echo
+ echo "--nodev : Do not configure the IP aliases of the vserver"
+ echo " Useful to enter a vserver without enabling its network"
+ echo " and avoiding conflicts with another copy of this vserver"
+ echo " running elsewhere"
+ echo "--silent : No informative messages about vserver context and IP numbers"
+ echo " Useful when you want to redirect the output"
+}
+
+calculateCaps()
+{
+ local f
+ for f in "$@"; do
+ case $f in
+ !CAP_SYS_CHROOT)
+ CHROOTOPT=--nochroot
+ ;;
+ *)
+ CAPS="$CAPS --cap $f"
+ ;;
+ esac
+ done
+}
+
+SILENT=
+NODEV=
+while true
+do
+ if [ "$1" = "--silent" ] ; then
+ SILENT=--silent
+ shift
+ elif [ "$1" = "--nodev" ] ; then
+ NODEV=--nodev
+ shift
+ else
+ break
+ fi
+done
+# Setup the default ulimit for a vserver
+setdefulimit(){
+ # File handle are limited to half of the current system limit
+ # Virtual memory is limited to the ram size
+ NFILE=`cat /proc/sys/fs/file-max`
+ NFILE=`expr $NFILE / 2`
+ VMEM=`cat /proc/meminfo | grep MemTotal | (read a b c; echo $b)`
+ # Disabled for now, we need a different to set the security
+ # context limit than fiddling with ulimit
+ #ulimit -H -n $NFILE -v $VMEM
+}
+if [ $# -lt 2 ] ; then
+ usage
+elif [ "$2" = "build" ] ; then
+ # Either the directory does not exist or is empty
+ NBSUB=`ls /vservers/$1 2>/dev/null | grep -v lost+found | wc -l`
+ NBSUB=`expr $NBSUB`
+ if [ "$NBSUB" != 0 ] ; then
+ echo Virtual server /vservers/$1 already exist
+ else
+ if [ ! -d /vservers ] ; then
+ mkdir /vservers || exit 1
+ chmod 000 /vservers
+ echo Directory /vservers was created with permissions 000
+ fi
+ mkdir -p /vservers/$1 || exit 1
+ chmod 755 /vservers/$1
+ mkdir -p /vservers/$1/{etc/rc.d/init.d,sbin,var/run,var/log}
+ cd /vservers/$1 || exit 1
+ rm -fr lib/modules/*
+ rm -f var/spool/mail/*
+ rm -f `find var/run -type f`
+ rm -f `find var/log -type f`
+ touch var/log/wtmp
+ rm -f var/lock/subsys/*
+ rm -f etc/cron.d/kmod
+ mkdir proc tmp home root boot
+ test -f /root/.bashrc && cp -a /root/.bashrc root/.
+ test -f /root/.bash_profile && cp -a /root/.bash_profile root/.
+ chmod 1777 tmp
+ chmod 750 root
+ # Create a minimal dev so the virtual server can't grab
+ # more privileges
+ mkdir dev dev/pts
+ vserver_mknod dev/null c 1 3 666
+ vserver_mknod dev/zero c 1 5 666
+ vserver_mknod dev/full c 1 7 666
+ vserver_mknod dev/random c 1 8 644
+ vserver_mknod dev/urandom c 1 9 644
+ vserver_mknod dev/tty c 5 0 666
+ vserver_mknod dev/ptmx c 5 2 666
+ touch dev/hdv1
+ # Turn off some service useless on a vserver
+ # vserver_turnoff apmd network autofs dhcpd gpm ipchains iptables \
+ # irda isdn keytable kudzu linuxconf-setup netfs nfs nfslock \
+ # pcmcia portmap pppoe random rawdevices rhnsd rstatd ruserd \
+ # rwalld rwhod sendmail smb snmpd v_httpd h_xinetd v_sshd vservers \
+ # xfs ypbind xinetd
+ (
+ cd etc/init.d 2>/dev/null || cd etc/rc.d/init.d
+ for serv in *
+ do
+ case $serv in
+ *.bak|*~|functions|killall|halt|single)
+ ;;
+ *)
+ #$USR_LIB_VSERVER/capchroot /vservers/$1 /sbin/chkconfig --level 2345 $serv off
+ $0 --silent $1 chkconfig --level 2345 $serv off
+ ;;
+ esac
+ done
+ )
+ rm -f etc/rc.d/rc6.d/S*reboot
+ # Create a dummy /etc/fstab and /etc/mtab to please
+ # df and linuxconf. We use hdv1, which does not exist
+ # to remind the admin that it is not the real drive
+ echo /dev/hdv1 / ext2 defaults 1 1 >etc/fstab
+ echo /dev/hdv1 / ext2 rw 0 0 >etc/mtab
+ # Install the vreboot utility
+ cp -a $USR_LIB_VSERVER/vreboot sbin/.
+ ln -sf vreboot sbin/vhalt
+
+ echo Directory /vservers/$1 has been populated
+ if [ ! -d /etc/vservers ] ; then
+ mkdir /etc/vservers
+ chmod 600 /etc/vservers
+ echo Directory /etc/vservers has been created
+ fi
+ if [ ! -f /etc/vservers/$1.conf ] ; then
+ CONF=/etc/vservers/$1.conf
+ cat >$CONF <<-EOF
+if [ "$PROFILE" = "" ] ; then
+ PROFILE=prod
+fi
+# Select the IP number assigned to the virtual server
+# This IP must be one IP of the server, either an interface
+# or an IP alias
+# A vserver may have more than one IP. Separate them with spaces.
+# do not forget double quotes.
+# Some examples:
+# IPROOT="1.2.3.4 2.3.4.5"
+# IPROOT="eth0:1.2.3.4 eth1:2.3.4.5"
+# If the device is not specified, IPROOTDEV is used
+case \$PROFILE in
+prod)
+ IPROOT=1.2.3.4
+ # The netmask and broadcast are computed by default from IPROOTDEV
+ #IPROOTMASK=
+ #IPROOTBCAST=
+ # You can define on which device the IP alias will be done
+ # The IP alias will be set when the server is started and unset
+ # when the server is stopped
+ #IPROOTDEV=eth0
+ # You can set a different host name for the vserver
+ # If empty, the host name of the main server is used
+ S_HOSTNAME=
+ ;;
+backup)
+ IPROOT=1.2.3.4
+ #IPROOTMASK=
+ #IPROOTBCAST=
+ #IPROOTDEV=eth0
+ S_HOSTNAME=
+ ;;
+esac
+# Uncomment the onboot line if you want to enable this
+# virtual server at boot time
+#ONBOOT=yes
+# You can set a different NIS domain for the vserver
+# If empty, the current on is kept
+# Set it to "none" to have no NIS domain set
+S_DOMAINNAME=
+# You can set the priority level (nice) of all process in the vserver
+# Even root won't be able to raise it
+S_NICE=
+# You can set various flags for the new security context
+# lock: Prevent the vserver from setting new security context
+# sched: Merge scheduler priority of all processes in the vserver
+# so that it acts a like a single one.
+# nproc: Limit the number of processes in the vserver according to ulimit
+# (instead of a per user limit, this becomes a per vserver limit)
+# private: No other process can join this security context. Even root
+# Do not forget the quotes around the flags
+S_FLAGS="lock nproc"
+# You can set various ulimit flags and they will be inherited by the
+# vserver. You enter here various command line argument of ulimit
+# ULIMIT="-H -u 200"
+# The example above, combined with the nproc S_FLAGS will limit the
+# vserver to a maximum of 200 processes
+ULIMIT="-H -u 1000"
+# You can set various capabilities. By default, the vserver are run
+# with a limited set, so you can let root run in a vserver and not
+# worry about it. He can't take over the machine. In some cases
+# you can to give a little more capabilities (such as CAP_NET_RAW)
+# S_CAPS="CAP_NET_RAW"
+S_CAPS=""
+# Select an unused context (this is optional)
+# The default is to allocate a free context on the fly
+# In general you don't need to force a context
+#S_CONTEXT=
+ EOF
+ echo $CONF has been created. Look at it\!
+ fi
+ fi
+elif [ ! -f /etc/vservers/$1.conf ] ; then
+ echo No configuration for this vserver: /etc/vservers/$1.conf
+ exit 1
+elif [ ! -d /vservers/$1/. ] ; then
+ echo No directory for this vserver: /vservers/$1
+ exit 1
+elif [ "$2" = "start" ] ; then
+ echo Starting the virtual server $1
+ testperm $1
+ if ! $VSERVER_CMD $1 running
+ then
+ test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
+ IPROOT=
+ IPROOTMASK=
+ IPROOTBCAST=
+ IPROOTDEV=
+ S_NICE=
+ S_FLAGS=
+ . /etc/vservers/$1.conf
+ export PROFILE
+ ifconfig_iproot $1
+ cd /vservers/$1 || exit 1
+
+ if [ "$PROFILE" != "" ] ; then
+ echo export PROFILE=$PROFILE >etc/PROFILE
+ fi
+
+ rm -f `find var/run -type f`
+ touch var/run/utmp
+ rm -f var/lock/subsys/*
+ mountproc /vservers/$1
+ CTXOPT=
+ HOSTOPT=
+ DOMAINOPT=
+ NICECMD=
+ FLAGS=
+ CAPS=
+ get_initdefault $1
+ STARTCMD="/etc/rc.d/rc $INITDEFAULT"
+ if [ -x /vservers/$1/etc/init.d/rc ] ; then
+ STARTCMD="/etc/init.d/rc $INITDEFAULT"
+ fi
+
+ DISCONNECT=
+ FAKEINIT=
+ for f in $S_FLAGS dummy
+ do
+ case $f in
+ dummy)
+ ;;
+
+ minit)
+ FAKEINIT=true
+ FLAGS="$FLAGS --flag fakeinit"
+ STARTCMD=/sbin/minit-start
+ DISCONNECT=--disconnect
+ ;;
+
+ fakeinit)
+ FAKEINIT=true
+ FLAGS="$FLAGS --flag $f"
+ STARTCMD=/sbin/init
+ DISCONNECT=--disconnect
+ ;;
+ *)
+ FLAGS="$FLAGS --flag $f"
+ ;;
+ esac
+ done
+ if [ "$FAKEINIT" = "" ] ; then
+ $USR_LIB_VSERVER/fakerunlevel $INITDEFAULT var/run/utmp
+ fi
+
+ calculateCaps $S_CAPS
+
+ if [ "$S_CONTEXT" != "" ] ; then
+ CTXOPT="--ctx $S_CONTEXT"
+ fi
+ if [ "$S_HOSTNAME" != "" ] ; then
+ HOSTOPT="--hostname $S_HOSTNAME"
+ export HOSTNAME=$S_HOSTNAME
+ fi
+ if [ "$S_DOMAINNAME" != "" ] ; then
+ DOMAINOPT="--domainname $S_DOMAINNAME"
+ fi
+ if [ "$S_NICE" != "" ] ; then
+ NICECMD="nice -$S_NICE"
+ fi
+ mkdir -p /var/run/vservers
+ chmod 700 /var/run/vservers
+ setdefulimit
+ if [ "$ULIMIT" != "" ] ; then
+ ulimit $ULIMIT
+ fi
+ #echo FLAGS=$FLAGS
+ #echo CAPS=$CAPS
+ # We switch to /vservers/$1 now, because after the
+ # security context switch /vservers directory becomes a dead zone.
+ cd /vservers/$1
+ IPOPT=`setipopt $IPROOT`
+ export PATH=$DEFAULTPATH
+ $NICECMD $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+ $CHCONTEXT_CMD $SILENT $DISCONNECT $CAPS $FLAGS $CTXOPT $HOSTOPT $DOMAINOPT --secure \
+ $SAVE_S_CONTEXT_CMD /var/run/vservers/$1.ctx \
+ $CAPCHROOT_CMD $CHROOTOPT . $STARTCMD
+ sleep 2
+ test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-start $1
+ fi
+elif [ "$2" = "running" ] ; then
+ if [ ! -f /var/run/vservers/$1.ctx ] ; then
+ echo Server $1 is not running
+ exit 1
+ else
+ . /var/run/vservers/$1.ctx
+ NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
+ #NB=`$CHCONTEXT_CMD --silent --ctx $S_CONTEXT ps ax | wc -l`
+ #NB=`eval expr $NB + 0`
+ if [ "$NB" -gt 0 ] ; then
+ echo Server $1 is running
+ exit 0
+ else
+ echo Server $1 is not running
+ exit 1
+ fi
+ fi
+elif [ "$2" = "status" ] ; then
+ if $0 $1 running
+ then
+ . /var/run/vservers/$1.ctx
+ NB=$($USR_SBIN/vps ax | awk '{print $2}' | grep \^$S_CONTEXT\$ | wc -l)
+ echo $NB processes running
+ echo Vserver uptime: `$USR_LIB_VSERVER/filetime /var/run/vservers/$1.ctx`
+ fi
+elif [ "$2" = "stop" ] ; then
+ echo Stopping the virtual server $1
+ IPROOT=
+ IPROOTMASK=
+ IPROOTBCAST=
+ IPROOTDEV=
+ CAPS=
+ IS_MINIT=
+ readlastconf $1
+ if $VSERVER_CMD $1 running
+ then
+ test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-stop $1
+ ifconfig_iproot $1
+ cd /vservers/$1
+ mountproc /vservers/$1
+ # The fakeinit flag tell us how to turn off the server
+ get_initdefault $1
+ export PREVLEVEL=$INITDEFAULT
+ STOPCMD="/etc/rc.d/rc 6"
+ if [ -x /vservers/$1/etc/init.d/rc ] ; then
+ STOPCMD="/etc/init.d/rc 6"
+ fi
+ for f in $S_FLAGS dummy
+ do
+ case $f in
+ minit)
+ IS_MINIT=1
+ FLAGS="$FLAGS --flag fakeinit"
+ STOPCMD="/sbin/minit-stop"
+ ;;
+
+ fakeinit)
+ FLAGS="$FLAGS --flag $f"
+ STOPCMD="/sbin/init 6"
+ ;;
+ *)
+ ;;
+ esac
+ done
+
+ calculateCaps $S_CAPS
+
+ cd /vservers/$1
+ IPOPT=`setipopt $IPROOT`
+ export PATH=$DEFAULTPATH
+ $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+ $CHCONTEXT_CMD $SILENT $CAPS --secure --ctx $S_CONTEXT \
+ $CAPCHROOT_CMD . $STOPCMD
+
+ if test "$IS_MINIT"; then
+ echo "Waiting for minit finish-signal"
+ dd if=var/run/minit-stop of=/dev/zero bs=1 count=1 &>/dev/null
+ sleep 1
+ else
+ echo sleeping 5 seconds
+ sleep 5
+ fi
+
+ echo Killing all processes
+ $CHBIND_CMD --silent $IPOPT --bcast $IPROOTBCAST \
+ $CHCONTEXT_CMD $CAPS --secure --silent --ctx $S_CONTEXT \
+ $VSERVERKILLALL_CMD
+ fi
+ # We umount anyway, because "enter" establish the mount
+ # but when you exit, the server is considered not running
+ umountproc /vservers/$1
+ cd /
+ test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh post-stop $1
+ ifconfig_iproot_off $1
+elif [ "$2" = "restart" ] ; then
+ if $0 $1 running
+ then
+ $0 $1 stop
+ $0 $1 start
+ fi
+elif [ "$2" = "suexec" ] ; then
+ if [ -z "$3" ] ; then
+ echo "Missing user!" >&2
+ echo "vserver vserver-name suexec user command [ args ... ]" >&2
+ exit 1
+ elif [ -z "$4" ] ; then
+ echo "Missing command and arguments!" >&2
+ echo "vserver vserver-name suexec user command [ args ... ]" >&2
+ exit 1
+ else
+ IPROOT=
+ IPROOTMASK=
+ IPROOTBCAST=
+ IPROOTDEV=
+ readlastconf $1
+ . /etc/vservers/$1.conf
+ cd /vservers/$1
+ ifconfig_iproot $1
+ mountproc /vservers/$1
+ PS1="[\u@vserver:$1 \W]"
+ export PS1
+ VSERVER=$1
+ USERID=$3
+ shift; shift; shift
+ CAPS=
+ for f in $S_CAPS dummy
+ do
+ case $f in
+ dummy)
+ ;;
+ !CAP_SYS_CHROOT)
+ CHROOTOPT=--nochroot
+ ;;
+ *)
+ CAPS="$CAPS --cap $f"
+ ;;
+ esac
+ done
+ FLAGS=
+ for f in $S_FLAGS dummy
+ do
+ case $f in
+ minit)
+ FLAGS="$FLAGS --flag fakeinit"
+ ;;
+
+ dummy)
+ ;;
+ *)
+ FLAGS="$FLAGS --flag $f"
+ ;;
+ esac
+ done
+ setdefulimit
+ if [ "$ULIMIT" != "" ] ; then
+ ulimit $ULIMIT
+ fi
+ if $0 $VSERVER running >/dev/null
+ then
+ . /var/run/vservers/$VSERVER.ctx
+ cd /vservers/$VSERVER
+ IPOPT=`setipopt $IPROOT`
+ export PATH=$DEFAULTPATH
+ $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+ $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure --ctx $S_CONTEXT \
+ $CAPCHROOT_CMD --suid $USERID . "$@"
+ else
+ test -x /etc/vservers/$1.sh && /etc/vservers/$1.sh pre-start $1
+ CTXOPT=
+ HOSTOPT=
+ DOMAINOPT=
+ if [ "$S_CONTEXT" != "" ] ; then
+ CTXOPT="--ctx $S_CONTEXT"
+ fi
+ if [ "$S_HOSTNAME" != "" ] ; then
+ HOSTOPT="--hostname $S_HOSTNAME"
+ export HOSTNAME=$S_HOSTNAME
+ fi
+ if [ "$S_DOMAINNAME" != "" ] ; then
+ DOMAINOPT="--domainname $S_DOMAINNAME"
+ fi
+ mkdir -p /var/run/vservers
+ cd /vservers/$VSERVER
+ IPOPT=`setipopt $IPROOT`
+ export PATH=$DEFAULTPATH
+ $CHBIND_CMD $SILENT $IPOPT --bcast $IPROOTBCAST \
+ $CHCONTEXT_CMD $SILENT $FLAGS $CAPS --secure $CTXOPT $HOSTOPT $DOMAINOPT \
+ $SAVE_S_CONTEXT_CMD /var/run/vservers/$VSERVER.ctx \
+ $CAPCHROOT_CMD --suid $USERID $CHROOTOPT . "$@"
+ fi
+ fi
+elif [ "$2" = "exec" ] ; then
+ VSERV=$1
+ shift; shift
+ exec $0 $NODEV $SILENT $VSERV suexec root "$@"
+elif [ "$2" = "enter" ] ; then
+ testperm $1
+ exec $0 $NODEV $SILENT $1 exec /bin/bash -login
+elif [ "$2" = "service" ] ; then
+ VSERVER=$1
+ shift
+ shift
+ exec $0 $NODEV $SILENT $VSERVER exec /sbin/service "$@"
+elif [ "$2" = "chkconfig" ] ; then
+ VSERVER=$1
+ shift
+ shift
+ if [ "$1" = "--level" ] ; then
+ shift
+ LEVELS=$1
+ shift
+ fi
+ if [ $# != 2 -a ! -x /vservers/$VSERVER/sbin/chkconfig ] ; then
+ echo Invalid argument, expected vserver name chkconfig [ --level nnn ] service on\|off
+ elif [ -x /vservers/$VSERVER/sbin/chkconfig ] ; then
+ exec $0 --silent $VSERVER exec /sbin/chkconfig "$@"
+ elif [ -x /vservers/$VSERVER/usr/sbin/update-rc.d ] ; then
+ if [ "$2" = "on" -o "$2" = "start" ] ; then
+ $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
+ exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 start 80 2 3 4 5 . stop 20 0 1 6 . >/dev/null
+ elif [ "$2" = "off" -o "$2" = "stop" ] ; then
+ $0 --silent $VSERVER exec /usr/sbin/update-rc.d -f $1 remove >/dev/null
+ exec $0 --silent $VSERVER exec /usr/sbin/update-rc.d $1 stop 20 0 1 2 3 4 5 6 . >/dev/null
+ else
+ echo vserver chkconfig: Expecting on or off
+ fi
+ else
+ echo chkconfig functionality is not available on this
+ echo vserver distribution.
+ echo Looked for /sbin/chkconfig and /usr/sbin/update-rc.d
+ fi
+else
+ echo Command unknown $2
+ echo
+ usage
+fi
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserver-copy by Mark Lawrence <nomad@null.net>
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Copy/Sync a virtual host from one machine to another
+#
+# History:
+#
+# 2003-04-04: Version 0.4 - Mark lawrence
+# - Set "ONBOOT=no" in the destination .conf file when --startstop
+# is not used, in case the destination roothost reboots. We don't
+# want two copies of a vserver running at the same time.
+#
+# 2003-03-04: Version 0.3 - Mark lawrence
+# - Changed all checks for [ "" != "$var" ] into [ -n|-z "$var" ]. "" doesn't
+# seem to work for bash on the Sparc architecture.
+# - Changed $ssh variable into $shcmd.
+#
+# 2003-02-23: Version 0.2 - Mark Lawrence
+# - Set ONBOOT to "no" in the original .conf file when the "-s" flag is
+# used so that if/when you reboot the source roothost you don't have the
+# same vserver and IP address running on two machines.
+
+VERSION="0.4"
+umask 022
+me=${0##*/}
+
+
+### Helper functions ###
+
+# Save stdin and stdout for later use
+exec 3>&1
+exec 4>&2
+
+noninteractive () {
+ exec &> /dev/null
+}
+
+interactive () {
+ exec 1>&3
+ exec 2>&4
+}
+
+info () {
+ ! $quiet && echo "I: $me: $1" >&3
+}
+
+warn () {
+ ! $quiet && echo "W: $me: $1" >&4
+}
+
+error () {
+ ! $quiet && echo "E: $me: $2" >&4
+ exit $1
+}
+
+
+### Usage/Info functions ###
+
+usage () {
+ cat <<EOF 1>&2
+Usage: $me [-hVvqidrRs] vserver newname
+ $me [-hVvqidrRs] vserver host:[newname]
+EOF
+}
+
+full_usage () {
+ usage
+ cat <<EOF
+
+$me uses rsync to make a copy of a vserver. If the destination
+name contains a host specification the vserver will be synchronised to
+the remote destination over ssh/rsh.
+
+This can be used on a running vserver to make a warm backup. With the -s
+flag a vserver can even be operationally moved to different hardware within
+seconds.
+
+The -i and -d flags can be used to minimally reconfigure the destination
+vserver (rewrites /etc/vservers/newname.conf and /vservers/newname/etc/hosts)
+
+Options:
+ -h, --help this help
+ -V, --version copyright and version information
+ -v, --verbose show all output
+ -q, --quiet direct all output to /dev/null (no password
+ prompt for logins on remote hosts!)
+ -d, --domain [string] new dns domain (must be used with -i)
+ -i, --ip [addr] new IP address (must be used with -d)
+ -r, --vsroot location of "/vserver/" directory
+ -R, --rsh use rsh (instead of default ssh) for
+ network transport
+ -s, --stopstart stop the local vserver before copying and start
+ it on the destination host afterwards
+
+EOF
+}
+
+full_version () {
+ cat <<EOF
+$me version $VERSION
+Copyright (c) 2002 Mark Lawrence <nomad@null.net>
+
+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; either version 2 of the License, or (at
+your option) any later version.
+
+EOF
+}
+
+
+### Default values and Command line options ###
+
+stopstart=(false)
+verbose=(false)
+quiet=(false)
+shcmd="ssh"
+rsflag="-e"
+rsh=(false)
+colon=":"
+domain=""
+ip=""
+vsroot="/vservers"
+
+if [ $# -eq 0 ]; then # Script invoked with no command-line args?
+ usage
+ exit 1
+fi
+
+temp=$(getopt -o hVvqd:i:rRs --long help,version,verbose,quiet,domain:,ip:,vsroot,rsh,stopstart, -n $me -- "$@")
+
+if [ $? -ne 0 ]; then
+ echo " (See -h for help)"
+ exit 1
+fi
+
+# Note the quotes around `$temp': they are essential!
+eval set -- "$temp"
+
+while true; do
+ case "$1" in
+ -h|--help) full_usage
+ exit 1
+ ;;
+ -V|--version) full_version
+ exit 1
+ ;;
+ -v|--verbose) verbose=(true)
+ shift
+ ;;
+ -q|--quiet) quiet=(true)
+ shift
+ ;;
+ -d|--domain) domain="$2"
+ shift 2
+ ;;
+ -i|--ip) ip="$2"
+ shift 2
+ ;;
+ -r|--vsroot) vsroot="$2"
+ shift 2
+ ;;
+ -R|--rsh) rsh=(true)
+ shift
+ ;;
+ -s|--stopstart) stopstart=(true)
+ shift
+ ;;
+ --) shift
+ break
+ ;;
+ *) echo "Internal error!"
+ exit 1
+ ;;
+ esac
+done
+
+if [ $# -ne 2 ]; then
+ usage
+ exit 1
+fi
+
+
+### ###
+
+# By default we are reasonably quiet (ouput only via info, warn & error)
+if $verbose; then
+ interactive
+else
+ noninteractive
+fi
+
+now=$(date)
+info "called on $(hostname) at $now"
+
+
+vserver=$1
+vconf=/etc/vservers/$vserver.conf
+vroot=$vsroot/$vserver
+
+if $rsh; then
+ shcmd="rsh"
+fi
+
+if (echo $2 | grep '^[a-z][a-z0-9]\+$'); then
+ dhost=""
+ newname=$2
+ shcmd=""
+ rsflag=""
+ colon=""
+ if $rsh; then
+ warn "rsh is set but not used for a local copy"
+ fi
+elif (echo $2 | grep '^[a-z].*[a-z0-9]:$'); then
+ dhost=${2/:/}
+ newname=$vserver
+elif (echo $2 | grep '^[a-z].*[a-z0-9]:[a-z].*[a-z0-9]$'); then
+ dhost=${2/:*/}
+ newname=${2/*:/}
+else
+ error 1 "Second argument must be of the form \"[host:]name\" or \"host:\""
+fi
+
+target=$vsroot/$newname
+targetconf=/etc/vservers/$newname.conf
+
+
+### Perform some sanity checks ###
+
+if [ ! -d $vroot ]; then
+ error 1 "Directory \"$vroot\" does not exist"
+fi
+
+if [ ! -e $vconf ]; then
+ error 1 "Vserver file \"$vconf\" does not exist"
+fi
+
+if [ -z "$dhost" ] && [ "$vserver" == "$newname" ]; then
+ error 1 "Source and destination names cannot be the same on the localhost"
+fi
+
+if [ -n "$dhost" ] && ! (host $dhost | grep 'has address'); then
+ warn "$dhost does not resolve into an IP address"
+fi
+
+if [ \( -n "$ip" -a -z "$domain" \) -o \
+ \( -z "$ip" -a -n "$domain" \) ]
+then
+ error 1 "Both IP address and domain must be specified together"
+fi
+
+if [ -n "$ip" ] && \
+! (echo $ip | grep '^[0-9]\{1,3\}\(\.[0-9]\{1,3\}\)\{3\}$' ); then
+ error 1 "\"$ip\" is not a valid IP address"
+fi
+
+# This works both locally and remote
+if ($shcmd $dhost /usr/sbin/vserver $newname running | grep 'is running'); then
+ warn "destination vserver \"$newname\" is running"
+ error 1 "Cannot copy over a running vserver"
+fi
+
+
+### Do the copy ###
+
+info "Attempting to copy $vserver to $dhost$colon$newname"
+
+if $stopstart; then
+ info "Stopping virtual server \"$vserver\" on localhost"
+ /usr/sbin/vserver $vserver stop
+fi
+
+info "Syncing directories"
+# trailing slashes very important in the rsync!
+if ! rsync -avxz $rsflag $shcmd $vroot/ $dhost$colon$target/; then
+ error 1 "rsync failed"
+fi
+
+if [ -n "$ip" -a -n "$domain" ]; then
+ # Insert the new IPROOT/S_HOSTNAME values into the config file
+ info "Modifying $targetconf"
+ tmpf=$(tempfile)
+ if (sed -e "s/^S_HOSTNAME=.*/S_HOSTNAME=\"$newname\"/" \
+ -e "s/^IPROOT=.*/IPROOT=\"$ip\"/" $vconf > $tmpf)
+ then
+ if ! rsync -v $rsflag $shcmd $tmpf $dhost$colon$targetconf; then
+ error $? "vserver config file copy/change failed"
+ fi
+
+ else
+ warn "Unable to reconfigure virtual server config file"
+ fi
+
+ # create a new /etc/hostname
+ info "Creating hostname file"
+ echo $newname > $tmpf
+ if ! rsync -v $rsflag $shcmd $tmpf $dhost$colon$target/etc/hostname; then
+ error 1 "vserver /etc/hostname copy failed"
+ fi
+
+ info "Creating /etc/hosts"
+ cat << EOF > $tmpf
+# /etc/hosts (automatically generated by $me)
+
+127.0.0.1 localhost
+$ip $newname.$domain $newname
+
+# The following lines are desirable for IPv6 capable hosts
+
+::1 ip6-localhost ip6-loopback
+fe00::0 ip6-localnet
+ff00::0 ip6-mcastprefix
+ff02::1 ip6-allnodes
+ff02::2 ip6-allrouters
+ff02::3 ip6-allhosts
+EOF
+
+ # copy /etc/hosts
+ if ! rsync -v $rsflag $shcmd $tmpf $dhost$colon$target/etc/hosts; then
+ error 1 "vserver /etc/hosts copy failed"
+ fi
+ rm -f $tmpf
+
+else
+ if ! $stopstart; then
+ # Make sure that this vserver doesn't start on the
+ # destination host if it reboots
+ tmpf=$(tempfile)
+ sed -e 's/^ONBOOT=.*/ONBOOT=no/' $vconf > $tmpf
+ vconf=$tmpf
+ fi
+
+ # copy newname.conf unchanged
+ info "Copying $targetconf"
+ if ! rsync -v $rsflag $shcmd $vconf $dhost$colon$targetconf; then
+ error 1 "vserver config file copy/change failed"
+ fi
+
+ rm -f $tmpf
+fi
+
+
+if $stopstart; then
+ info "Starting virtual server \"$vserver\" on $dhost"
+ $shcmd $dhost /usr/sbin/vserver $vserver start
+ if ($shcmd $dhost /usr/sbin/vserver $vserver running | \
+ grep 'not running'); then
+ error 1 "Virtual server \"$vserver\" failed to start on $dhost"
+ fi
+
+ # Make sure that we don't start the original on next boot
+ tmpf=$(tempfile)
+ sed -e 's/^ONBOOT=.*/ONBOOT=no/' $vconf > $tmpf
+ mv $tmpf $vconf
+fi
+
+exit 0
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vserverkillall by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This script kills all process it can finds
+# Only useful if you are using a security context.
+# It does nothing in context 0
+USR_LIB_VSERVER=$(dirname $0)
+CTX=`grep ^s_context /proc/self/status | sed s/s_context:// | (read a b; echo $a)`
+CTX=`eval expr $CTX + 0`
+if [ "$CTX" = 0 ] ; then
+ echo Running in security context 0, do nothing
+else
+ cd /proc
+ for SIG in -TERM -TERM -TERM -9
+ do
+ ONE=0
+ for dir in *
+ do
+ case $dir in
+ 1)
+ ;;
+ $$)
+ ;;
+ [1-9]*)
+ ONE=1
+ echo kill $SIG "`$USR_LIB_VSERVER/readlink /proc/$dir/exe`"[$dir]
+ kill $SIG $dir
+ ;;
+ *)
+ ;;
+ esac
+ done
+ if [ "$ONE" = 0 ] ; then
+ break
+ fi
+ sleep 1
+ done
+ # Kill the fakeinit process. It is shown as process one, but can't
+ # be killed this way
+ INITPID=`cat /proc/self/status | grep initpid: | (read a b; expr $b)`
+ if [ "$INITPID" != "0" ] ; then
+ echo kill init, pid $INITPID
+ kill -9 $INITPID
+ fi
+fi
+
+
--- /dev/null
+#!/bin/sh
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vservers.grabinfo.sh by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Produce some XML statistics about vservers
+
+: ${UTIL_VSERVER_VARS:=$(dirname $0)/util-vserver-vars}
+test -e "$UTIL_VSERVER_VARS" || {
+ echo "Can not find util-vserver installation; aborting..."
+ exit 1
+}
+. "$UTIL_VSERVER_VARS"
+
+cd /vservers
+for vserv in *
+do
+ if [ -f /etc/vservers/$vserv.conf ] ; then
+ . /etc/vservers/$vserv.conf
+ echo "<m:vserver name=\"$vserv\" onboot=\"$ONBOOT\" HOSTNAME=\"$S_HOSTNAME\">"
+ for ip in $IPROOT
+ do
+ case $ip in
+ *:*)
+ echo $ip | tr ':' ' ' | (read a b; echo " <m:ip num=\"$b\"/>")
+ ;;
+ *)
+ echo " <m:ip num=\"$ip\"/>"
+ ;;
+ esac
+ done
+ echo " <status>"
+ $SBINDIR/vserver $vserv status
+ echo " </status>"
+ echo "</m:vserver>"
+ fi
+done
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vsyswrapper by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# Helper script for all the v_xxx scripts
+USR_SBIN=/usr/sbin
+if [ $# = 0 ] ; then
+ echo vsysvwrapper service_name >&2
+else
+ SERVICE=$1
+ shift
+ IP=eth0
+ if [ -f /etc/vservices/$SERVICE.conf ] ; then
+ . /etc/vservices/$SERVICE.conf
+ fi
+ IPOPT=
+ for oneip in $IP
+ do
+ IPOPT="$IPOPT --ip $oneip"
+ done
+ echo exec $USR_SBIN/chbind $IPOPT /etc/init.d/$SERVICE $*
+ exec $USR_SBIN/chbind $IPOPT /etc/init.d/$SERVICE $*
+fi
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vtop by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+#Presents the processes running in all virtual servers
+exec /usr/sbin/chcontext --silent --ctx 1 top $*
+
+
--- /dev/null
+#!/bin/sh
+
+# Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+# based on vunify by Jacques Gelinas
+#
+# 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; either version 2, or (at your option)
+# any later version.
+#
+# 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.
+
+# This scripts is used to unify the disk space used by vservers
+# It takes various RPM packages and hard link them together so all
+# vservers are sharing the same exact copy of the files.
+# After doing so, it set them immutable, so the vserver can't change them
+
+# This has the following advantages:
+# -You save disk space. If you have 100 vservers, each using 500 megs
+# (common linux server installation), you can unify 90% of that
+# -Memory usage. Since the exact same binary are loaded, including
+# the same shared object, you save some memory and this can increase
+# performance, especially the memory cache usage.
+#
+# On the down side, you are loosing some flexibility. The vserver
+# administrators can't upgrade package as they see fit, since the
+# files are immutable. On the other end, just unifying glibc is probably
+# a win.
+if [ $# = 0 ] ; then
+ echo vunify [ --undo ] ref-vserver vservers -- packages
+else
+ undo=0
+ if [ "$1" == "--undo" ] ; then
+ undo=1
+ shift
+ fi
+ ref=$1
+ shift
+ servers=
+ while [ "$1" != "" -a "$1" != "--" ]
+ do
+ servers="$servers $1"
+ shift
+ done
+ if [ "$servers" = "" ] ; then
+ echo No vserver specified >&2
+ exit 1
+ elif [ "$1" != "--" ] ; then
+ echo Missing -- marker >&2
+ exit 1
+ else
+ shift
+ if [ $# = 0 ] ; then
+ echo No package specified >&2
+ exit 1
+ else
+ if [ ! -d /vservers/$ref/. ] ; then
+ echo No vserver $ref >&2
+ exit 1
+ else
+ #echo ref=$ref
+ #echo servers=$servers
+ #echo packages=$*
+ tmpfile=/var/run/vunifi.$$
+ rm -f $tmpfile
+ echo Extracting list of file to unify in $tmpfile
+ for pkg in $*
+ do
+ /vservers/$ref/bin/rpm --root /vservers/$ref -ql --dump $pkg | \
+ while read path size mtime md5 \
+ mode owner group isconfig isdoc rdev symlink
+ do
+ if [ "$isconfig" = 0 ] ; then
+ echo $path >>$tmpfile
+ fi
+ done
+ done
+ for serv in $servers
+ do
+ if [ "$undo" = 0 ] ; then
+ echo Unifying server $serv
+ cat $tmpfile | while read file
+ do
+ if [ ! -d /vservers/$ref/$file -a ! -L /vservers/$ref/$file ] ; then
+ ln -f /vservers/$ref/$file /vservers/$serv/$file
+ fi
+ done
+ cat $tmpfile | while read file
+ do
+ chattr +i /vservers/$ref/$file
+ done
+ else
+ echo Differencing server $serv
+ cat $tmpfile | while read file
+ do
+ chattr -i /vservers/$ref/$file
+ if [ ! -d /vservers/$ref/$file ] ; then
+ rm -f /vservers/$serv/$file
+ cp -a /vservers/$ref/$file /vservers/$serv/$file
+ fi
+ done
+ fi
+ done
+ rm -f $tmpfile
+ fi
+ fi
+ fi
+fi
+
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+src_HDRS = src/vutil.h src/vutil.p
+
+src_pkglib_PRGS = src/capchroot \
+ src/fakerunlevel \
+ src/filetime \
+ src/ifspec \
+ src/listdevip \
+ src/parserpmdump \
+ src/readlink \
+ src/showattr \
+ src/showperm \
+ src/vbuild \
+ src/vcheck \
+ src/vreboot \
+ src/vunify
+
+src_sbin_PRGS = src/chbind \
+ src/chcontext \
+ src/rebootmgr \
+ src/reducecap \
+ src/setctxlimit \
+ src/vdu \
+ src/vfiles \
+ src/vserver-stat
+
+src_capchroot_SOURCES = src/capchroot.c
+src_capchroot_LDADD = lib/libvserver.a
+
+src_chbind_SOURCES = src/chbind.c
+src_chbind_LDADD = lib/libvserver.a
+
+src_chcontext_SOURCES = src/chcontext.c
+src_chcontext_LDADD = lib/libvserver.a
+
+src_fakerunlevel_SOURCES = src/fakerunlevel.c
+src_filetime_SOURCES = src/filetime.c
+src_ifspec_SOURCES = src/ifspec.c
+src_listdevip_SOURCES = src/listdevip.c
+src_parserpmdump_SOURCES = src/parserpmdump.c
+src_readlink_SOURCES = src/readlink.c
+src_rebootmgr_SOURCES = src/rebootmgr.c
+
+src_reducecap_SOURCES = src/reducecap.c
+src_reducecap_LDADD = lib/libvserver.a
+
+src_setctxlimit_SOURCES = src/setctxlimit.c
+src_setctxlimit_LDADD = lib/libvserver.a
+
+src_showattr_SOURCES = src/showattr.c
+src_showperm_SOURCES = src/showperm.c
+src_vbuild_SOURCES = src/vbuild.cc src/vutil.cc
+src_vdu_SOURCES = src/vdu.c
+src_vfiles_SOURCES = src/vfiles.cc src/vutil.cc
+src_vreboot_SOURCES = src/vreboot.c
+
+src_vserver_stat_SOURCES = src/vserver-stat.c
+src_vserver_stat_LDADD = lib/libvserver.a
+
+src_vunify_SOURCES = src/vunify.cc src/vutil.cc
+src_vcheck_SOURCES = src/vcheck.cc src/vutil.cc
+
+
+## Local Variables:
+## compile-command: "make -C .. -k"
+## End:
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on capchroot.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This chroot command does very little. Once the chroot
+ system call is executed, it (option) remove the CAP_SYS_CHROOT
+ capability. Then it executes its argument
+*/
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "linuxcaps.h"
+#include "vserver.h"
+
+static int my_chroot(const char *dir)
+{
+ int ret = -1;
+ if (has_chrootsafe()){
+ ret = call_chrootsafe(dir);
+ }else{
+ //fprintf (stderr,"Kernel do not support chrootsafe(), using chroot()\n");
+ ret = chroot (dir);
+ }
+ return ret;
+}
+
+int main (int argc, char *argv[])
+{
+ if (argc < 3){
+ fprintf (stderr,"capchroot version %s\n",VERSION);
+ fprintf (stderr
+ ,"capchroot --nochroot directory [ --suid user ] command argument\n"
+ "\n"
+ "--nochroot remove the CAP_SYS_CHROOT capability\n"
+ " after the chroot system call.\n"
+ "--suid switch to a different user (in the vserver context)\n"
+ " before executing the command.\n");
+ }else{
+ const char *uid = NULL;
+ bool nochroot = false;
+ int dir;
+ for (dir=1; dir<argc; dir++){
+ const char *arg = argv[dir];
+ if (arg[0] != '-' && arg[1] != '-'){
+ break;
+ }else if (strcmp(arg,"--nochroot")==0){
+ nochroot = true;
+ }else if (strcmp(arg,"--suid")==0){
+ dir++;
+ uid = argv[dir];
+ }
+
+ }
+ // We resolve the UID before doing the chroot.
+ // If we do the getpwnam after the chroot, we will end
+ // up loading shared object from the vserver.
+ // This is causing two kind of problem: Incompatibilities
+ // and also a security flaw. The shared objects in the vserver
+ // may be tweaked to get control of the root server ...
+ getpwnam ("root");
+ if (my_chroot (argv[dir]) == -1){
+ fprintf (stderr,"Can't chroot to directory %s (%s)\n",argv[dir]
+ ,strerror(errno));
+ }else{
+ struct passwd *p = NULL;
+ int cmd = dir + 1;
+
+ if (nochroot){
+ call_new_s_context (0,NULL,1<<CAP_SYS_CHROOT,0);
+ }
+
+ if (uid != NULL && strcmp(uid,"root")!=0){
+ p = getpwnam(uid);
+ if (p == NULL){
+ fprintf (stderr,"User not found: %s\n",uid);
+ exit (-1);
+ }
+ }
+ if (p != NULL) {
+ setgroups (0,NULL);
+ setgid(p->pw_gid);
+ setuid(p->pw_uid);
+ }
+ if (cmd >= argc){
+ fprintf (stderr,"capchroot: No command to execute, do nothing\n");
+ }else{
+ execvp (argv[cmd],argv+cmd);
+ fprintf (stderr,"Can't execute %s (%s)\n",argv[cmd]
+ ,strerror(errno));
+ }
+ }
+ }
+ return -1;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on chbind.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "vserver.h"
+
+static void usage()
+{
+ fprintf (stderr,"chbind version %s\n",VERSION);
+ fprintf (stderr,"chbind [ --silent ] [ --ip ip_num[/mask] ] [ --bcast broadcast ] command argument\n");
+ exit (-1);
+}
+
+/*
+ Check if a network device exist in /proc/net/dev.
+ This is used because ifconfig_ioctl triggers modprobe if requesting
+ information about non existant devices.
+
+ Return != 0 if the device exist.
+*/
+static int chbind_devexist (const char *dev)
+{
+ int ret = 0;
+ FILE *fin = fopen ("/proc/net/dev","r");
+ if (fin != NULL){
+ int len = strlen(dev);
+ char buf[1000];
+ fgets(buf,sizeof(buf)-1,fin); // Skip one line
+ while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
+ const char *pt = strstr(buf,dev);
+ if (pt != NULL && pt[len] == ':'){
+ ret = 1;
+ break;
+ }
+ }
+ fclose (fin);
+ }
+ return ret;
+}
+
+
+static int ifconfig_ioctl(
+ int fd,
+ const char *ifname,
+ int cmd,
+ struct ifreq *ifr)
+{
+ strcpy(ifr->ifr_name, ifname);
+ return ioctl(fd, cmd,ifr);
+}
+
+/*
+ Fetch the IP number of an interface from the kernel.
+ Assume the device is already available in the kernel
+ Return -1 if any error.
+*/
+int ifconfig_getaddr (
+ const char *ifname,
+ unsigned long *addr,
+ unsigned long *mask,
+ unsigned long *bcast)
+{
+ int ret = -1;
+ if (chbind_devexist(ifname)){
+ int skfd = socket(AF_INET, SOCK_DGRAM, 0);
+ *addr = 0;
+ *bcast = 0xffffffff;
+ if (skfd != -1){
+ struct ifreq ifr;
+ if (ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ *addr = sin->sin_addr.s_addr;
+ ret = 0;
+ }
+ if (ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ *mask = sin->sin_addr.s_addr;
+ ret = 0;
+ }
+ if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ *bcast = sin->sin_addr.s_addr;
+ ret = 0;
+ }
+ close (skfd);
+ }
+ }
+ return ret;
+}
+
+
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ int silent = 0;
+ int i;
+ unsigned long addrs[16],masks[16];
+ int nbaddrs = 0;
+ unsigned long bcast = 0xffffffff;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ const char *opt = argv[i+1];
+ if (strcmp(arg,"--ip")==0){
+ unsigned long addr,mask;
+ if (nbaddrs == 16){
+ fprintf (stderr,"Too many IP numbers, max 16, ignored\n");
+
+ }else if (ifconfig_getaddr(opt,&addr,&mask,&bcast)==-1){
+ unsigned long mask = 0x00ffffff;
+ const char *pt = strchr(opt,'/');
+ char tmpopt[strlen(opt)+1];
+ struct hostent *h;
+
+ if (pt != NULL){
+ strcpy (tmpopt,opt);
+ tmpopt[pt-opt] = '\0';
+ opt = tmpopt;
+ pt++;
+ if (strchr(pt,'.')==NULL){
+ // Ok, we have a network size, not a netmask
+ int size = atoi(pt);
+ int i;
+ mask = 0;
+ for (i=0; i<size; i++){
+ mask = mask >> 1;
+ mask |= 0x80000000;
+ }
+ mask = ntohl(mask);
+ }else{
+ struct hostent *h = gethostbyname (pt);
+ if (h != NULL){
+ memcpy (&mask,h->h_addr,sizeof(mask));
+ }else{
+ fprintf (stderr,"Invalid netmask: %s\n",pt);
+ usage();
+ }
+ }
+
+ }
+
+ h = gethostbyname (opt);
+ if (h == NULL){
+ fprintf (stderr,"Invalid IP number or host name: %s\n",opt);
+ usage();
+ }else{
+ memcpy (&addr,h->h_addr,sizeof(addr));
+ masks[nbaddrs] = mask;
+ addrs[nbaddrs++] = addr;
+ }
+ }else{
+ masks[nbaddrs] = mask;
+ addrs[nbaddrs++] = addr;
+ }
+ i++;
+ }else if (strcmp(arg,"--bcast")==0){
+ unsigned long tmp;
+ if (ifconfig_getaddr(opt,&tmp,&tmp,&bcast)==-1){
+ struct hostent *h = gethostbyname (opt);
+ if (h == NULL){
+ fprintf (stderr,"Invalid broadcast number: %s\n",opt);
+ usage();
+ }else{
+ memcpy (&bcast,h->h_addr,sizeof(bcast));
+ }
+ }
+ i++;
+ }else if (strcmp(arg,"--silent")==0){
+ silent = 1;
+ }else{
+ break;
+ }
+ }
+ if (i == argc){
+ usage();
+ }else if (argv[i][0] == '-'){
+ usage();
+ }else{
+ if (call_set_ipv4root(addrs,nbaddrs,bcast,masks)==0){
+ if (!silent){
+ int i;
+ printf ("ipv4root is now");
+ for (i=0; i<nbaddrs; i++){
+ unsigned long hostaddr = ntohl(addrs[i]);
+ printf (" %ld.%ld.%ld.%ld"
+ ,hostaddr>>24
+ ,(hostaddr>>16)&0xff
+ ,(hostaddr>>8)&0xff
+ ,hostaddr &0xff);
+ }
+ printf ("\n");
+ }
+ execvp (argv[i],argv+i);
+ fprintf (stderr,"Can't exec %s (%s)\n",argv[i],strerror(errno));
+ }else{
+ fprintf (stderr,"Can't set the ipv4 root (%s)\n",strerror(errno));
+ }
+ }
+ return ret;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on chcontext.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ chcontext is a wrapper to user the new_s_context system call. It
+ does little more than mapping command line option to the system call
+ arguments.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "linuxcaps.h"
+#include "vserver.h"
+
+static void usage()
+{
+ fprintf (stderr,"chcontext version %s\n",VERSION);
+ fprintf (stderr
+ ,"chcontext [ options ] command arguments ...\n"
+ "\n"
+ "chcontext allocate a new security context and executes\n"
+ "a command in that context.\n"
+ "By default, a new/unused context is allocated\n"
+ "\n"
+
+ "--cap CAP_NAME\n"
+ "\tAdd a capability from the command. This option may be\n"
+ "\trepeated several time.\n"
+ "\tSee /usr/include/linux/capability.h\n"
+ "\tIn general, this option is used with the --secure option\n"
+ "\t--secure removes most critical capabilities and --cap\n"
+ "\tadds specific ones.\n"
+ "\n"
+
+ "--cap !CAP_NAME\n"
+ "\tRemove a capability from the command. This option may be\n"
+ "\trepeated several time.\n"
+ "\tSee /usr/include/linux/capability.h\n"
+ "\n"
+ "--ctx num\n"
+ "\tSelect the context. On root in context 0 is allowed to\n"
+ "\tselect a specific context.\n"
+ "\tContext number 1 is special. It can see all processes\n"
+ "\tin any contexts, but can't kill them though.\n"
+ "\tOption --ctx may be repeated several times to specify up to 16 contexts.\n"
+
+ "--disconnect\n"
+ "\tStart the command in background and make the process\n"
+ "\ta child of process 1.\n"
+
+ "--domainname new_domainname\n"
+ "\tSet the domainname (NIS) in the new security context.\n"
+ "\tUse \"none\" to unset the domain name.\n"
+
+ "--flag\n"
+ "\tSet one flag in the new or current security context. The following\n"
+ "\tflags are supported. The option may be used several time.\n"
+ "\n"
+ "\tfakeinit: The new process will believe it is process number 1.\n"
+ " Useful to run a real /sbin/init in a vserver.\n"
+ "\tlock: The new process is trapped and can't use chcontext anymore.\n"
+ "\tsched: The new process and its children will share a common \n"
+ " execution priority.\n"
+ "\tnproc: Limit the number of process in the vserver according to\n"
+ " ulimit setting. Normally, ulimit is a per user thing.\n"
+ " With this flag, it becomes a per vserver thing.\n"
+ "\tprivate: No one can join this security context once created.\n"
+ "\tulimit: Apply the current ulimit to the whole context\n"
+
+ "--hostname new_hostname\n"
+ "\tSet the hostname in the new security context\n"
+ "\tThis is need because if you create a less privileged\n"
+ "\tsecurity context, it may be unable to change its hostname\n"
+
+ "--secure\n"
+ "\tRemove all the capabilities to make a virtual server trustable\n"
+
+ "--silent\n"
+ "\tDo not print the allocated context number.\n"
+ "\n"
+ "Information about context is found in /proc/self/status\n");
+}
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ int i;
+ int nbctx = 0;
+ int ctxs[16];
+ int disconnect = 0;
+ int fakeinit = 0;
+ int silent = 0;
+ int flags = 0;
+ unsigned remove_cap = 0;
+ unsigned add_cap = 0;
+ unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
+ |(1<<CAP_NET_BROADCAST)
+ |(1<<CAP_NET_ADMIN)
+ |(1<<CAP_NET_RAW)
+ |(1<<CAP_IPC_LOCK)
+ |(1<<CAP_IPC_OWNER)
+ |(1<<CAP_SYS_MODULE)
+ |(1<<CAP_SYS_RAWIO)
+ |(1<<CAP_SYS_PACCT)
+ |(1<<CAP_SYS_ADMIN)
+ |(1<<CAP_SYS_BOOT)
+ |(1<<CAP_SYS_NICE)
+ |(1<<CAP_SYS_RESOURCE)
+ |(1<<CAP_SYS_TIME)
+ |(1<<CAP_MKNOD);
+ const char *hostname=NULL, *domainname=NULL;
+
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ const char *opt = argv[i+1];
+ if (strcmp(arg,"--ctx")==0){
+ if (nbctx >= 16){
+ fprintf (stderr,"Too many context, max 16, ignored.\n");
+ }else{
+ ctxs[nbctx++] = atoi(opt);
+ }
+ i++;
+ }else if (strcmp(arg,"--disconnect")==0){
+ disconnect = 1;
+ }else if (strcmp(arg,"--silent")==0){
+ silent = 1;
+ }else if (strcmp(arg,"--flag")==0){
+ if (strcmp(opt,"lock")==0){
+ flags |= 1;
+ }else if (strcmp(opt,"sched")==0){
+ flags |= 2;
+ }else if (strcmp(opt,"nproc")==0){
+ flags |= 4;
+ }else if (strcmp(opt,"private")==0){
+ flags |= 8;
+ }else if (strcmp(opt,"fakeinit")==0){
+ fakeinit = 1;
+ flags |= 16;
+ }else if (strcmp(opt,"hideinfo")==0){
+ flags |= 32;
+ }else if (strcmp(opt,"ulimit")==0){
+ flags |= 64;
+ }else{
+ fprintf (stderr,"Unknown flag %s\n",opt);
+ }
+ i++;
+ }else if (strcmp(arg,"--cap")==0){
+ static struct {
+ const char *option;
+ int bit;
+ }tbcap[]={
+ // The following capabilities are normally available
+ // to vservers administrator, but are place for
+ // completeness
+ {"CAP_CHOWN",CAP_CHOWN},
+ {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
+ {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
+ {"CAP_FOWNER",CAP_FOWNER},
+ {"CAP_FSETID",CAP_FSETID},
+ {"CAP_KILL",CAP_KILL},
+ {"CAP_SETGID",CAP_SETGID},
+ {"CAP_SETUID",CAP_SETUID},
+ {"CAP_SETPCAP",CAP_SETPCAP},
+ {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
+ {"CAP_LEASE",CAP_LEASE},
+ {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
+
+ // Those capabilities are not normally available
+ // to vservers because they are not needed and
+ // may represent a security risk
+ {"CAP_LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
+ {"CAP_NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
+ {"CAP_NET_BROADCAST",CAP_NET_BROADCAST},
+ {"CAP_NET_ADMIN", CAP_NET_ADMIN},
+ {"CAP_NET_RAW", CAP_NET_RAW},
+ {"CAP_IPC_LOCK", CAP_IPC_LOCK},
+ {"CAP_IPC_OWNER", CAP_IPC_OWNER},
+ {"CAP_SYS_MODULE",CAP_SYS_MODULE},
+ {"CAP_SYS_RAWIO", CAP_SYS_RAWIO},
+ {"CAP_SYS_PACCT", CAP_SYS_PACCT},
+ {"CAP_SYS_ADMIN", CAP_SYS_ADMIN},
+ {"CAP_SYS_BOOT", CAP_SYS_BOOT},
+ {"CAP_SYS_NICE", CAP_SYS_NICE},
+ {"CAP_SYS_RESOURCE",CAP_SYS_RESOURCE},
+ {"CAP_SYS_TIME", CAP_SYS_TIME},
+ {"CAP_MKNOD", CAP_MKNOD},
+ {NULL,0}
+ };
+ int j;
+ unsigned *cap = &add_cap;
+ if (opt[0] == '!'){
+ cap = &remove_cap;
+ opt++;
+ }
+ for (j=0; tbcap[j].option != NULL; j++){
+ if (strcasecmp(tbcap[j].option,opt)==0){
+ *cap |= (1<<tbcap[j].bit);
+ break;
+ }
+ }
+ if (tbcap[j].option == NULL){
+ fprintf (stderr,"Unknown capability %s\n",opt);
+ }
+ i++;
+ }else if (strcmp(arg,"--secure")==0){
+ remove_cap |= secure;
+ }else if (strcmp(arg,"--hostname")==0){
+ hostname = opt;
+ i++;
+ }else if (strcmp(arg,"--domainname")==0){
+ if (opt != NULL && strcmp(opt,"none")==0) opt = "";
+ domainname = opt;
+ i++;
+ }else{
+ break;
+ }
+ }
+ if (i == argc){
+ usage();
+ }else if (argv[i][0] == '-'){
+ usage();
+ }else{
+ /*
+ We must fork early because fakeinit set the current
+ process as the special init process
+ */
+ if (disconnect == 0 || fork()==0){
+ int newctx;
+ if (nbctx == 0) ctxs[nbctx++] = -1;
+ newctx = call_new_s_context(nbctx,ctxs,0,flags);
+ if (newctx != -1){
+ if (hostname != NULL){
+ if (sethostname (hostname,strlen(hostname))==-1){
+ fprintf (stderr,"Can't set the host name (%s)\n"
+ ,strerror(errno));
+ }else if (!silent){
+ printf ("Host name is now %s\n",hostname);
+ }
+ }
+ if (domainname != NULL){
+ setdomainname (domainname,strlen(domainname));
+ if (!silent){
+ printf ("Domain name is now %s\n",domainname);
+ }
+ }
+ remove_cap &= (~add_cap);
+ if (remove_cap != 0) call_new_s_context (0,NULL,remove_cap,0);
+ if (!silent){
+ printf ("New security context is %d\n"
+ ,ctxs[0] == -1 ? newctx : ctxs[0]);
+ }
+ execvp (argv[i],argv+i);
+ fprintf (stderr,"Can't exec %s (%s)\n",argv[i]
+ ,strerror(errno));
+ }else{
+ perror ("Can't set the new security context\n");
+ }
+ if (disconnect != 0) _exit(0);
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on fakerunlevel.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This program add a RUNLEVEL record in a utmp file.
+ This is used when a vserver lack a private init process
+ so runlevel properly report the fake runlevel.
+*/
+#include <utmp.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+
+static void usage()
+{
+ fprintf (stderr,"fakerunlevel version %s\n",VERSION);
+ fprintf (stderr
+ ,"\n"
+ "fakerunlevel runlevel utmp_file\n"
+ "\n"
+ "Put a runlevel record in file utmp_file\n");
+}
+
+int main (int argc, char *argv[])
+{
+ if (argc != 3){
+ usage();
+ }else{
+ int runlevel = atoi(argv[1]);
+ const char *fname = argv[2];
+ if (runlevel < 1 || runlevel > 5){
+ usage();
+ }else{
+ // Make sure the file exist
+ FILE *fout = fopen (fname,"a");
+ if (fout == NULL){
+ fprintf (stderr,"Can't open file %s (%s)\n",fname
+ ,strerror(errno));
+ }else{
+ struct utmp ut;
+
+ fclose (fout);
+ utmpname (fname);
+ setutent();
+ memset (&ut,0,sizeof(ut));
+ ut.ut_type = RUN_LVL;
+ ut.ut_pid = ('#' << 8) + runlevel+'0';
+ pututline (&ut);
+ endutent();
+ }
+ }
+ }
+
+ return 0;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on filetime.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/stat.h>
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc != 2){
+ fprintf (stderr
+ ,"filetime version %s\n"
+ "filetime file\n"
+ "\n"
+ "Prints the age of a file\n"
+ "(how long since it was created or modified)\n"
+ ,VERSION);
+ }else{
+ struct stat st;
+ if (stat(argv[1],&st)==-1){
+ fprintf (stderr,"Can't stat file %s (%s)\n",argv[1]
+ ,strerror(errno));
+ }else{
+ time_t now = time(NULL);
+ time_t since = now - st.st_mtime;
+ int days = since / (24*60*60);
+ int today = since % (24*60*60);
+ int hours = today / (60*60);
+ int minutes = (today % (60*60)) / 60;
+ if (days > 0){
+ printf ("%d days ",days);
+ }
+ printf ("%02d:%02d\n",hours,minutes);
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on ifspec.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Prints the specs of a network device in shell like form
+
+ ADDR=
+ NETMASK=
+ BCAST=
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+static void usage()
+{
+ fprintf (stderr,"ifspec version %s\n",VERSION);
+ fprintf (stderr
+ ,"ifspec network-device [ ipaddr netmask broadcast ]\n"
+ "prints device specification in a shell usable way\n");
+ exit (-1);
+}
+
+static int ifconfig_ioctl(
+ int fd,
+ const char *ifname,
+ int cmd,
+ struct ifreq *ifr)
+{
+ strcpy(ifr->ifr_name, ifname);
+ return ioctl(fd, cmd,ifr);
+}
+
+static unsigned long ip_cnv (const char *str)
+{
+ const char *start_str = str;
+ unsigned tb[4];
+ int no = 0;
+ unsigned long ret;
+
+ memset (tb,-1,sizeof(tb));
+ while (*str != '\0' && no < 4){
+ if (isdigit(*str)){
+ int val = atoi(str);
+ if (val > 255) break;
+ tb[no++] = val;
+ while (isdigit(*str)) str++;
+ if (*str == '.'){
+ str++;
+ }else{
+ break;
+ }
+ }else{
+ break;
+ }
+ }
+
+ ret = (tb[0] << 24) | (tb[1]<<16) | (tb[2] << 8) | tb[3];
+ if (no != 4 || *str != '\0'){
+ fprintf (stderr,"Invalid IP number or netmask: %s\n",start_str);
+ ret = 0xffffffff;
+ }
+ return ret;
+}
+
+
+/*
+ Fetch the IP number of an interface from the kernel.
+ Assume the device is already available in the kernel
+ Return -1 if any error.
+*/
+int ifconfig_print (
+ const char *ifname,
+ const char *addrstr,
+ const char *maskstr,
+ const char *bcaststr)
+{
+ int ret = -1;
+ int skfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (skfd != -1){
+ struct ifreq ifr;
+ struct {
+ unsigned long addr;
+ unsigned long mask;
+ } solved;
+ if (addrstr != NULL && addrstr[0] != '\0'){
+ printf ("ADDR=%s\n",addrstr);
+ solved.addr = ip_cnv (addrstr);
+ }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFADDR, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ unsigned long addr = ntohl(sin->sin_addr.s_addr);
+ printf ("ADDR=%lu.%lu.%lu.%lu\n"
+ ,(addr>>24)&0xff
+ ,(addr>>16)&0xff
+ ,(addr>>8)&0xff
+ ,addr&0xff);
+ solved.addr = addr;
+ ret = 0;
+ }
+ if (maskstr != NULL && maskstr[0] != '\0'){
+ printf ("NETMASK=%s\n",maskstr);
+ solved.mask = ip_cnv (maskstr);
+ }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFNETMASK, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ unsigned long addr = ntohl(sin->sin_addr.s_addr);
+ printf ("NETMASK=%lu.%lu.%lu.%lu\n"
+ ,(addr>>24)&0xff
+ ,(addr>>16)&0xff
+ ,(addr>>8)&0xff
+ ,addr&0xff);
+ solved.mask = addr;
+ ret = 0;
+ }
+ if (bcaststr != NULL && bcaststr[0] != '\0'){
+ printf ("BCAST=%s\n",bcaststr);
+ }else if (ifconfig_ioctl(skfd,ifname,SIOCGIFBRDADDR, &ifr) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr.ifr_addr;
+ unsigned long addr = ntohl(sin->sin_addr.s_addr);
+ printf ("BCAST=%lu.%lu.%lu.%lu\n"
+ ,(addr>>24)&0xff
+ ,(addr>>16)&0xff
+ ,(addr>>8)&0xff
+ ,addr&0xff);
+ ret = 0;
+ }else{
+ // Can't get it from the kernel, compute it from the IP
+ // and the netmask
+ unsigned long addr = (solved.addr & solved.mask)
+ | ~solved.mask;
+ printf ("BCAST=%lu.%lu.%lu.%lu\n"
+ ,(addr>>24)&0xff
+ ,(addr>>16)&0xff
+ ,(addr>>8)&0xff
+ ,addr&0xff);
+
+ }
+ close (skfd);
+ }
+ return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc < 2){
+ usage();
+ }else{
+ const char *addrstr = argc >= 3 ? argv[2] : NULL;
+ const char *maskstr = argc >= 4 ? argv[3] : NULL;
+ const char *bcaststr = argc >= 5 ? argv[4] : NULL;
+ ret = ifconfig_print (argv[1],addrstr,maskstr,bcaststr);
+ }
+ return ret;
+}
+
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on listdevip.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Print the list of all network (IP) devices. Print the IP
+ in fact, including all aliases.
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <net/if.h>
+
+
+static int ifconfig_ioctl(
+ int fd,
+ const char *ifname,
+ int cmd,
+ struct ifreq *ifr)
+{
+ strcpy(ifr->ifr_name, ifname);
+ return ioctl(fd, cmd,ifr);
+}
+
+
+static int devlist_read2_2()
+{
+ int ret = -1;
+ int skfd = socket (AF_INET,SOCK_DGRAM,0);
+ if (skfd < 0) {
+ perror ("socket");
+ }else{
+ struct ifconf ifc;
+ int numreqs = 30;
+ ifc.ifc_buf = NULL;
+ ret = 0;
+ while (1) {
+ ifc.ifc_len = sizeof(struct ifreq) * numreqs;
+ ifc.ifc_buf = (char*)realloc(ifc.ifc_buf, ifc.ifc_len);
+
+ if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0) {
+ perror("SIOCGIFCONF");
+ ret = -1;
+ break;
+ }
+ if (ifc.ifc_len == (int)sizeof(struct ifreq) * numreqs) {
+ /* assume it overflowed and try again */
+ numreqs += 10;
+ continue;
+ }
+ break;
+ }
+ if (ret == 0){
+ struct ifreq *ifr = ifc.ifc_req;
+ int n;
+ for (n = 0; n < ifc.ifc_len; n += sizeof(struct ifreq)) {
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifr->ifr_addr;
+ unsigned long addr = ntohl(sin->sin_addr.s_addr);
+ unsigned long mask = 0xffffff00;
+ struct ifreq ifmask;
+ if (ifconfig_ioctl(skfd,ifr->ifr_name,SIOCGIFNETMASK, &ifmask) >= 0){
+ struct sockaddr_in *sin = (struct sockaddr_in*)&ifmask.ifr_addr;
+ mask = ntohl(sin->sin_addr.s_addr);
+ }
+
+ printf ("%lu.%lu.%lu.%lu/%lu.%lu.%lu.%lu\n"
+ ,(addr>>24)&0xff
+ ,(addr>>16)&0xff
+ ,(addr>>8)&0xff
+ ,addr&0xff
+ ,(mask>>24)&0xff
+ ,(mask>>16)&0xff
+ ,(mask>>8)&0xff
+ ,mask&0xff);
+ ifr++;
+ }
+ }
+ free(ifc.ifc_buf);
+ }
+ return ret;
+}
+
+int main (int argc, char *argv[])
+{
+ devlist_read2_2();
+ return 0;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on parserpmdump.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Litte utility to extract non config file from
+ an rpm --dump command.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <alloca.h>
+
+
+int main (int argc, char *argv[])
+{
+ int *tblen = alloca(argc * sizeof(int));
+ int i;
+ char tmp[1000];
+
+ for (i=1; i<argc; i++) tblen[i] = strlen(argv[i]);
+ while (fgets(tmp,sizeof(tmp)-1,stdin)!=NULL){
+ int i;
+ // Check if the file is in an excluded directory
+ for (i=1; i<argc; i++){
+ if (strncmp(argv[i],tmp,tblen[i])==0) break;
+ }
+ if (i == argc){
+ // Ok no match
+ int last = strlen(tmp)-1;
+ mode_t mode=-1;
+ int type=-1;
+ char *start = tmp;
+ int i;
+
+ if (last >= 0 && tmp[last] == '\n') tmp[last] = '\0';
+
+ for (i=0; i<8; i++){
+ char *pt = start;
+ while (*pt > ' ') pt++;
+ if (*pt == ' ') *pt++ = '\0';
+ if (i == 4){
+ sscanf(start,"%o",&mode);
+ }else if (i==7){
+ type = atoi(start);
+ }
+ start = pt;
+
+ }
+ if (S_ISREG(mode) && type == 0) printf ("%s\n",tmp);
+ }
+ }
+ return 0;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on readlink.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Copyright Jacques Gelinas jack@solucorp.qc.ca
+ Distributed under the Gnu Public License, see the License file
+ in this package.
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc != 2){
+ fprintf (stderr,"readlink symlink-file\n");
+ fprintf (stderr,"Prints the contents of a symlink\n");
+ }else{
+ char buf[PATH_MAX];
+ int len = readlink (argv[1],buf,sizeof(buf)-1);
+ if (len > 0){
+ buf[len] = '\0';
+ printf ("%s\n",buf);
+ ret = 0;
+ }else{
+ fprintf (stderr,"readlink failed for file %s (%s)\n"
+ ,argv[1],strerror(errno));
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on rebootmgr.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ The reboot manager allow a virtual server administrator to request
+ a complete restart of his vserver. This means that all services
+ are terminated, all remaining processes are killed and then
+ all services are started.
+
+ This is done by issuing
+
+ /usr/sbin/vserver vserver restart
+
+
+ The rebootmgr installs a unix domain socket in each vservers
+ and listen for the reboot messages. All other message are discarded.
+
+ The unix domain socket is placed in /vservers/N/dev/reboot and is
+ turned immutable.
+
+ The vreboot utility is used to send the signal from the vserver
+ environment.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <syslog.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <alloca.h>
+
+static void usage()
+{
+ fprintf (stderr,"rebootmgr version %s\n",VERSION);
+ fprintf (stderr,"\n");
+ fprintf (stderr,"rebootmgr [--pidfile file ] vserver-name [ vserver-name ...]\n");
+}
+
+static int rebootmgr_opensocket (const char *vname)
+{
+ int ret = -1;
+ char sockn[PATH_MAX];
+ int fd = socket (AF_UNIX,SOCK_STREAM,0);
+ sprintf (sockn,"/vservers/%s/dev/reboot",vname);
+ unlink (sockn);
+ if (fd == -1){
+ fprintf (stderr,"Can't create a unix domain socket (%s)\n"
+ ,strerror(errno));
+ }else{
+ struct sockaddr_un un;
+ un.sun_family = AF_UNIX;
+ strcpy (un.sun_path,sockn);
+ if (bind(fd,(struct sockaddr*)&un,sizeof(un))==-1){
+ fprintf (stderr,"Can't bind to file %s (%s)\n",sockn
+ ,strerror(errno));
+ }else{
+ int code;
+ chmod (sockn,0600);
+ code = listen (fd,10);
+ if (code == -1){
+ fprintf (stderr,"Can't listen to file %s (%s)\n",sockn
+ ,strerror(errno));
+ }else{
+ ret = fd;
+ }
+ }
+ }
+ return ret;
+}
+
+static int rebootmgr_process (int fd, const char *vname)
+{
+ int ret = -1;
+ char buf[100];
+ int len = read (fd,buf,sizeof(buf)-1);
+ // fprintf (stderr,"process %d %s len %d\n",fd,vname,len);
+ if (len > 0){
+ buf[len] = '\0';
+ if (strcmp(buf,"reboot\n")==0){
+ char cmd[1000];
+ syslog (LOG_NOTICE,"reboot vserver %s\n",vname);
+ snprintf (cmd,sizeof(cmd)-1,"/usr/sbin/vserver %s restart >>/var/log/boot.log 2>&1",vname);
+ system (cmd);
+ ret = 0;
+ }else if (strcmp(buf,"halt\n")==0){
+ char cmd[1000];
+ syslog (LOG_NOTICE,"halt vserver %s\n",vname);
+ snprintf (cmd,sizeof(cmd)-1,"/usr/sbin/vserver %s stop >>/var/log/boot.log 2>&1",vname);
+ system (cmd);
+ ret = 0;
+ }else{
+ syslog (LOG_ERR,"Invalid request from vserver %s",vname);
+ }
+ }
+ return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc < 2){
+ usage();
+ }else{
+ int error = 0;
+ int start = 1;
+ int i;
+ int *sockets = alloca(argc * sizeof(int));
+
+ openlog ("rebootmgr",LOG_PID,LOG_DAEMON);
+ for (i=0; i<argc; i++){
+ const char *arg = argv[i];
+ if (strcmp(arg,"--pidfile")==0){
+ const char *pidfile = argv[i+1];
+ FILE *fout = fopen (pidfile,"w");
+ if (fout == NULL){
+ fprintf (stderr,"Can't open pidfile %s (%s)\n"
+ ,pidfile,strerror(errno));
+
+ __extension__
+ syslog (LOG_ERR,"Can't open pidfile %s (%m)"
+ ,pidfile);
+ }else{
+ fprintf (fout,"%d\n",getpid());
+ fclose (fout);
+ }
+ start = i+2;
+ i++;
+ }else if (strcmp(arg,"--")==0){
+ start = i+1;
+ break;
+ }else if (arg[0] == '-'){
+ fprintf (stderr,"Invalid argument %s\n",arg);
+ syslog (LOG_ERR,"Invalid argument %s",arg);
+ }
+ }
+ for (i=start; i<argc; i++){
+ int fd = rebootmgr_opensocket (argv[i]);
+ if (fd == -1){
+ error = 1;
+ }else{
+ sockets[i] = fd;
+ }
+ }
+ if (!error){
+ int maxhandles = argc*2;
+ struct {
+ int handle;
+ const char *vname;
+ } handles[maxhandles];
+ int nbhandles=0;
+ while (1){
+ int maxfd = 0;
+ int i;
+ int ok;
+
+ fd_set fdin;
+ FD_ZERO (&fdin);
+ for (i=start; i<argc; i++){
+ int fd = sockets[i];
+ if (fd > maxfd) maxfd = fd;
+ FD_SET (fd,&fdin);
+ }
+ for (i=0; i<nbhandles; i++){
+ int fd = handles[i].handle;
+ if (fd > maxfd) maxfd = fd;
+ FD_SET (fd,&fdin);
+ }
+ ok = select (maxfd+1,&fdin,NULL,NULL,NULL);
+ if (ok <= 0){
+ break;
+ }else{
+ int i;
+ int dst = 0;
+
+ for (i=start; i<argc; i++){
+ int fd = sockets[i];
+ if (FD_ISSET(fd,&fdin)){
+ struct sockaddr_un unc;
+ size_t len = sizeof(unc);
+ unc.sun_family = AF_UNIX;
+ fd = accept (fd,(struct sockaddr*)&unc,&len);
+ if (fd != -1){
+ if (nbhandles == maxhandles){
+ int j;
+ // Overloaded, we close every handle
+ syslog (LOG_ERR,"%d sockets opened: Overloaded\n",nbhandles);
+ for (j=0; j<nbhandles; j++){
+ close (handles[j].handle);
+ }
+ nbhandles = 0;
+ }
+ handles[nbhandles].handle = fd;
+ handles[nbhandles].vname = argv[i];
+ nbhandles++;
+ // fprintf (stderr,"accept %d\n",nbhandles);
+ }
+ }
+ }
+ for (i=0; i<nbhandles; i++){
+ int fd = handles[i].handle;
+ if (FD_ISSET(fd,&fdin)){
+ if (rebootmgr_process (fd,handles[i].vname)==-1){
+ close (fd);
+ }else{
+ handles[dst++] = handles[i];
+ }
+ }else{
+ handles[dst++] = handles[i];
+ }
+ }
+ nbhandles = dst;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on reducecap.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "linuxcaps.h"
+#include "vserver.h"
+
+extern int capget (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
+extern int capset (struct __user_cap_header_struct *, struct __user_cap_data_struct *);
+
+static void usage()
+{
+ fprintf (stderr,"reducecap version %s\n",VERSION);
+ fprintf (stderr,"reducecap [ options ] command argument\n");
+ exit (-1);
+}
+
+static void reducecap_print(struct __user_cap_data_struct *user)
+{
+ static const char *tb[]={
+ "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_OPENDEV",
+ NULL
+ };
+ int i;
+ printf ("%22s %9s %9s %9s\n","Capability","Effective","Permitted"
+ ,"Inheritable");
+ for (i=0; tb[i] != NULL; i++){
+ int bit = (1 << i);
+ printf ("%22s %9s %9s %9s\n"
+ ,tb[i]
+ ,(user->effective & bit) ? "X " : " "
+ ,(user->permitted & bit) ? "X " : " "
+ ,(user->inheritable & bit) ? "X " : " ");
+ }
+}
+
+static void reducecap_show()
+{
+ struct __user_cap_header_struct header;
+ struct __user_cap_data_struct user;
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = getpid();
+ if (capget(&header,&user)==-1){
+ perror ("capget");
+ }else{
+ reducecap_print (&user);
+ }
+}
+
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ unsigned long remove = 0;
+ int show = 0;
+ int flags = 0;
+ unsigned long secure = (1<<CAP_LINUX_IMMUTABLE)
+ |(1<<CAP_NET_BROADCAST)
+ |(1<<CAP_NET_ADMIN)
+ |(1<<CAP_NET_RAW)
+ |(1<<CAP_IPC_LOCK)
+ |(1<<CAP_IPC_OWNER)
+ |(1<<CAP_SYS_MODULE)
+ |(1<<CAP_SYS_RAWIO)
+ |(1<<CAP_SYS_PACCT)
+ |(1<<CAP_SYS_ADMIN)
+ |(1<<CAP_SYS_BOOT)
+ |(1<<CAP_SYS_NICE)
+ |(1<<CAP_SYS_RESOURCE)
+ |(1<<CAP_SYS_TIME)
+ |(1<<CAP_MKNOD);
+ int i;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ const char *opt = argv[i+1];
+ if (strcmp(arg,"--secure")==0){
+ remove = secure;
+ }else if (strcmp(arg,"--show")==0){
+ show = 1;
+ }else if (strcmp(arg,"--flag")==0){
+ if (strcmp(opt,"lock")==0){
+ flags |= 1;
+ }else if (strcmp(opt,"sched")==0){
+ flags |= 2;
+ }else if (strcmp(opt,"nproc")==0){
+ flags |= 4;
+ }else if (strcmp(opt,"private")==0){
+ flags |= 8;
+ }else if (strcmp(opt,"hideinfo")==0){
+ flags |= 32;
+ }else{
+ fprintf (stderr,"Unknown flag %s\n",opt);
+ }
+ i++;
+ }else if (arg[0] == '-' && arg[1] == '-'){
+ static struct {
+ const char *option;
+ int bit;
+ }tbcap[]={
+ // The following capabilities are normally available
+ // to vservers administrator, but are place for
+ // completeness
+ {"CAP_CHOWN",CAP_CHOWN},
+ {"CAP_DAC_OVERRIDE",CAP_DAC_OVERRIDE},
+ {"CAP_DAC_READ_SEARCH",CAP_DAC_READ_SEARCH},
+ {"CAP_FOWNER",CAP_FOWNER},
+ {"CAP_FSETID",CAP_FSETID},
+ {"CAP_KILL",CAP_KILL},
+ {"CAP_SETGID",CAP_SETGID},
+ {"CAP_SETUID",CAP_SETUID},
+ {"CAP_SETPCAP",CAP_SETPCAP},
+ {"CAP_SYS_TTY_CONFIG",CAP_SYS_TTY_CONFIG},
+ {"CAP_LEASE",CAP_LEASE},
+ {"CAP_SYS_CHROOT",CAP_SYS_CHROOT},
+
+ // Those capabilities are not normally available
+ // to vservers because they are not needed and
+ // may represent a security risk
+ {"--LINUX_IMMUTABLE",CAP_LINUX_IMMUTABLE},
+ {"--NET_BIND_SERVICE",CAP_NET_BIND_SERVICE},
+ {"--NET_BROADCAST",CAP_NET_BROADCAST},
+ {"--NET_ADMIN", CAP_NET_ADMIN},
+ {"--NET_RAW", CAP_NET_RAW},
+ {"--IPC_LOCK", CAP_IPC_LOCK},
+ {"--IPC_OWNER", CAP_IPC_OWNER},
+ {"--SYS_MODULE",CAP_SYS_MODULE},
+ {"--SYS_RAWIO", CAP_SYS_RAWIO},
+ {"--SYS_PACCT", CAP_SYS_PACCT},
+ {"--SYS_ADMIN", CAP_SYS_ADMIN},
+ {"--SYS_BOOT", CAP_SYS_BOOT},
+ {"--SYS_NICE", CAP_SYS_NICE},
+ {"--SYS_RESOURCE",CAP_SYS_RESOURCE},
+ {"--SYS_TIME", CAP_SYS_TIME},
+ {"--MKNOD", CAP_MKNOD},
+ {NULL,0}
+ };
+ int j;
+ for (j=0; tbcap[j].option != NULL; j++){
+ if (strcasecmp(tbcap[j].option,arg)==0){
+ remove |= (1<<tbcap[j].bit);
+ break;
+ }
+ }
+ if (tbcap[j].option != NULL){
+ usage();
+ }
+ }else{
+ break;
+ }
+ }
+ if (i == argc){
+ if (show){
+ reducecap_show();
+ }else{
+ usage();
+ }
+ }else if (argv[i][0] == '-'){
+ usage();
+ }else{
+ struct __user_cap_header_struct header;
+ struct __user_cap_data_struct user;
+ header.version = _LINUX_CAPABILITY_VERSION;
+ header.pid = 0;
+ if (capget(&header,&user)==-1){
+ perror ("capget");
+ }else{
+ if (show){
+ reducecap_print (&user);
+ }
+ if (call_new_s_context(0,NULL,remove,flags)==-1){
+ perror ("new_s_context -2");
+ }else{
+ fprintf (stderr,"Executing\n");
+ execvp (argv[i],argv+i);
+ fprintf (stderr,"Can't execute command %s\n",argv[i]);
+ }
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on setctxlimit.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Set the global per context limit of a resource (memory, file handle).
+ This utility can do it either for the current context or a selected
+ one.
+
+ It uses the same options as ulimit, when possible
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+
+#include "vserver.h"
+
+static void set_ctxlim (int res, long lim, const char *msg)
+{
+ if (call_set_ctxlimit(res,lim)==-1){
+ fprintf (stderr,"Error setting limit \"%s\": %s\n"
+ ,msg,strerror(errno));
+ exit (-1);
+ }
+}
+
+static void usage()
+{
+ fprintf (stderr,"setctxlimit version %s\n",VERSION);
+ fprintf (stderr
+ ,"setctxlimit [ --ctx context ] limits\n"
+ "\n"
+ "-n nax opened files\n");
+}
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc < 2){
+ usage();
+ }else{
+ int i;
+ ret = 0;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ const char *narg = argv[i+1];
+ int val;
+
+ if (narg == NULL) narg = "";
+ val = atoi(narg);
+ if (strcmp(arg,"--help")==0){
+ usage();
+ }else if (strcmp(arg,"--ctx")==0){
+ int tb[1];
+
+ tb[0] = val;
+ if (call_new_s_context (1,tb,0,0)==-1){
+ fprintf (stderr,"Can't select context %d (%s)\n"
+ ,val,strerror(errno));
+ exit (-1);
+ }
+ }else if (strcmp (arg,"-n")==0){
+ set_ctxlim (RLIMIT_NOFILE,val,"Number of opened files");
+ }
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on showattr.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/ext2_fs.h>
+
+// Patch to help compile this utility on unpatched kernel source
+#ifndef EXT2_IMMUTABLE_FILE_FL
+ #define EXT2_IMMUTABLE_FILE_FL 0x00000010
+ #define EXT2_IMMUTABLE_LINK_FL 0x00008000
+#endif
+
+/*
+ Get the extended attributes of a file
+*/
+static int getext2flags (const char *fname, long *flags)
+{
+ int ret = -1;
+ int fd = open (fname,O_RDONLY);
+ if (fd == -1){
+ fprintf (stderr,"Can't open file %s (%s)\n",fname,strerror(errno));
+ }else{
+ *flags = 0;
+ ret = ioctl (fd,EXT2_IOC_GETFLAGS,flags);
+ close (fd);
+ if (ret == -1){
+ fprintf (stderr,"Can't get ext2 flags on file %s (%s)\n"
+ ,fname,strerror(errno));
+ }
+ }
+ return ret;
+}
+
+/*
+ Set the extended attributes of a file
+*/
+static int setext2flags (const char *fname, long flags)
+{
+ int ret = -1;
+ int fd = open (fname,O_RDONLY);
+ if (fd == -1){
+ fprintf (stderr,"Can't open file %s (%s)\n",fname,strerror(errno));
+ }else{
+ ret = ioctl (fd,EXT2_IOC_SETFLAGS,&flags);
+ close (fd);
+ if (ret == -1){
+ fprintf (stderr,"Can't set ext2 flags on file %s (%s)\n"
+ ,fname,strerror(errno));
+ }
+ }
+ return ret;
+}
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc <= 1){
+ fprintf (stderr
+ ,"showattr file ...\n"
+ "\n"
+ "Presents extended file attribute.\n"
+ "\n"
+ "setattr --immutable --immulink file ...\n"
+ "\n"
+ "Sets the extended file attributes.\n"
+ "\n"
+ "These utilities exist as an interim until lsattr and\n"
+ "chattr are updated.\n"
+ );
+ }else if (strstr(argv[0],"showattr")!=NULL){
+ int i;
+ for (i=1; i<argc; i++){
+ long flags;
+ ret = getext2flags (argv[i],&flags);
+ if (ret == -1){
+ break;
+ }else{
+ printf ("%s\t%08lx\n",argv[i],flags);
+ }
+ }
+ }else if (strstr(argv[0],"setattr")!=NULL){
+ long flags = 0;
+ int i;
+ ret = 0;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ if (strncmp(arg,"--",2)==0){
+ if (strcmp(arg,"--immutable")==0){
+ flags |= EXT2_IMMUTABLE_FILE_FL;
+ }else if (strcmp(arg,"--immulink")==0){
+ flags |= EXT2_IMMUTABLE_LINK_FL;
+ }else{
+ fprintf (stderr,"Invalid option %s\n",arg);
+ ret = -1;
+ break;
+ }
+ }else{
+ ret = setext2flags (arg,flags);
+ if (ret == -1){
+ break;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on showperm.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc < 2){
+ fprintf (stderr,"showperm version %s\n",VERSION);
+ fprintf (stderr,
+ "showperm file or directory ...\n"
+ "prints permission bits for files\n"
+ "A very stripped down stat utility\n"
+ );
+ }else{
+ int i;
+ ret = 0;
+ for (i=1; i<argc; i++){
+ struct stat st;
+ if (lstat(argv[i],&st)==-1){
+ fprintf (stderr,"can't lstat %s (%s)\n",argv[i]
+ ,strerror(errno));
+ ret = -1;
+ }else{
+ printf ("%03o\n",(st.st_mode & 0777));
+ }
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vbuild.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This utility is used to build a new vserver using a reference vserver.
+ It uses hard link whenever possible instead of duplicating files.
+ Once done, it sets the immutable bits.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <set>
+#include "vutil.h"
+
+using namespace std;
+
+struct EXCLDIR{
+ string prefix;
+ int len;
+ EXCLDIR(const char *s)
+ {
+ prefix = s;
+ prefix += '/';
+ len = prefix.size();
+ }
+};
+static vector<EXCLDIR> excldirs;
+
+
+static int ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL;
+static struct {
+ int nblink;
+ int nbcopy;
+ long size_copy;
+ int nbdir;
+ int nbsymlink;
+ int nbspc;
+} stats;
+
+
+static void usage()
+{
+ cerr <<
+ "vbuild version " << VERSION <<
+ "\n\n"
+ "vbuild [ options ] reference-server new-vservers\n"
+ "\n"
+ "--test: Show what will be done, do not do it.\n"
+ "--debug: Prints some debugging messages.\n"
+ "\n"
+ "--excldir: None of the files under a given directory will be copied\n"
+ "\tThe directory is expressed in absolute/logical form (relative\n"
+ "\tto the vserver root (ex: /var/log)\n"
+ "\n"
+ "\n"
+ "--noflags: Do not put any immutable flags on the file\n"
+ "--immutable: Set the immutable_file bit on the files.\n"
+ "--immutable-mayunlink: Sets the immutable_link flag on files.\n"
+ "--stats: Produce statistics on the number of file linked\n"
+ " copied and so on.\n"
+ "\n"
+ "By default, the immutable_file and immutable_link flags are\n"
+ "set on the files. So if you want no immutable flags, you must\n"
+ "use --noflags. If you want a single flag, you must use\n"
+ "--noflags first, then the --immutable or --immutable-mayunlink\n"
+ "flag.\n"
+ ;
+}
+
+/*
+ Return true if a directory lies inside a directory set
+*/
+static bool vbuild_inside (vector<EXCLDIR> &dirs, const char *path)
+{
+ bool found = false;
+ for (unsigned i=0; i<dirs.size(); i++){
+ if (strncmp(dirs[i].prefix.c_str(),path,dirs[i].len)==0){
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
+
+
+static int vbuild_copy (
+ string refserv,
+ string newserv,
+ dev_t dev, // We stay on the same volume
+ string logical_dir,
+ set<string> &files)
+{
+ int ret = -1;
+ if (debug > 0) printf ("Copying directory %s\n",logical_dir.c_str());
+ DIR *dir = opendir (refserv.c_str());
+ if (dir == NULL){
+ fprintf (stderr,"Can't open directory %s (%s)\n",refserv.c_str()
+ ,strerror(errno));
+ }else{
+ logical_dir += "/";
+ bool copy_files = !vbuild_inside(excldirs,logical_dir.c_str());
+ struct dirent *ent;
+ ret = 0;
+ while (ret == 0 && (ent=readdir(dir))!=NULL){
+ if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0){
+ continue;
+ }
+ string file = refserv + "/" + ent->d_name;
+ struct stat st;
+ if (vutil_lstat(file.c_str(),st) == -1){
+ ret = -1;
+ }else if (st.st_dev != dev){
+ if (debug > 0) printf ("Ignore sub-directory %s\n",file.c_str());
+ }else{
+ string newfile = newserv + "/" + ent->d_name;
+ if (S_ISDIR(st.st_mode)){
+ if (vbuild_mkdir (newfile.c_str(),st.st_mode)==-1){
+ fprintf (stderr,"Can't mkdir %s (%s)\n"
+ ,newfile.c_str(),strerror(errno));
+ ret = -1;
+ }else{
+ stats.nbdir++;
+ if (vbuild_chown(newfile.c_str(),st.st_uid,st.st_gid)==-1){
+ fprintf (stderr,"Can't chown %s (%s)\n"
+ ,newfile.c_str(),strerror(errno));
+ ret = -1;
+ }
+ ret |= vbuild_copy (file,newfile,dev
+ ,logical_dir + ent->d_name,files);
+ }
+ }else if (S_ISLNK(st.st_mode)){
+ char path[PATH_MAX];
+ int len = readlink(file.c_str(),path,sizeof(path)-1);
+ if (len < 0){
+ fprintf (stderr,"Can't readlink %s (%s)\n"
+ ,file.c_str(),strerror(errno));
+ ret = -1;
+ }else{
+ path[len] = '\0';
+ stats.nbsymlink++;
+ if (vbuild_symlink (path,newfile.c_str())==-1){
+ fprintf (stderr,"Can't symlink %s to %s (%s)\n",
+ newfile.c_str(),path,strerror(errno));
+ }
+ }
+ }else if (S_ISBLK(st.st_mode)
+ || S_ISCHR(st.st_mode)
+ || S_ISFIFO(st.st_mode)){
+ stats.nbspc++;
+ if (vbuild_mknod (newfile.c_str(),st.st_mode,st.st_rdev)==-1){
+ fprintf (stderr,"Can't mknod %s (%s)\n"
+ ,newfile.c_str(),strerror(errno));
+ ret = -1;
+ }
+ }else if (S_ISSOCK(st.st_mode)){
+ // Do nothing
+ }else if (copy_files){
+ // Ok, this is a file. We either copy it or do a link
+ string logical_file = logical_dir + ent->d_name;
+ if (files.find (logical_file)==files.end()){
+ if (debug > 1) printf ("Copying file %s\n",file.c_str());
+ if (vbuild_file_copy (file.c_str(),newfile.c_str(),st)==-1){
+ fprintf (stderr,"Can't copy %s to %s (%s)\n",
+ file.c_str(),newfile.c_str(),strerror(errno));
+ ret = -1;
+ }else{
+ stats.size_copy += st.st_size;
+ stats.nbcopy++;
+ }
+ }else{
+ if (debug > 2) printf ("Linking file %s\n",file.c_str());
+ setext2flag (file.c_str(),false,ext2flags);
+ stats.nblink++;
+ if (vbuild_link (file.c_str(),newfile.c_str())==-1){
+ fprintf (stderr,"Can't link %s to %s (%s)\n",
+ file.c_str(),newfile.c_str(),strerror(errno));
+ ret = -1;
+ }
+ setext2flag (file.c_str(),true,ext2flags);
+ }
+ }
+ }
+ }
+ closedir(dir);
+ }
+ return ret;
+}
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ bool statistics = false;
+ int i;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ //const char *opt = argv[i+1];
+ if (strcmp(arg,"--test")==0){
+ testmode = true;
+ }else if (strcmp(arg,"--debug")==0){
+ debug++;
+ }else if (strcmp(arg,"--stats")==0){
+ statistics = true;
+ }else if (strcmp(arg,"--noflags")==0){
+ ext2flags = 0;
+ }else if (strcmp(arg,"--immutable")==0){
+ ext2flags |= EXT2_IMMUTABLE_FILE_FL;
+ }else if (strcmp(arg,"--immutable-mayunlink")==0){
+ ext2flags |= EXT2_IMMUTABLE_LINK_FL;
+ }else if (strcmp(arg,"--excldir")==0){
+ i++;
+ excldirs.push_back (EXCLDIR(argv[i]));
+ }else{
+ break;
+ }
+ }
+ if (i!=argc-2){
+ usage();
+ }else{
+ string refserv = argv[i++];
+ string newserv = argv[i];
+ list<PACKAGE> packages;
+ // Load the files which are not configuration files from
+ // the packages
+ vutil_loadallpkg (refserv,packages);
+ set<string> files;
+ for (list<PACKAGE>::iterator it=packages.begin(); it!=packages.end(); it++){
+ (*it).loadfiles(refserv,files);
+ }
+ // Now, we do a recursive copy of refserv into newserv
+ umask (0);
+ mkdir (newserv.c_str(),0755);
+ // Check if it is on the same volume
+ struct stat refst,newst;
+ if (vutil_lstat(refserv,refst)!=-1
+ && vutil_lstat(newserv,newst)!=1){
+ if (refst.st_dev != newst.st_dev){
+ fprintf (stderr,"Can't vbuild %s because it is not on the same volume as %s\n"
+ ,newserv.c_str(),refserv.c_str());
+ }else{
+ stats.nbdir = stats.nblink = stats.nbcopy = stats.nbsymlink = 0;
+ stats.nbspc = 0;
+ stats.size_copy = 0;
+ ret = vbuild_copy (refserv,newserv,refst.st_dev,"",files);
+ if (statistics){
+ printf ("Directory created: %d\n",stats.nbdir);
+ printf ("Files copied : %d\n",stats.nbcopy);
+ printf ("Bytes copied : %ld\n",stats.size_copy);
+ printf ("Files linked : %d\n",stats.nblink);
+ printf ("Files symlinked : %d\n",stats.nbsymlink);
+ printf ("Special files : %d\n",stats.nbspc);
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vcheck.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This utility is used to compare two vservers. One is known to
+ be clean and the other is potentially corrupted (cracked). The
+ goal of this program is to run the rpm verify command, but using
+ the RPM database of the first vserver.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <set>
+#include "vutil.h"
+
+using namespace std;
+
+
+static void usage()
+{
+ cerr <<
+ "vcheck version " << VERSION <<
+ "\n\n"
+ "vcheck [ options ] reference-server chk-vservers\n"
+ "\n"
+ "--diffpkgs: Shows which package differ.\n"
+ " + means the package only exists in chk-server.\n"
+ " - means the package does not exist in chk-server.\n"
+ " ! means the servers have different version.\n"
+ "\n"
+ "--verify: Execute an RPM verify on common packages.\n"
+ "--debug: Turn on some (useless) debugging messages.\n"
+ ;
+}
+
+typedef list<PACKAGE> PACKAGES;
+
+/*
+ Delete a directory silently
+*/
+static int vcheck_deldir (const string &path)
+{
+ int ret = -1;
+ struct stat st;
+ if (lstat(path.c_str(),&st)==-1){
+ ret = 0;
+ }else{
+ if (!S_ISDIR(st.st_mode)){
+ fprintf (stderr,"%s already exist and is not a directory\n"
+ ,path.c_str());
+ exit (-1);
+ }else{
+ DIR *d = opendir (path.c_str());
+ if (d != NULL){
+ struct dirent *ent;
+ ret = 0;
+ while ((ent=readdir(d))!=NULL){
+ if (strcmp(ent->d_name,".")!=0
+ && strcmp(ent->d_name,"..")!=0){
+ string tmp = path + "/" + ent->d_name;
+ if (unlink(tmp.c_str())==-1){
+ fprintf (stderr,"Can't delete file %s (%s)\n",tmp.c_str()
+ ,strerror(errno));
+ ret = -1;
+ break;
+ }
+ }
+ }
+ closedir (d);
+ rmdir (path.c_str());
+ }
+ }
+ }
+ return ret;
+}
+
+
+static int vcheck_copydb (const string &refserv, const string &path)
+{
+ int ret = -1;
+ string refpath = refserv + "/var/lib/rpm";
+ DIR *d = opendir (refpath.c_str());
+ if (d == NULL){
+ fprintf (stderr,"Can't open directory %s (%s)\n",refpath.c_str()
+ ,strerror(errno));
+ }else{
+ ret = 0;
+ struct dirent *ent;
+ while ((ent=readdir(d))!=NULL){
+ if (strcmp(ent->d_name,".")!=0
+ && strcmp(ent->d_name,"..")!=0){
+ string srcpath = refpath + "/" + ent->d_name;
+ const char *spath = srcpath.c_str();
+ struct stat st;
+ if (stat(spath,&st)!=-1){
+ string dstpath = path + "/" + ent->d_name;
+ if (file_copy (spath,dstpath.c_str(),st) == -1){
+ ret = -1;
+ break;
+ }
+ }else{
+ ret = -1;
+ fprintf (stderr,"Can't stat %s (%s)\n",spath,strerror(errno));
+ break;
+ }
+ }
+ }
+ closedir (d);
+ }
+ return ret;
+}
+
+class cmp_name{
+public:
+ int operator()(const PACKAGE &p1, const PACKAGE &p2){
+ return strcmp(p1.name.c_str(),p2.name.c_str());
+ }
+};
+
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ bool diffpkg = false;
+ bool verify = false;
+ int i;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ //const char *opt = argv[i+1];
+ if (strcmp(arg,"--diffpkg")==0){
+ diffpkg = true;
+ }else if (strcmp(arg,"--verify")==0){
+ verify = true;
+ }else if (strcmp(arg,"--debug")==0){
+ debug++;
+ }else{
+ break;
+ }
+ }
+ if (i!=argc-2){
+ usage();
+ }else{
+ string refserv = argv[i++];
+ string chkserv = argv[i];
+ PACKAGES refpkgs,chkpkgs;
+ // Load the package list from both vservers
+ vutil_loadallpkg (refserv,refpkgs);
+ vutil_loadallpkg (chkserv,chkpkgs);
+ PACKAGES common, differ, added, removed;
+ // Find which package are different, missing and added
+ // to chkserv
+ for (PACKAGES::iterator it=refpkgs.begin(); it!=refpkgs.end(); it++){
+ PACKAGES::iterator f = find_if(chkpkgs.begin(),chkpkgs.end(),same_name(*it));
+ if (f == chkpkgs.end()){
+ removed.push_back (*it);
+ }else if (f->version != it->version){
+ differ.push_back (*it);
+ }else{
+ common.push_back (*it);
+ }
+ }
+ for (list<PACKAGE>::iterator it=chkpkgs.begin(); it!=chkpkgs.end(); it++){
+ list<PACKAGE>::iterator f = find_if(refpkgs.begin(),refpkgs.end(),same_name(*it));
+ if (f == refpkgs.end()){
+ added.push_back (*it);
+ }
+ }
+ differ.sort ();
+ added.sort();
+ removed.sort();
+ common.sort ();
+ bool something = false;
+ if (diffpkg){
+ for (PACKAGES::iterator it=removed.begin(); it!=removed.end(); it++){
+ printf ("- %s\n",it->name.c_str());
+ }
+ for (PACKAGES::iterator it=added.begin(); it!=added.end(); it++){
+ printf ("+ %s\n",it->name.c_str());
+ }
+ for (PACKAGES::iterator it=differ.begin(); it!=differ.end(); it++){
+ printf ("! %s\n",it->name.c_str());
+ }
+ something = true;
+ }
+ if (verify){
+ // We copy the rpm database from the reference vserver to
+ // the target vserver
+ string dbpath = chkserv + "/tmp/vcheck.db";
+ vcheck_deldir (dbpath);
+ if (mkdir (dbpath.c_str(),0)==-1){
+ fprintf (stderr,"Can't create directory %s (%s)\n"
+ ,dbpath.c_str(),strerror(errno));
+ }else if (vcheck_copydb (refserv,dbpath) != -1){
+ // We only compare the common package
+ string cmd = "rpm --dbpath /tmp/vcheck.db --root " + chkserv + " -V";
+ for (PACKAGES::iterator it=common.begin(); it!=common.end(); it++){
+ //printf ("compare %s\n",it->name.c_str());
+ cmd += " " + it->name;
+ }
+ if (debug) printf ("CMD: %s\n",cmd.c_str());
+ system (cmd.c_str());
+ }
+ vcheck_deldir (dbpath);
+ something = true;
+ }
+ if (!something){
+ fprintf (stderr,"Nothing to do !!!\n\n");
+ usage();
+ }
+ }
+ return ret;
+}
+
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vdu.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+
+__extension__ typedef long long longlong;
+
+static int vdu_onedir (char const *path, longlong *size)
+{
+ int ret = -1;
+ int dirfd = open (path,O_RDONLY); // A handle to speed up
+ // chdir
+ if (dirfd == -1){
+ fprintf (stderr,"Can't open directory %s (%s)\n",path
+ ,strerror(errno));
+ }else{
+ DIR *dir;
+
+ fchdir (dirfd);
+ dir = opendir (".");
+ if (dir == NULL){
+ fprintf (stderr,"Can't open (opendir) directory %s (%s)\n",path
+ ,strerror(errno));
+ }else{
+ struct stat dirst;
+ struct dirent *ent;
+ longlong dirsize = 0;
+
+ ret = 0;
+ lstat (".",&dirst);
+ while ((ent=readdir(dir))!=NULL){
+ struct stat st;
+ if (lstat(ent->d_name,&st)==-1){
+ fprintf (stderr,"Can't stat %s/%s (%s)\n",path
+ ,ent->d_name,strerror(errno));
+ ret = -1;
+ break;
+ }else if (S_ISREG(st.st_mode)){
+ if (st.st_nlink == 1){
+ dirsize += st.st_size;
+ }
+ }else if (S_ISDIR(st.st_mode) && st.st_dev == dirst.st_dev){
+ if (strcmp(ent->d_name,".")!=0
+ && strcmp(ent->d_name,"..")!=0){
+ char *tmp = malloc(strlen(path) + strlen(ent->d_name) + 2);
+ if (tmp==0) ret=-1;
+ else {
+ strcpy(tmp, path);
+ strcat(tmp, "/");
+ strcat(tmp, ent->d_name);
+ ret = vdu_onedir(tmp,&dirsize);
+ free(tmp);
+ fchdir (dirfd);
+ }
+ }
+ }
+ }
+ closedir (dir);
+ *size += dirsize;
+ }
+ close (dirfd);
+ }
+ return ret;
+}
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc < 2){
+ fprintf (stderr,"vdu version %s\n",VERSION);
+ fprintf (stderr,"vdu directory ...\n\n");
+ fprintf (stderr
+ ,"Compute the size of a directory tree, ignoring files\n"
+ "with more than one link.\n");
+ }else{
+ int i;
+
+ ret = 0;
+ for (i=1; i<argc && ret != -1; i++){
+ longlong size = 0;
+ long ksize;
+
+ ret = vdu_onedir (argv[i],&size);
+ ksize = size >> 10;
+ printf ("%s\t%ldK\n",argv[i],ksize);
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vfiles.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This utility is used to extract the list of non unified files in
+ a vserver.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+#include <dirent.h>
+
+#include <string>
+#include <list>
+#include <set>
+#include "vutil.h"
+
+using namespace std;
+
+static bool ignorelink = false;
+
+
+static void usage()
+{
+ cerr <<
+ "vfiles version " << VERSION <<
+ "\n\n"
+ "vfiles [ options ] reference-server vserver\n"
+ "\n"
+ "--debug: Prints some debugging messages.\n"
+ "--ignorelink: Do not print symbolic links (they are never unified)\n"
+ "\n"
+ ;
+}
+
+
+static int vfiles_walk (
+ string absdir,
+ dev_t dev, // We stay on the same volume
+ string logical_dir,
+ set<string> &files)
+{
+ int ret = -1;
+ if (debug > 0) printf ("Entering directory %s\n",logical_dir.c_str());
+ DIR *dir = opendir (absdir.c_str());
+ if (dir == NULL){
+ fprintf (stderr,"Can't open directory %s (%s)\n",absdir.c_str()
+ ,strerror(errno));
+ }else{
+ struct dirent *ent;
+ ret = 0;
+ while (ret == 0 && (ent=readdir(dir))!=NULL){
+ if (strcmp(ent->d_name,".")==0 || strcmp(ent->d_name,"..")==0){
+ continue;
+ }
+ string file = absdir + "/" + ent->d_name;
+ struct stat st;
+ if (vutil_lstat(file,st) == -1){
+ ret = -1;
+ }else if (st.st_dev != dev){
+ if (debug > 0) printf ("Ignore sub-directory %s\n",file.c_str());
+ }else{
+ if (S_ISDIR(st.st_mode)){
+ ret |= vfiles_walk (file,dev
+ ,logical_dir + "/" + ent->d_name,files);
+ }else if (S_ISLNK(st.st_mode)){
+ if (!ignorelink) printf ("%s\n",file.c_str());
+ }else if (S_ISBLK(st.st_mode)
+ || S_ISCHR(st.st_mode)
+ || S_ISFIFO(st.st_mode)){
+ printf ("%s\n",file.c_str());
+ }else if (S_ISSOCK(st.st_mode)){
+ // Do nothing
+ }else{
+ // Ok, this is a file. We either copy it or do a link
+ string logical_file = logical_dir + "/" + ent->d_name;
+ if (files.find (logical_file)==files.end()){
+ printf ("%s\n",file.c_str());
+ }
+ }
+ }
+ }
+ closedir(dir);
+ }
+ return ret;
+}
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ int i;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ //const char *opt = argv[i+1];
+ if (strcmp(arg,"--debug")==0){
+ debug++;
+ }else if (strcmp(arg,"--ignorelink")==0){
+ ignorelink=true;
+ }else{
+ break;
+ }
+ }
+ if (i!=argc-2){
+ usage();
+ }else{
+ string refserv = argv[i++];
+ string newserv = argv[i];
+ list<PACKAGE> packages;
+ // Load the files which are not configuration files from
+ // the packages
+ vutil_loadallpkg (refserv,packages);
+ set<string> files;
+ for (list<PACKAGE>::iterator it=packages.begin(); it!=packages.end(); it++){
+ (*it).loadfiles(refserv,files);
+ }
+ struct stat st;
+ if (vutil_lstat(newserv,st)!=-1){
+ // Now, we do a recursive walk of newserv and prints
+ // all files not unifiable
+ ret = vfiles_walk (newserv,st.st_dev,"",files);
+ }
+ }
+ return ret;
+}
+
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vreboot.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Used to send a reboot message to the reboot manager. It opens /dev/reboot
+ and write "reboot\n".
+*/
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdbool.h>
+
+/*
+ Connect to a unix domain socket
+*/
+static int vreboot_connect (const char *sockpath, bool showerror)
+{
+ int ret = -1;
+ int fd = socket (AF_UNIX,SOCK_STREAM,0);
+ if (fd == -1){
+ if (showerror) perror("socket client");
+ }else{
+ struct sockaddr_un un;
+ int s;
+
+ un.sun_family = AF_UNIX;
+ strcpy (un.sun_path,sockpath);
+ s = connect(fd,(struct sockaddr*)&un,sizeof(un));
+ if (s == -1){
+ if (showerror) fprintf (stderr,"connect %s (%s)\n"
+ ,sockpath,strerror(errno));
+ }else{
+ ret = fd;
+ }
+ }
+ return ret;
+}
+
+static void usage()
+{
+ fprintf (stderr,"vreboot version %s\n",VERSION);
+ fprintf (stderr,"\n");
+ fprintf (stderr,"vreboot [ --socket path ]\n");
+ fprintf (stderr,"vhalt [ --socket path ]\n");
+ fprintf (stderr,"vreboot request a reboot or a halt of a virtual server\n");
+}
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ int i;
+ const char *sockpath = "/dev/reboot";
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ const char *opt = argv[i+1];
+ if (strcmp(arg,"--socket")==0){
+ sockpath = opt;
+ i++;
+ }else if (strcmp(arg,"--help")==0){
+ break;
+
+ }else{
+ fprintf (stderr,"Invalid option %s\n",arg);
+ break;
+ }
+ }
+ if (argc != i){
+ usage();
+ }else{
+ int fd = vreboot_connect (sockpath,true);
+ if (fd != -1){
+ if (strstr(argv[0],"halt")!=NULL){
+ write (fd,"halt\n",5);
+ }else{
+ write (fd,"reboot\n",7);
+ }
+ close (fd);
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vserver-stat.cc by Guillaum Dallaire and Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ vserver-stat help you to see all the active context currently in the kernel
+ with some useful stat
+
+ Changelog:
+
+ 2003-01-08 Jacques Gelinas: Shows vserver description
+ 2002-02-28 Jacques Gelinas: Use dynamic system call
+ 2002-06-05 Martial Rioux : fix memory output error
+ 2002-12-05 Martial Rioux : fix output glitch
+ 2001-11-29 added uptime/ctx stat
+ 2001-11-20 added vmsize, rss, stime and utime stat
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
+#include <errno.h>
+#include <syscall.h>
+#include <time.h>
+
+#define PROC_DIR_NAME "/proc"
+#define CTX_DIR_NAME "/var/run/vservers/"
+#define CTX_NAME_MAX_LEN 50
+
+int call_new_s_context(int nbctx, int ctxs[], int remove_cap, int flags);
+
+
+struct ctx_list
+{
+ int ctx;
+ int process_count;
+ int VmSize_total;
+ int VmRSS_total;
+ long start_time_oldest;
+ long stime_total, utime_total;
+ char name[CTX_NAME_MAX_LEN];
+ struct ctx_list *next;
+} *my_ctx_list;
+
+struct process_info
+{
+ long VmSize; // number of pages of virtual memory
+ long VmRSS; // resident set size from /proc/#/stat
+ long start_time; // start time of process -- seconds since 1-1-70
+ long stime, utime; // kernel & user-mode CPU time accumulated by process
+ long cstime, cutime; // cumulative time of process and reaped children
+ int s_context;
+};
+
+char *process_name;
+
+void usage()
+{
+ fprintf(stderr, "%s: from vserver kit version %s\n", process_name, VERSION);
+ fprintf(stderr, "(no argument needed)\n\n");
+ fprintf(stderr, "Show informations about all the active context.\n\n");
+ fprintf(stderr, " CTX# Context number\n");
+ fprintf(stderr, " #0 = root context\n");
+ fprintf(stderr, " #1 = monitoring context\n");
+ fprintf(stderr, " PROC QTY Quantity of processes in each context\n");
+ fprintf(stderr, " VSZ Number of pages of virtual memory\n");
+ fprintf(stderr, " RSS Resident set size\n");
+ fprintf(stderr, " userTIME User-mode CPU time accumulated\n");
+ fprintf(stderr, " sysTIME Kernel-mode CPU time accumulated\n");
+ fprintf(stderr, " UPTIME Uptime/context\n");
+ fprintf(stderr, " NAME Virtual server name\n");
+ fprintf(stderr, "\n");
+
+}
+
+// return uptime (in ms) from /proc/uptime
+long get_uptime()
+{
+ int fd;
+ double up;
+ char buffer[64];
+
+ // open the /proc/uptime file
+ if ((fd = open("/proc/uptime", O_RDONLY, 0)) == -1)
+ return 0;
+
+ if (read(fd, buffer, sizeof(buffer)) < 1)
+ return 0;
+
+ close(fd);
+
+ if (sscanf(buffer, "%lf", &up) < 1)
+ {
+ fprintf(stderr, "%s: bad data in /proc/uptime\n", process_name);
+ return 0;
+ }
+
+ return up * 100;
+}
+
+// insert a new record to the list
+struct ctx_list *insert_ctx(int ctx, struct ctx_list *next)
+{
+ struct ctx_list *new;
+
+ new = (struct ctx_list *)malloc(sizeof(struct ctx_list));
+ new->ctx = ctx;
+ new->process_count = 0;
+ new->VmSize_total = 0;
+ new->VmRSS_total = 0;
+ new->utime_total = 0;
+ new->stime_total = 0;
+ new->start_time_oldest = 0;
+ new->next = next;
+ new->name[0] = '\0';
+
+ return new;
+}
+
+// find the ctx record with the ctx number
+struct ctx_list *find_ctx(struct ctx_list *list, int ctx)
+{
+ // very simple search engine...
+ while(list != NULL)
+ {
+ // find
+ if (list->ctx == ctx)
+ {
+ return list;
+ }
+ list = list->next;
+ }
+ return NULL;
+}
+
+// compute the process info into the list
+void add_ctx(struct ctx_list *list, struct process_info *process)
+{
+ list->process_count ++;
+ list->VmSize_total += process->VmSize;
+ list->VmRSS_total += process->VmRSS;
+ list->utime_total += process->utime + process->cutime;
+ list->stime_total += process->stime + process->cstime;
+
+ if (list->start_time_oldest == 0) // first entry
+ list->start_time_oldest = process->start_time;
+ else
+ if (list->start_time_oldest > process->start_time)
+ list->start_time_oldest = process->start_time;
+}
+
+// increment the count number in the ctx record using ctx number
+void count_ctx(struct ctx_list *list, struct process_info *process)
+{
+ struct ctx_list *prev = list;
+
+ if (process == NULL) return;
+
+ // search
+ while(list != NULL)
+ {
+ // find
+ if (list->ctx == process->s_context)
+ {
+ add_ctx(list, process);
+ return;
+ }
+ // insert between
+ if (list->ctx > process->s_context)
+ {
+ prev->next = insert_ctx(process->s_context, list);
+ add_ctx(prev->next, process);
+ return;
+ }
+ // ++
+ prev = list;
+ list = list->next;
+ }
+ // add at the end
+ prev->next = insert_ctx(process->s_context, NULL);
+ add_ctx(prev->next, process);
+}
+
+// free mem
+void free_ctx(struct ctx_list *list)
+{
+ struct ctx_list *prev;
+
+ for(;list != NULL; list = prev)
+ {
+ prev = list->next;
+ free(list);
+ }
+}
+
+/*
+ Read the vserver description
+*/
+static void read_description(
+ const char *name, // Vserver name
+ char descrip[1000])
+{
+ char conf[PATH_MAX];
+ FILE *fin;
+ descrip[0] = '\0';
+ snprintf (conf,sizeof(conf)-1,"/etc/vservers/%s.conf",name);
+ fin = fopen (conf,"r");
+ if (fin != NULL){
+ char line[1000];
+ while (fgets(line,sizeof(line)-1,fin)!=NULL){
+ if (line[0] == '#'){
+ char *pt = line+1;
+ while (isspace(*pt)) pt++;
+ if (strncmp(pt,"Description:",12)==0){
+ int last;
+ pt += 12;
+ while (isspace(*pt)) pt++;
+ strcpy (descrip,pt);
+ last = strlen(descrip)-1;
+ if (last >=0 && descrip[last] == '\n'){
+ descrip[last] = '\0';
+ }
+ }
+ }
+ }
+ fclose (fin);
+ }
+}
+
+// show the ctx_list with name from /var/run/servers/*.ctx
+void show_ctx(struct ctx_list *list)
+{
+ // fill the ctx_list using the /var/run/servers/*.ctx file(s)
+ __extension__ int bind_ctx_name(struct ctx_list *list)
+ {
+ // fetch the context number in /var/run/vservers/'filename'
+ int fetch_ctx_number(char *filename)
+ {
+ int fd;
+ int ctx;
+ char buf[25];
+
+ // open file
+ if ((fd = open(filename, O_RDONLY, 0)) == -1)
+ return -1;
+ // put the file in a small buffer
+ if (read(fd, buf, sizeof(buf)) < 1)
+ return -1;
+
+ close(fd);
+
+ sscanf(buf, "S_CONTEXT=%d", &ctx);
+ return ctx;
+ }
+
+ /* begin bind_ctx_name */
+
+ DIR *ctx_dir;
+ struct dirent *dir_entry;
+ char *p;
+ char ctx_name[CTX_NAME_MAX_LEN];
+ struct ctx_list *ctx;
+ int ctx_number;
+
+ // open the /var/run/vservers directory
+ if ((ctx_dir = opendir(CTX_DIR_NAME)) == NULL)
+ {
+ fprintf(stderr, "%s: in openning %s: %s\n", process_name, CTX_DIR_NAME, strerror(errno));
+ return -1;
+ }
+
+ chdir(CTX_DIR_NAME);
+ while ((dir_entry = readdir(ctx_dir)) != NULL)
+ {
+ strncpy(ctx_name, dir_entry->d_name, sizeof(ctx_name));
+ p = strstr(ctx_name, ".ctx");
+ if (p != NULL) // make sure that it is a .ctx file..
+ {
+ *p = '\0'; // remove the .ctx in the file name
+ if ((ctx_number = fetch_ctx_number(dir_entry->d_name)) > 1)
+ {
+ if ((ctx = find_ctx(list, ctx_number)) != NULL)
+ strncpy(ctx->name, ctx_name, CTX_NAME_MAX_LEN);
+ }
+ }
+ // else fprintf(stderr, "invalid file %s in %s\n", dir_entry->d_name, CTX_DIR_NAME);
+ }
+ closedir(ctx_dir);
+ return 0;
+ }
+
+ __extension__ char *convert_time(unsigned t, char *str)
+ {
+ unsigned hh, mm, ss, ms;
+
+ ms = t % 100;
+ t /= 100;
+
+ ss = t%60;
+ t /= 60;
+ mm = t%60;
+ t /= 60;
+ hh = t%60;
+ t /= 24;
+
+ if (t > 0) // day > 0
+ {
+ snprintf(str, 25, "%3.ud%02uh%02u", t, (hh%12) ? hh%12 : 12, mm);
+ }
+ else
+ {
+ if (hh > 0) // hour > 0
+ snprintf(str, 25, " %2.uh%02um%02u", hh, mm, ss);
+ else
+ {
+ snprintf(str, 25, " %2.um%02u.%02u", mm, ss, ms);
+ }
+ }
+ return str;
+ }
+
+ __extension__ char *convert_mem(unsigned long total, char *str)
+ {
+ // Byte
+ if (total < 1024)
+ {
+ snprintf(str, 25, "%luB", total);
+ return str;
+ }
+
+ total >>= 10; // kByte
+ if (total < 1024)
+ {
+ snprintf(str, 25, "%lukB", total);
+ return str;
+ }
+
+ total >>= 10; // MByte
+ if (total < 1024)
+ {
+ snprintf(str, 25, "%luMB", total);
+ return str;
+ }
+
+ total >>= 10; // GByte
+ if (total < 1024)
+ {
+ snprintf(str, 25, "%luGB", total);
+ return str;
+ }
+ total >>= 10; // TByte
+ snprintf(str, 25, "%luTB", total);
+ return str;
+ }
+
+ /* begin show_ctx */
+ char utime[25], stime[25], ctx_uptime[25];
+ char vmsize[25], vmrss[25];
+ long uptime = get_uptime();
+
+ // now we have all the active context, fetch the name
+ // from /var/run/vservers/*.ctx
+ bind_ctx_name(list);
+
+ printf("CTX PROC VSZ RSS userTIME sysTIME UPTIME NAME DESCRIPTION\n");
+ while(list != NULL)
+ {
+ char descrip[1000];
+ if (list->ctx == 1)
+ strncpy(list->name, "monitoring server", CTX_NAME_MAX_LEN);
+
+ read_description (list->name,descrip);
+
+ printf("%-4d %4d %6s %6s %9s %9s %9s %-8s %s\n", list->ctx, list->process_count,
+ convert_mem(list->VmSize_total, vmsize), convert_mem(list->VmRSS_total, vmrss),
+ convert_time(list->utime_total, utime), convert_time(list->stime_total, stime), convert_time(uptime - list->start_time_oldest, ctx_uptime)
+ , list->name,descrip);
+ list = list->next;
+ }
+}
+
+// open the process's status file to get the ctx number, and other stat
+struct process_info *get_process_info(char *pid)
+{
+ int fd;
+ char buffer[1024];
+ char *p;
+ static struct process_info process;
+
+ // open the proc/#/status file
+ snprintf(buffer, sizeof(buffer), "/proc/%s/status", pid);
+ if ((fd = open(buffer, O_RDONLY, 0)) == -1)
+ return NULL;
+ // put the file in a buffer
+ if (read(fd, buffer, sizeof(buffer)) < 1)
+ return NULL;
+
+ close(fd);
+
+ // find the s_context entry
+ if ((p = strstr(buffer, "s_context:")) == NULL)
+ return NULL;
+
+ sscanf(p, "s_context: %d", &process.s_context);
+
+ // open the /proc/#/stat file
+ snprintf(buffer, sizeof(buffer), "/proc/%s/stat", pid);
+ if ((fd = open(buffer, O_RDONLY, 0)) == -1)
+ return NULL;
+ // put the file in a buffer
+ if (read(fd, buffer, sizeof(buffer)) < 1)
+ return NULL;
+
+ close(fd);
+
+ p = strchr(buffer, ')'); // go after the PID (process_name)
+ sscanf(p + 2,
+ "%*s "
+ "%*s %*s %*s %*s %*s "
+ "%*s %*s %*s %*s %*s %ld %ld "
+ "%ld %ld %*s %*s %*s %*s "
+ "%ld %ld "
+ "%ld ", &process.utime, &process.stime,
+ &process.cutime, &process.cstime,
+ &process.start_time,
+ &process.VmSize, &process.VmRSS);
+
+ return &process;
+}
+
+int main(int argc, char **argv)
+{
+ DIR *proc_dir;
+ struct dirent *dir_entry;
+ pid_t my_pid;
+ static int ctx1[]={1};
+
+ // for error msg
+ process_name = argv[0];
+
+ if (argc > 1)
+ {
+ usage();
+ return 0;
+ }
+
+ // do not include own stat
+ my_pid = getpid();
+
+ // try to switch in context 1
+ if (call_new_s_context(1,ctx1, 0, 0) < 0)
+ {
+ fprintf(stderr, "%s: unable to switch in context security #1\n", process_name);
+ return -1;
+ }
+
+ // create the fist...
+ my_ctx_list = insert_ctx(0, NULL);
+ // init with the default name for the context 0
+ strncpy(my_ctx_list->name, "root server", CTX_NAME_MAX_LEN);
+
+ // open the /proc dir
+ if ((proc_dir = opendir(PROC_DIR_NAME)) == NULL)
+ {
+ fprintf(stderr, "%s: %s\n", process_name, strerror(errno));
+ return -1;
+ }
+
+ chdir(PROC_DIR_NAME);
+ while ((dir_entry = readdir(proc_dir)) != NULL)
+ {
+ // select only process file
+ if (!isdigit(*dir_entry->d_name))
+ continue;
+
+ if (atoi(dir_entry->d_name) != my_pid)
+ count_ctx(my_ctx_list, get_process_info(dir_entry->d_name));
+
+ }
+ closedir(proc_dir);
+
+ // output the ctx_list
+ show_ctx(my_ctx_list);
+
+ // free the ctx_list
+ free_ctx(my_ctx_list);
+
+ return 0;
+}
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vunify.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+
+/*
+ This utility is used to unify (using hard links) two or more
+ virtual servers.
+ It compares the each vserver with the first one and for every
+ common package (RPM, same version), it does a hard link on non
+ configuration file. It turns the file immutable after that.
+*/
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <string>
+#include <vector>
+#include <list>
+#include <algorithm>
+#include <iostream>
+#include "vutil.h"
+
+using namespace std;
+
+static bool undo = false;
+
+static int ext2flags = EXT2_IMMUTABLE_FILE_FL | EXT2_IMMUTABLE_LINK_FL;
+struct EXCLDIR{
+ string prefix;
+ int len;
+ EXCLDIR(const char *s)
+ {
+ prefix = s;
+ prefix += '/';
+ len = prefix.size();
+ }
+};
+static vector<EXCLDIR> excldirs;
+static vector<EXCLDIR> incldirs;
+
+
+static void usage()
+{
+ cerr <<
+ "vunify version " << VERSION <<
+ "\n\n"
+ "vunify [ options ] reference-server vservers ... -- packages\n"
+ "vunify [ options ] reference-server vservers ... -- ALL\n"
+ "\n"
+ "--test: Show what will be done, do not do it.\n"
+ "--undo: Put back the file in place, using copies from the\n"
+ " reference server.\n"
+ "--debug: Prints some debugging messages.\n"
+ "--noflags: Do not put any immutable flags on the file\n"
+ "--immutable: Set the immutable_file bit on the files.\n"
+ "--immutable-mayunlink: Sets the immutable_link flag on files.\n"
+ "\n"
+ "--excldir: None of the files under a given directory will be unified\n"
+ "\tThe directory is expressed in absolute/logical form (relative\n"
+ "\tto the vserver root (ex: /var/log)\n"
+ "\n"
+ "--incldir: All the files under a given directory will be unified\n"
+ "\tThe directory is expressed in absolute/logical form (relative\n"
+ "\tto the vserver root (ex: /var/log)\n"
+ "\n"
+ "By default, the immutable_file and immutable_link flags are\n"
+ "set on the files. So if you want no immutable flags, you must\n"
+ "use --noflags. If you want a single flag, you must use\n"
+ "--noflags first, then the --immutable or --immutable-mayunlink\n"
+ "flag.\n"
+ ;
+}
+
+static bool vunify_inside (vector<EXCLDIR> &dirs, const char *path)
+{
+ bool found = false;
+ for (unsigned i=0; i<dirs.size(); i++){
+ if (strncmp(dirs[i].prefix.c_str(),path,dirs[i].len)==0){
+ found = true;
+ break;
+ }
+ }
+ return found;
+}
+
+class PACKAGE_UNI: public PACKAGE{
+public:
+ list<string> files; // Files to unify
+ // This is loaded on demand
+ PACKAGE_UNI(string &_name, string &_version)
+ : PACKAGE(_name,_version)
+ {
+ }
+ PACKAGE_UNI(const char *_name, const char *_version)
+ : PACKAGE (_name,_version)
+ {
+ }
+ PACKAGE_UNI(const string &line)
+ : PACKAGE (line)
+ {
+ }
+ // Load the file member of the package, but exclude configuration file
+ void loadfiles(const string &ref)
+ {
+ if (files.empty()){
+ if (debug) cout << "Loading files for package " << name << endl;
+ string namever;
+ namever = name + '-' + version;
+ FILE *fin = vutil_execdistcmd (K_UNIFILES,ref,namever.c_str());
+ if (fin != NULL){
+ char tmp[1000];
+ while (fgets(tmp,sizeof(tmp)-1,fin)!=NULL){
+ int last = strlen(tmp)-1;
+ if (last >= 0 && tmp[last] == '\n') tmp[last] = '\0';
+ bool must_unify = false;
+ int type = 0; // K_UNIFILES only report unify-able files
+ if(type == 0 && !vunify_inside(excldirs,tmp)){
+ must_unify = true;
+ }else if(vunify_inside(incldirs,tmp)){
+ must_unify = true;
+ }
+ if (must_unify){
+ files.push_front (tmp);
+ }else if (debug){
+ cout << "Package " << name << " exclude " << tmp << endl;
+ }
+ }
+ }
+ if (debug) cout << "Done\n";
+ }
+ }
+};
+
+
+static ostream & operator << (ostream &c, const PACKAGE_UNI &p)
+{
+ return c << p.name << "-" << p.version;
+}
+
+template<class T>
+ void printit(T a){
+ cout << "xx " << a << endl;
+ }
+
+template<class T>
+ class printer{
+ string title;
+ public:
+ printer (const char *_title): title(_title){}
+ void operator()(T a){
+ cout << title << " " << a << endl;
+ }
+ };
+
+
+/*
+ Load the list of all packages in a vserver
+*/
+static void vunify_loadallpkg (string &refserver, list<PACKAGE_UNI> &packages)
+{
+ FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL);
+ if (fin != NULL){
+ char line[1000];
+ while (fgets(line,sizeof(line)-1,fin)!=NULL){
+ // fprintf (stderr,"line: %s",line);
+ int last = strlen(line)-1;
+ if (last >= 0 && line[last] == '\n') line[last] = '\0';
+ packages.push_back (PACKAGE_UNI(line));
+ }
+ pclose (fin);
+ }
+}
+
+/*
+ Object to unify a file
+ The file is first removed, then a hard link is made and then
+ the immutable flag is done
+*/
+class file_unifier{
+ string &ref_server,&target_server;
+ int &ret;
+ public:
+ file_unifier(string &_ref, string &_target, int &_ret)
+ : ref_server(_ref),target_server(_target), ret(_ret)
+ {}
+ void operator()(const string &file)
+ {
+ string refpath = "/vservers/" + ref_server + file;
+ string dstpath = "/vservers/" + target_server + file;
+ if (debug) cout << "Unify " << refpath << " -> " << dstpath << endl;
+ struct stat st;
+ if (stat(refpath.c_str(),&st)==-1){
+ if (debug) cout << "File " << refpath << " does not exist, ignored\n";
+ }else if (setext2flag(refpath.c_str(),false,ext2flags)==-1){
+ ret = -1;
+ }else if (vbuild_unlink(dstpath.c_str())==-1){
+ ret = -1;
+ cerr << "Can't delete file " << dstpath
+ << " (" << strerror(errno) << ")\n";
+ }else{
+ if (undo){
+ if (vbuild_file_copy(refpath.c_str(),dstpath.c_str(),st)==-1){
+ ret = -1;
+ cerr << "Can't copy file " << refpath << " to " << dstpath
+ << " (" << strerror(errno) << ")\n";
+ }
+ }else{
+ if (vbuild_link(refpath.c_str(),dstpath.c_str())==-1){
+ ret = -1;
+ cerr << "Can't link file " << refpath << " to " << dstpath
+ << " (" << strerror(errno) << ")\n";
+ }
+ }
+ // We put back the original immutable because other vservers
+ // may be unified on it.
+ if (setext2flag(refpath.c_str(),true,ext2flags)==-1){
+ ret = -1;
+ }
+ }
+ }
+};
+#if 0
+// Check if two package have the same name (but potentially different version)
+class same_name{
+ PACKAGE_UNI &pkg;
+public:
+ same_name(PACKAGE_UNI &_pkg) : pkg(_pkg) {}
+ bool operator()(const PACKAGE_UNI &p)
+ {
+ return pkg.name == p.name;
+ }
+};
+#endif
+// Predicate to decide if a package must be unified
+class package_unifier{
+public:
+ string &ref_server,&target_server;
+ list<PACKAGE_UNI> &target_packages;
+ int &ret;
+ package_unifier(string &_ref,
+ string &_target,
+ list<PACKAGE_UNI> &_target_packages,
+ int &_ret)
+ : ref_server(_ref),target_server(_target)
+ , target_packages(_target_packages) , ret(_ret)
+ {}
+ void operator()(PACKAGE_UNI &pkg)
+ {
+ if (find(target_packages.begin(),target_packages.end(),pkg)
+ !=target_packages.end()){
+ // Ok, the package is also in the target vserver
+ cout << "Unify pkg " << pkg << " from " << ref_server << " to "
+ << target_server << endl;
+
+ if (!testmode || debug){
+ pkg.loadfiles(ref_server);
+ for_each (pkg.files.begin(),pkg.files.end()
+ ,file_unifier(ref_server,target_server,ret));
+ }
+ }else if (testmode){
+ // The package is missing, in test mode we provide more information
+ if (find_if(target_packages.begin(),target_packages.end(),same_name(pkg))
+ !=target_packages.end()){
+ cout << pkg << " exist in server " << target_server << " not unified\n";
+ }else{
+ cout << pkg << " does not exist in server " << target_server << endl;
+ }
+ }
+ }
+};
+
+// For each vserver, find the common packages and unify them
+class server_unifier{
+public:
+ list<PACKAGE_UNI> &ref_packages;
+ string &ref_server;
+ int &ret;
+ server_unifier(string _ref_server, list<PACKAGE_UNI> &_packages, int &_ret)
+ : ref_packages(_packages),ref_server(_ref_server), ret(_ret)
+ {}
+ void operator()(string serv)
+ {
+ list<PACKAGE_UNI> pkgs;
+ vunify_loadallpkg (serv,pkgs);
+ for_each(ref_packages.begin(),ref_packages.end()
+ ,package_unifier(ref_server,serv,pkgs,ret));
+ }
+};
+class deleteif{
+public:
+ char **argv0,**argvn;
+ deleteif(char **_argv0, char **_argvn): argv0(_argv0),argvn(_argvn){}
+ bool operator()(const PACKAGE_UNI &pkg)
+ {
+ bool found = false;
+ for (char **pt = argv0; pt < argvn; pt++){
+ if (pkg.name == *pt){
+ found = true;
+ break;
+ }
+ }
+ return !found;
+ }
+};
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ int i;
+ for (i=1; i<argc; i++){
+ const char *arg = argv[i];
+ //const char *opt = argv[i+1];
+ if (strcmp(arg,"--test")==0){
+ testmode = true;
+ }else if (strcmp(arg,"--undo")==0){
+ undo = true;
+ }else if (strcmp(arg,"--debug")==0){
+ debug++;
+ }else if (strcmp(arg,"--noflags")==0){
+ ext2flags = 0;
+ }else if (strcmp(arg,"--immutable")==0){
+ ext2flags |= EXT2_IMMUTABLE_FILE_FL;
+ }else if (strcmp(arg,"--immutable-mayunlink")==0){
+ ext2flags |= EXT2_IMMUTABLE_LINK_FL;
+ }else if (strcmp(arg,"--excldir")==0){
+ i++;
+ //excldirs[excldirs.size()] = EXCLDIR(argv[i]);
+ excldirs.push_back (EXCLDIR(argv[i]));
+ }else if (strcmp(arg,"--incldir")==0){
+ i++;
+ incldirs.push_back (EXCLDIR(argv[i]));
+ }else{
+ break;
+ }
+ }
+ if (i==argc){
+ usage();
+ }else{
+ string refserv = argv[i++];
+ list<string> vservers;
+ for (; i<argc && strcmp(argv[i],"--")!=0; i++){
+ vservers.push_front (argv[i]);
+ }
+ for_each (vservers.begin(),vservers.end(),printer<string>("vservers"));
+ if (i == argc || strcmp(argv[i],"--")!=0){
+ usage();
+ }else{
+ i++;
+ if (i < argc){
+ list<PACKAGE_UNI> packages;
+ vunify_loadallpkg (refserv,packages);
+ if (i != argc-1 || strcmp(argv[i],"ALL")!=0){
+ // We keep only the packages supplied on the command line
+ packages.remove_if(deleteif (argv+i,argv+argc));
+ }
+ ret = 0;
+ umask (0);
+ for_each (vservers.begin(),vservers.end(),server_unifier(refserv,packages,ret));
+ }else{
+ usage();
+ }
+ }
+ }
+ return ret;
+}
+
+
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vutil.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#pragma implementation
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <utime.h>
+#include "vutil.h"
+#include <sys/ioctl.h>
+#include <linux/ext2_fs.h>
+
+bool testmode;
+int debug;
+
+int file_copy (const char *src, const char *dst, struct stat &st)
+{
+ int ret = -1;
+ FILE *fin = fopen (src,"r");
+ if (fin == NULL){
+ fprintf (stderr,"Can't open file %s (%s)\n",src,strerror(errno));
+ }else{
+ FILE *fout = fopen (dst,"w");
+ if (fout == NULL){
+ fprintf (stderr,"Can't open file %s (%s)\n",dst,strerror(errno));
+ }else{
+ char buf[8192];
+ int len;
+ while ((len=fread(buf,1,sizeof(buf),fin))>0){
+ fwrite (buf,1,len,fout);
+ }
+ fflush (fout);
+ ret = 0;
+ if (fchown (fileno(fout),st.st_uid,st.st_gid)==-1){
+ fprintf (stderr,"Can't chown file %s (%s)\n"
+ ,dst,strerror(errno));
+ ret = -1;
+ }else if (fchmod (fileno(fout),st.st_mode)==-1){
+ fprintf (stderr,"Can't chmod file %s (%s)\n"
+ ,dst,strerror(errno));
+ ret = -1;
+ }
+ fclose(fout);
+ struct utimbuf timbuf;
+ timbuf.modtime = st.st_mtime;
+ timbuf.actime = st.st_atime;
+ if (utime (dst,&timbuf)==-1){
+ fprintf (stderr,"Can't set time stamp on file %s (%s)\n"
+ ,dst,strerror(errno));
+ }
+ }
+ fclose (fin);
+ }
+ return ret;
+}
+
+/*
+ Set the immutable flag on a file
+*/
+int setext2flag (const char *fname, bool set, int ext2flags)
+{
+ int ret = -1;
+ if (testmode){
+ ret = 0;
+ }else{
+ int fd = open (fname,O_RDONLY);
+ if (fd == -1){
+ fprintf (stderr,"Can't open file %s (%s)\n",fname
+ ,strerror(errno));
+ }else{
+ int flags = set ? ext2flags : 0;
+ ret = ioctl (fd,EXT2_IOC_SETFLAGS,&flags);
+ close (fd);
+ if (ret == -1){
+ fprintf (stderr,"Can't %s immutable flag on file %s (^s)\n"
+ ,(set ? "set" : "unset")
+ ,fname
+ ,strerror(errno));
+ }
+ }
+ }
+ return ret;
+}
+
+int vbuild_mkdir (const char *path, mode_t mode)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("mkdir %s; chmod %o %s\n",path,mode,path);
+ ret = 0;
+ }else{
+ ret = mkdir (path,mode);
+ if (ret == -1 && errno == EEXIST){
+ struct stat st;
+ if (lstat(path,&st)!=-1 && S_ISDIR(st.st_mode)){
+ ret = chmod (path,mode);
+ }
+ }
+ }
+ return ret;
+}
+
+int vbuild_mknod(const char *path, mode_t mode, dev_t dev)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("mknod %s %o %02x:%02x\n",path,mode,major(dev),minor(dev));
+ ret = 0;
+ }else{
+ ret = mknod (path,mode,dev);
+ if (ret == -1 && errno == EEXIST){
+ struct stat st;
+ lstat(path,&st);
+ if (lstat(path,&st)!=-1
+ && (st.st_mode & S_IFMT) == (mode & S_IFMT)
+ && st.st_rdev == dev){
+ ret = chmod (path,mode);
+ }
+ }
+ }
+ return ret;
+}
+int vbuild_symlink(const char *src, const char *dst)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("ln -s %s %s\n",src,dst);
+ ret = 0;
+ }else{
+ ret = symlink (src,dst);
+ }
+ return ret;
+}
+
+int vbuild_link(const char *src, const char *dst)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("ln %s %s\n",src,dst);
+ ret = 0;
+ }else{
+ ret = link (src,dst);
+ }
+ return ret;
+}
+
+int vbuild_unlink(const char *path)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("unlink %s\n",path);
+ ret = 0;
+ }else{
+ ret = unlink (path);
+ }
+ return ret;
+}
+
+int vbuild_chown(const char *path, uid_t uid, gid_t gid)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("chown %d.%d %s\n",uid,gid,path);
+ ret = 0;
+ }else{
+ ret = chown (path,uid,gid);
+ }
+ return ret;
+}
+
+int vbuild_file_copy(
+ const char *src,
+ const char *dst,
+ struct stat &st)
+{
+ int ret = -1;
+ if (testmode){
+ printf ("cp -a %s %s\n",src,dst);
+ ret = 0;
+ }else{
+ ret = file_copy (src,dst,st);
+ }
+ return ret;
+}
+
+/*
+ Load the list of all packages in a vserver
+*/
+void vutil_loadallpkg (string &refserver, list<PACKAGE> &packages)
+{
+ FILE *fin = vutil_execdistcmd (K_PKGVERSION,refserver,NULL);
+ if (fin != NULL){
+ char line[1000];
+ while (fgets(line,sizeof(line)-1,fin)!=NULL){
+ int last = strlen(line)-1;
+ if (last >= 0 && line[last] == '\n') line[last] = '\0';
+ packages.push_back (PACKAGE(line));
+ }
+ pclose (fin);
+ }
+}
+
+int vutil_lstat (string path, struct stat &st)
+{
+ int ret = 0;
+ if (lstat(path.c_str(),&st) == -1){
+ fprintf (stderr,"Can't lstat file %s (%s)\n"
+ ,path.c_str(),strerror(errno));
+ ret = -1;
+ }
+ return ret;
+}
+
+const char K_PKGVERSION[]="pkgversion";
+const char K_DUMPFILES[]="dumpfiles";
+const char K_UNIFILES[]="unifiles";
+
+FILE *vutil_execdistcmd (const char *key, const string &vserver, const char *args)
+{
+ string cmd = PKGLIBDIR "/distrib-info ";
+ cmd += vserver;
+ cmd += " ";
+ cmd += key;
+ if (args != NULL){
+ cmd += " ";
+ cmd += args;
+ }
+ FILE *ret = popen (cmd.c_str(),"r");
+ if (ret == NULL){
+ fprintf (stderr,"Can't execute command %s\n",cmd.c_str());
+ }else{
+ #if 0
+ char buf[1000];
+ while (fgets(buf,sizeof(buf)-1,fin)!=NULL){
+ int last = strlen(buf)-1;
+ if (last >= 0) buf[last] = '\0';
+ ret = buf;
+ break;
+ }
+ pclose (fin);
+ #endif
+ }
+ return ret;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vutil.h by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#pragma interface
+#ifndef VUTIL_H
+#define VUTIL_H
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <string>
+#include <set>
+#include <algorithm>
+#include <iostream>
+#include <list>
+
+using namespace std;
+
+extern int debug;
+extern bool testmode;
+
+// Patch to help compile this utility on unpatched kernel source
+#ifndef EXT2_IMMUTABLE_FILE_FL
+ #define EXT2_IMMUTABLE_FILE_FL 0x00000010
+ #define EXT2_IMMUTABLE_LINK_FL 0x00008000
+#endif
+
+
+FILE *vutil_execdistcmd (const char *, const string &, const char *);
+extern const char K_DUMPFILES[];
+extern const char K_UNIFILES[];
+extern const char K_PKGVERSION[];
+
+class PACKAGE{
+public:
+ string name;
+ string version; // version + release
+ PACKAGE(string &_name, string &_version)
+ : name (_name), version(_version)
+ {
+ }
+ PACKAGE(const char *_name, const char *_version)
+ : name (_name), version(_version)
+ {
+ }
+ PACKAGE(const string &line)
+ {
+ *this = line;
+ }
+ PACKAGE & operator = (const string &_line)
+ {
+ string line (_line);
+ string::iterator pos = find (line.begin(),line.end(),'=');
+ if (pos != line.end()){
+ name = string(line.begin(),pos);
+ version = string(pos + 1,line.end());
+ }
+ return *this;
+ }
+ PACKAGE (const PACKAGE &pkg)
+ {
+ name = pkg.name;
+ version = pkg.version;
+ }
+ bool operator == (const PACKAGE &v) const
+ {
+ return name == v.name && version == v.version;
+ }
+ bool operator < (const PACKAGE &v) const
+ {
+ bool ret = false;
+ if (name < v.name){
+ ret = true;
+ }else if (name == v.name && version < v.version){
+ ret = true;
+ }
+ return ret;
+ }
+ // Load the file member of the package, but exclude configuration file
+ void loadfiles(const string &ref, set<string> &files)
+ {
+ if (debug > 2) cout << "Loading files for package " << name << endl;
+ string namever = name + '-' + version;
+ FILE *fin = vutil_execdistcmd (K_UNIFILES,ref,namever.c_str());
+ if (fin != NULL){
+ char tmp[1000];
+ while (fgets(tmp,sizeof(tmp)-1,fin)!=NULL){
+ int last = strlen(tmp)-1;
+ if (last >= 0 && tmp[last] == '\n') tmp[last] = '\0';
+ files.insert (tmp);
+ }
+ }
+ if (debug > 2) cout << "Done\n";
+ }
+ #if 0
+ bool locate(const string &path)
+ {
+ return find (files.begin(),files.end(),path) != files.end();
+ }
+ #endif
+};
+
+// Check if two package have the same name (but potentially different version)
+class same_name{
+ const PACKAGE &pkg;
+public:
+ same_name(const PACKAGE &_pkg) : pkg(_pkg) {}
+ bool operator()(const PACKAGE &p)
+ {
+ return pkg.name == p.name;
+ }
+};
+
+
+#include "vutil.p"
+
+#endif
+
--- /dev/null
+// $Id$ --*- c++ -*--
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on vutil.p by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+
+/* vutil.cc 11/04/2003 14.22.04 */
+int file_copy (const char *src, const char *dst, struct stat&st);
+int setext2flag (const char *fname, bool set, int ext2flags);
+int vbuild_mkdir (const char *path, mode_t mode);
+int vbuild_mknod (const char *path, mode_t mode, dev_t dev);
+int vbuild_symlink (const char *src, const char *dst);
+int vbuild_link (const char *src, const char *dst);
+int vbuild_unlink (const char *path);
+int vbuild_chown (const char *path, uid_t uid, gid_t gid);
+int vbuild_file_copy (const char *src,
+ const char *dst,
+ struct stat&st);
+void vutil_loadallpkg (string&refserver, list<PACKAGE>&packages);
+int vutil_lstat (string path, struct stat&st);
+FILE *vutil_execdistcmd (const char *key,
+ const string&vserver,
+ const char *args);
+/* syscall.cc 18/07/2003 09.50.10 */
+extern "C" int call_new_s_context (int nbctx,
+ int ctxs[],
+ int remove_cap,
+ int flags);
+extern "C" int call_set_ipv4root (unsigned long ip[],
+ int nb,
+ unsigned long bcast,
+ unsigned long mask[]);
+extern "C" int call_chrootsafe (const char *dir);
+extern "C" int has_chrootsafe (void);
+extern "C" int call_set_ctxlimit (int res, long limit);
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+sysv_XTRAS = sysv/rebootmgr.subst \
+ sysv/v_gated.subst \
+ sysv/v_httpd.subst \
+ sysv/v_named.subst \
+ sysv/v_portmap.subst \
+ sysv/v_sendmail.subst \
+ sysv/v_smb.subst \
+ sysv/v_sshd.subst \
+ sysv/v_xinetd.subst \
+ sysv/vservers.subst
+
+sysv_GENSCRPTS = sysv/rebootmgr \
+ sysv/v_gated \
+ sysv/v_httpd \
+ sysv/v_named \
+ sysv/v_portmap \
+ sysv/v_sendmail \
+ sysv/v_smb \
+ sysv/v_sshd \
+ sysv/v_xinetd \
+ sysv/vservers
+
+sysv_SCRPTS = $(sysv_GENSCRPTS)
+
+sysv_CFG = sysv/vservers.conf
+
+
+sysv/%: sysv/%.subst
+ @mkdir -p $$(dirname '$@')
+ sed -s 's!/usr/lib/util-vserver!$(pkglibdir)!g; \
+ s!^USR_SBIN=/usr/sbin$$!USR_SBIN=$(sbindir)!g' '$<' >'$@.tmp'
+ if cmp -s '$<' '$@.tmp'; then \
+ cp -p '$<' '$@'; \
+ else \
+ mv -f '$@.tmp' '$@'; \
+ fi
+ -rm -f '$@.tmp'
+ @chmod a-w '$@'
--- /dev/null
+#!/bin/sh
+# chkconfig: - 98 10
+# description: The rebootmgr service is monitoring all virtual servers \
+# and restart them as need. Virtual servers are using \
+# the /sbin/vreboot command to talk with the reboot manager
+# processname: rebootmgr
+# config: /etc/vservers
+
+
+USR_SBIN=/usr/sbin
+PIDFILE=/var/run/rebootmgr.pid
+# See how we were called.
+case "$1" in
+ start)
+ echo "Starting the reboot manager"
+ cd /etc/vservers
+ VSERVERS=
+ for serv in *.conf
+ do
+ serv=`basename $serv .conf`
+ if [ -d /vservers/$serv ] ; then
+ VSERVERS="$VSERVERS $serv"
+ fi
+ done
+ $USR_SBIN/rebootmgr --pidfile $PIDFILE $VSERVERS &
+ touch /var/lock/subsys/rebootmgr
+ ;;
+ stop)
+ echo "Stopping the reboot manager"
+ kill `cat $PIDFILE`
+ rm -f /var/lock/subsys/rebootmgr
+ rm -f $PIDFILE
+ ;;
+ restart)
+ $0 stop
+ $0 start
+ ;;
+ reload)
+ echo Not implemented
+ ;;
+ status)
+ if [ -f $PIDFILE ] ; then
+ if kill -0 `cat $PIDFILE`
+ then
+ echo rebootmgr is running
+ else
+ echo rebootmgr is NOT running
+ fi
+ fi
+ ;;
+ *)
+ echo "Usage: rebootmgr {start|stop|restart|reload|status}"
+ exit 1
+esac
+
+exit 0
+
+
+
+
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 32 75
+# description: Wrapper to start gated bound to a single IP
+
+# normally, you will need /etc/vservices/gated.conf
+# with the following line
+# IP=0.0.0.0
+# so gated is started without restriction even if you
+# restart it from an ssh session, itself "chbounded" to a single
+# IP.
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper gated $*
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 85 15
+# description: Wrapper to start httpd bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper httpd $*
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 55 45
+# description: Wrapper to start named bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper named $*
+
+
+
+
+
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 91 35
+# description: Wrapper to start portmap bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper portmap $*
+
+
+
+
+
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 80 30
+# description: Wrapper to start sendmail bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper sendmail $*
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 91 35
+# description: Wrapper to start smb bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper smb $*
+
+
+
+
+
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 55 25
+# description: Wrapper to start sshd bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper sshd $*
+
+
+
+
+
+
--- /dev/null
+#!/bin/sh
+# chkconfig: - 56 50
+# description: Wrapper to start xinetd bound to a single IP
+USR_LIB_VSERVER=/usr/lib/util-vserver
+exec $USR_LIB_VSERVER/vsysvwrapper xinetd $*
+
--- /dev/null
+# Configuration file for the vservers service
+# BACKGROUND=yes
+# start the vservers on tty9, in background so the rest of the
+# boot process end early
+BACKGROUND=no
+
+
--- /dev/null
+#!/bin/sh
+# chkconfig: 345 98 10
+# description: The vservers service is used to start and stop all
+# the virtual servers.
+
+USR_SBIN=/usr/sbin
+
+
+# Print the vserver name in priority/alpha order
+sortserver(){
+ (
+ cd /etc/vservers
+ for serv in *.conf
+ do
+ PRIORITY=100
+ . $serv
+ printf "%03d %s\n" $PRIORITY `basename $serv .conf`
+ done
+ ) | sort $* | (while read a b; do echo $b; done)
+}
+
+startservers(){
+ echo "Starting the virtual servers"
+ cd /etc/vservers
+ for name in `sortserver`
+ do
+ ONBOOT=
+ . $name.conf
+ if [ "$ONBOOT" = "yes" ] ; then
+ $USR_SBIN/vserver $name start
+ else
+ echo virtual server $name not configured for on boot start
+ fi
+ done
+}
+
+BACKGROUND=off
+if [ -f /etc/vservers.conf ] ; then
+ . /etc/vservers.conf
+fi
+
+
+# See how we were called.
+case "$1" in
+ start)
+ if [ "$BACKGROUND" = "yes" ] ; then
+ startservers >/dev/tty8 </dev/tty8 2>/dev/tty8 &
+ else
+ startservers
+ fi
+ touch /var/lock/subsys/vservers
+ ;;
+ stop)
+ echo "Stopping the virtual servers"
+ cd /etc/vservers
+ for name in `sortserver -r`
+ do
+ $USR_SBIN/vserver $name stop
+ done
+ rm -f /var/lock/subsys/vservers
+ ;;
+ restart)
+ $0 stop
+ $0 start
+ ;;
+ reload)
+ echo Not implemented
+ ;;
+ status)
+ cd /etc/vservers
+ for serv in *.conf
+ do
+ ONBOOT=no
+ name=`basename $serv .conf`
+ . $serv
+ echo -n ONBOOT=$ONBOOT " "
+ $USR_SBIN/vserver $name running
+ done
+ ;;
+ *)
+ echo "Usage: vservers {start|stop|restart|reload|status}"
+ exit 1
+esac
+
+exit 0
+
+
+
+
--- /dev/null
+## $Id$ -*- makefile -*-
+
+## Copyright (C) 2003 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; either version 2, or (at your option)
+## any later version.
+##
+## 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.
+##
+
+test_PRGS = tests/chrootsafe \
+ tests/escaperoot \
+ tests/forkbomb \
+ tests/testipc \
+ tests/testlimit \
+ tests/testopenf
+
+tests_chrootsafe_SOURCES = tests/chrootsafe.cc
+tests_chrootsafe_LDADD = lib/libvserver.a
+
+tests_escaperoot_SOURCES = tests/escaperoot.cc
+tests_forkbomb_SOURCES = tests/forkbomb.cc
+tests_testipc_SOURCES = tests/testipc.cc
+tests_testlimit_SOURCES = tests/testlimit.cc
+tests_testopenf_SOURCES = tests/testopenf.cc
--- /dev/null
+// $Id$ --*- c++ -*--
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/chrootsafe.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Test the chrootsafe command.
+ Pass the path of a vserver as the only argument
+
+ chrootsafe /vservers/test
+*/
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <grp.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "vserver.h"
+
+int main (int argc, char *argv[])
+{
+ // This test must fail
+ int fd = open ("/",O_RDONLY);
+ if (fd != -1){
+ if (call_chrootsafe(argv[1])==-1){
+ fprintf (stderr,"Ok, chrootsafe failed with one open directory errno=%s\n",strerror(errno));
+ }else{
+ fprintf (stderr,"Hum, chrootsafe succeed with one open directory\n");
+ system ("/bin/sh");
+ }
+ close (fd);
+ }
+ // Now it should work
+ if (call_chrootsafe(argv[1])!=-1){
+ fprintf (stderr,"Ok, chrootsafe worked\n");
+ system ("/bin/sh");
+ }else{
+ fprintf (stderr,"chrootsafe failed errno=%s\n",strerror(errno));
+ }
+ return 0;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/escaperoot.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ This program tries to escape out of a vserver using chroot flaws.
+ Once escaped, it exec a shell.
+
+ None of this works on 2.4.13.
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <wait.h>
+#include <limits.h>
+
+static void print_pwd()
+{
+ char path[PATH_MAX];
+ if (getcwd(path,sizeof(path)-1)!=NULL){
+ printf ("PWD: %s\n",path);
+ }
+}
+/*
+ Just set a chroot in a sub-directory and keep the
+ current directory behind
+*/
+static void test1()
+{
+ printf ("test1\n");
+ print_pwd();
+ mkdir ("dummy_dir",0755);
+ if (chroot ("dummy_dir")==-1){
+ fprintf (stderr,"Can't chroot into dummy_dir (%s)\n",strerror(errno));
+ }else{
+ // Try to chdir into the real root
+ for (int i=0; i<1000; i++) chdir("..");
+ print_pwd();
+ if (execl ("/bin/sh","/bin/sh",NULL)==-1){
+ fprintf (stderr,"execl /bin/sh failed (%s)\n",strerror(errno));
+ }
+ }
+}
+
+/*
+ Same as test1, except we open the current directory and do
+ a fchdir() to it before trying to escape to the real root.
+*/
+static void test2()
+{
+ printf ("test2\n");
+ print_pwd();
+ mkdir ("dummy_dir",0755);
+ int fd = open (".",O_RDONLY);
+ if (fd == -1){
+ fprintf (stderr,"Can't open current directory (%s)\n",strerror(errno));
+ }else if (chroot ("dummy_dir")==-1){
+ fprintf (stderr,"Can't chroot into dummy_dir (%s)\n",strerror(errno));
+ }else if (fchdir(fd)==-1){
+ fprintf (stderr,"Can't fchdir to the current directory (%s)\n"
+ ,strerror(errno));
+ }else{
+ // Try to chdir into the real root
+ for (int i=0; i<1000; i++) chdir("..");
+ print_pwd();
+ if (execl ("/bin/sh","/bin/sh",NULL)==-1){
+ fprintf (stderr,"execl /bin/sh failed (%s)\n",strerror(errno));
+ }
+ }
+}
+
+/*
+ Perform the test in a sub-process so it won't affect the current one
+*/
+static void dotest (void (*f)())
+{
+ pid_t pid = fork();
+ if (pid == 0){
+ f();
+ _exit (0);
+ }else if (pid == -1){
+ fprintf (stderr,"Can't fork (%s)\n",strerror(errno));
+ }else{
+ int status;
+ wait (&status);
+ }
+}
+
+int main (int argc, char *argv[])
+{
+ dotest (test1);
+ dotest (test2);
+ printf ("All attempts failed\n");
+ return 0;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/forkbomb.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <stdio.h>
+
+enum MODE {MODE_SLEEP,MODE_LOOP,MODE_FORK, MODE_FORKSHELL};
+
+
+static void forkbomb_userfork (MODE mode)
+{
+ pid_t pid = fork();
+ if (pid==-1){
+ fprintf (stderr,"Fork failed (%s)\n",strerror(errno));
+ }else if (pid == 0){
+ if (mode == MODE_SLEEP){
+ sleep(20);
+ }else if (mode == MODE_LOOP){
+ int k=0;
+ while (1) k++;
+ }else if (mode == MODE_FORKSHELL){
+ system ("/bin/false");
+ }
+ _exit (0);
+ }
+}
+
+
+int main (int argc, char *argv[])
+{
+ if (argc != 4){
+ fprintf (stderr,"formboom N M mode\n"
+ "where N is the number of process to start\n"
+ "and M is the number of user to start\n"
+ "Each user will try to start N process\n"
+ "\n"
+ "mode is:\n"
+ " sleep: Each process sleeps for 20 seconds and exits\n"
+ " loop: Each process loops forever\n"
+ " fork: Each process exits immediatly and is restarted\n"
+ " by the parent\n"
+ " forkshell: Each process runs /bin/false in a shell and\n"
+ " exits, then the parent start a new one\n"
+ );
+ }else{
+ MODE mode;
+ if (strcmp(argv[3],"sleep")==0){
+ mode = MODE_SLEEP;
+ }else if (strcmp(argv[3],"loop")==0){
+ mode = MODE_LOOP;
+ }else if (strcmp(argv[3],"fork")==0){
+ mode = MODE_FORK;
+ }else if (strcmp(argv[3],"forkshell")==0){
+ mode = MODE_FORKSHELL;
+ }else{
+ fprintf (stderr,"Invalid mode\n");
+ exit (-1);
+ }
+ for (int i=0; i<atoi(argv[2]); i++){
+ if (fork()==0){
+ if (setuid (i+1)==-1){
+ fprintf (stderr,"Can't setuid to uid %d (%s)\n",i+1
+ ,strerror(errno));
+ }else{
+ for (int j=0; j<atoi(argv[1]); j++){
+ forkbomb_userfork (mode);
+ }
+ if (mode == MODE_FORK || mode == MODE_FORKSHELL){
+ // Ok, all processes are started, in MODE_FORK
+ // we create a new one all the time
+ int status;
+ while (wait(&status)!=-1) forkbomb_userfork(mode);
+ }
+ }
+ _exit (0);
+ }
+ }
+ system ("ps ax | wc -l");
+ printf ("All the process are running now\n");
+ printf ("Exit to end all processes\n");
+ system ("/bin/sh");
+ system ("killall forkbomb");
+ }
+ return 0;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/testipc.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+/*
+ Test to see isolation of the various IPC resources
+ between security context
+*/
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+
+int main (int argc, char *argv[])
+{
+ int ret = -1;
+ if (argc < 2){
+ fprintf (stderr,
+ "testipc createshm\n"
+ );
+ }else if(strcmp(argv[1],"createshm")==0){
+ int id = shmget (1,1024,IPC_CREAT|0666);
+ if (id == -1){
+ fprintf (stderr,"shmget failed (%s)\n",strerror(errno));
+ }else{
+ printf ("shmget id %d\n",id);
+ void *pt = shmat (id,NULL,0);
+ if (pt == NULL){
+ fprintf (stderr,"can't shmat to id %d (%s)\n",id,strerror(errno));
+ }else{
+ strcpy ((char*)pt,"original string");
+
+ printf ("Letting a sub-program attach to this memory\n");
+ char tmp[100];
+ sprintf (tmp,"./testipc accessshm %d",id);
+ int ok = system (tmp);
+ printf ("\tSub-program returned %d\n",ok);
+
+ printf ("\tThe segment now hold :%s:\n",(char*)pt);
+ shmdt (pt);
+
+ printf ("A sub-program in another context can't attach\n");
+ sprintf (tmp,"/usr/sbin/chcontext ./testipc accessshm %d",id);
+ ok = system (tmp);
+ printf ("\tSub-program returned %d\n",ok);
+
+ printf ("Executing a sub-shell\n");
+ system ("/bin/sh");
+ }
+ printf ("Delete the share memory segment\n");
+ if (shmctl (id,IPC_RMID,NULL)==-1){
+ fprintf (stderr,"shmctl failed (%s)\n",strerror(errno));
+ }else{
+ ret = 0;
+ }
+ }
+ }else if(strcmp(argv[1],"accessshm")==0){
+ int id = atoi(argv[2]);
+ void *pt = shmat (id,NULL,0);
+ if (pt == (void*)-1){
+ fprintf (stderr,"can't shmat to id %d (%s)\n",id,strerror(errno));
+ }else{
+ printf ("\tWriting hello in share memory\n");
+ strcpy ((char*)pt,"hello");
+ ret = 0;
+ }
+ }else if(strcmp(argv[1],"createsem")==0){
+ int id = semget (1,1,IPC_CREAT|0666);
+ if (id == -1){
+ fprintf (stderr,"semget failed (%s)\n",strerror(errno));
+ }else{
+ printf ("semget id %d\n",id);
+
+ printf ("Letting a sub-program play with this semaphore\n");
+ char tmp[100];
+ sprintf (tmp,"./testipc accesssem %d",id);
+ int ok = system (tmp);
+ printf ("\tSub-program returned %d\n",ok);
+
+ printf ("A sub-program in another context can't use the semaphore\n");
+ sprintf (tmp,"/usr/sbin/chcontext ./testipc accesssem %d",id);
+ ok = system (tmp);
+ printf ("\tSub-program returned %d\n",ok);
+
+ printf ("Executing a sub-shell\n");
+ system ("/bin/sh");
+
+ printf ("Delete the semaphore\n");
+ if (semctl (id,0,IPC_RMID,NULL)==-1){
+ fprintf (stderr,"semctl failed (%s)\n",strerror(errno));
+ }else{
+ ret = 0;
+ }
+ }
+ }else if(strcmp(argv[1],"accesssem")==0){
+ int id = atoi(argv[2]);
+ struct sembuf ops[]={
+ {0,0,0}
+ };
+ if (semop (id,ops,1) == -1){
+ fprintf (stderr,"can't semop with id %d (%s)\n",id,strerror(errno));
+ }else{
+ ret = 0;
+ }
+ }
+ return ret;
+}
+
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/testlimit.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[])
+{
+ if (argc != 3){
+ fprintf (stderr,"testlimit nbprocess malloc_size\n");
+ }else{
+ int nbproc = atoi(argv[1]);
+ int size = atoi(argv[2]);
+ for (int i=0; i<nbproc; i++){
+ if (fork()==0){
+ void *pt = malloc(size);
+ if (pt == NULL){
+ fprintf (stderr,"Child %d: can't malloc (%s)\n"
+ ,i,strerror(errno));
+ }else{
+ memset (pt,1,size);
+ }
+ sleep (100);
+ _exit (0);
+ }
+ }
+ int status;
+ while (wait(&status)!=-1);
+ }
+ return 0;
+}
+
--- /dev/null
+// $Id$
+
+// Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
+// based on tests/testopenf.cc by Jacques Gelinas
+//
+// 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; either version 2, or (at your option)
+// any later version.
+//
+// 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+int main (int argc, char *argv[])
+{
+ if (argc != 3){
+ fprintf (stderr,"testlimit nbprocess nbopen\n");
+ }else{
+ int nbproc = atoi(argv[1]);
+ int nbopen = atoi(argv[2]);
+ for (int i=0; i<nbproc; i++){
+ if (fork()==0){
+ int j;
+ for (j=0; j<nbopen; j++){
+ FILE *fin = fopen ("/proc/self/status","r");
+ if (fin == NULL){
+ fprintf (stderr,"Can't open %d (%s)\n",errno,strerror(errno));
+ break;
+ }
+ }
+ printf ("%d open files, sleeping\n",j);
+ sleep (100);
+ _exit (0);
+ }
+ }
+ int status;
+ while (wait(&status)!=-1);
+ }
+ return 0;
+}
+
--- /dev/null
+Summary: Linux virtual server utilities
+Name: @PACKAGE@
+Version: @VERSION@
+Release: 1
+Epoch: 0
+Copyright: GPL
+Group: System Environment/Base
+Source: %name-%version.tar.bz2
+Provides: %name-devel = %epoch:%version-%release
+BuildRoot: %_tmppath/%name-%version-%release-root
+Provides: vserver = %epoch:%version-%release
+Conflicts: vserver < %epoch:%version
+
+
+%description
+This package provides the components and a framework to setup virtual
+servers. A virtual server runs inside a linux server. It is nevertheless
+highly independent. As such, you can run various services with normal
+configuration. The various vservers can't interact with each other and
+can't interact with services in the main server.
+
+This requires a special kernel supporting the new new_s_context and
+set_ipv4root system call.
+
+
+%prep
+%setup -q
+
+
+%build
+%configure
+%__make %{?_smp_mflags}
+
+
+%install
+rm -rf $RPM_BUILD_ROOT
+%__make DESTDIR=$RPM_BUILD_ROOT install
+
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+
+%define v_services httpd named portmap sendmail smb sshd xinetd
+%post
+/sbin/chkconfig --add vservers
+/sbin/chkconfig --add rebootmgr
+
+for i in %v_services; do
+ /sbin/chkconfig --add v_$i
+done
+
+
+%preun
+test "$1" != 0 || for i in %v_services; do
+ /sbin/chkconfig --del v_$i
+done
+
+test "$1" != 0 || %{_initrddir}/rebootmgr stop &>/dev/null || :
+test "$1" != 0 || /sbin/chkconfig --del rebootmgr
+test "$1" != 0 || /sbin/chkconfig --del vservers
+
+
+%postun
+test "$1" = 0 || %{_initrddir}/rebootmgr condrestart >/dev/null || :
+
+
+%files
+%defattr(-,root,root)
+%doc AUTHORS COPYING ChangeLog NEWS README THANKS
+%doc doc/FAQ.txt
+%_sbindir/*
+%_libdir/%name
+%_includedir/vserver.h
+%_libdir/libvserver.a
+%_mandir/man8/*
+%config /etc/init.d/*
+%config(noreplace) /etc/vservers/newvserver.defaults
+%config(noreplace) /etc/vservers.conf
+
+
+%changelog
+
+* Fri Sep 26 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> - 0:0.23.4-1
+- initial build.