From: Enrico Scholz Date: Thu, 16 Oct 2003 02:42:50 +0000 (+0000) Subject: initial checkin X-Git-Tag: VERSION_0_10~1245 X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0692b508de44595db941a2b98b5a73228a65e8fc;p=util-vserver.git initial checkin git-svn-id: http://svn.linux-vserver.org/svn/util-vserver/trunk@165 94cd875c-1c1d-0410-91d2-eb244daf1a30 --- diff --git a/util-vserver/src/compat-pivot_root.h b/util-vserver/src/compat-pivot_root.h new file mode 100644 index 0000000..9fcdba2 --- /dev/null +++ b/util-vserver/src/compat-pivot_root.h @@ -0,0 +1,29 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef H_UTIL_VSERVER_SRC_COMPAT_PIVOT_ROOT_H +#define H_UTIL_VSERVER_SRC_COMPAT_PIVOT_ROOT_H + +#include +#include +#include +#include + +_syscall2(int,pivot_root,const char *,new_root,const char *,put_old) + +#endif // H_UTIL_VSERVER_SRC_COMPAT_PIVOT_ROOT_H diff --git a/util-vserver/src/ctx-kill.c b/util-vserver/src/ctx-kill.c new file mode 100644 index 0000000..a8209a7 --- /dev/null +++ b/util-vserver/src/ctx-kill.c @@ -0,0 +1,341 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif +#include "compat.h" + +#include "wrappers.h" +#include "wrappers-vserver.h" +#include "util.h" +#include "stack-start.h" + +#include +#include +#include +#include +#include +#include + +#ifndef CLONE_NEWNS +# define CLONE_NEWNS 0x00020000 +#endif + +#ifndef MNT_DETACH +# define MNT_DETACH 0x000000002 +#endif + +#if 0 +# include +# define DPRINTF(...) printf(__VA_ARGS__) +#else +# define DPRINTF(...) (void)0 +#endif + +struct ArgInfo { + enum { tpUNSET, tpCTX, tpPID } type; + ctx_t ctx; + pid_t pid; + unsigned int interval; + bool shutdown; + bool omit_init; + size_t argc; + char * const * argv; +}; + +static struct option const +CMDLINE_OPTIONS[] = { + { "help", no_argument, 0, 'h' }, + { "version", no_argument, 0, 'v' }, + { "all", no_argument, 0, 'a' }, + { "ctx", required_argument, 0, 'c' }, + { "pid", required_argument, 0, 'p' }, + { "interval", required_argument, 0, 'i' }, + { "shutdown", no_argument, 0, 's' }, + { 0,0,0,0 } +}; + +int wrapper_exit_code = 1; + +static void +showHelp(int fd, char const *cmd, int res) +{ + WRITE_MSG(fd, "Usage: "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + " (-c|--ctx )|(-p|--pid ) [-i|--interval ] [-a|--all]\n" + " [-s|--shutdown] [--] [ ]*\n\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n"); + exit(res); +} + +static void +showVersion() +{ + WRITE_MSG(1, + "ctx-kill " VERSION " -- kills processes in foreign contexts\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2003 Enrico Scholz\n" + VERSION_COPYRIGHT_DISCLAIMER); + exit(0); +} + +static void +iterateThroughProc(void (*fn)(pid_t pid, void *data), + struct ArgInfo const * const args, + void *data) +{ + int grp = getpgrp(); + DIR *dir; + struct dirent *d; + + kill(-1, SIGSTOP); + dir = opendir("/proc"); + if (dir==0) { + perror("opendir()"); + kill(-1, SIGCONT); + exit(1); + } + + kill(-1, SIGSTOP); + while ((d=readdir(dir))!=0) { + pid_t pid = atoi(d->d_name); + if (pid==0 || // not a /proc// entry + (args->omit_init && pid==1) || + getpgid(pid)==grp) // our own process-group + continue; + + (*fn)(pid,data); + } + kill(-1, SIGCONT); + + closedir(dir); +} + +static void +doKillAllSingle(pid_t pid, void *sig_ptr_v) +{ + register int const * const sig_ptr = sig_ptr_v; + + DPRINTF("sending signal '%u' to process '%u'\n", + *sig_ptr, pid); + kill(pid, *sig_ptr); +} + +static void +getRemainingProcCountProc(pid_t UNUSED pid, void *cnt_v) +{ + register size_t * const cnt = cnt_v; + + ++*cnt; +} + +static size_t +getRemainingProcCount(struct ArgInfo const * const args) +{ + size_t cnt = 0; + iterateThroughProc(&getRemainingProcCountProc, args, &cnt); + + return cnt; +} + +static void +doKillAll(struct ArgInfo const * const args) +{ + size_t i=0; + + signal(SIGSTOP, SIG_IGN); + + while (iargc) { + int sig = atoi(args->argv[i]); + time_t next_time = time(0); + + ++i; + if (iargc) + next_time += atoi(args->argv[i]); + + iterateThroughProc(&doKillAllSingle, args, &sig); + while (time(0)0) + usleep(args->interval * 1000); + + ++i; + } + + if (args->shutdown && getRemainingProcCount(args)>0) { + WRITE_MSG(2, "There are processes which could not be killed\n"); + exit(1); + } + +} + +static void +doKillSingle(struct ArgInfo const * const args) +{ + size_t i=0; + + while (iargc) { + int sig = atoi(args->argv[i]); + time_t next_time = time(0); + + ++i; + if (iargc) + next_time += atoi(args->argv[i]); + + DPRINTF("sending signal '%u' to process '%u'\n", + sig, args->pid); + kill(args->pid, sig); + while (time(0)pid)!=-1 || errno!=ESRCH)) + + usleep(args->interval * 1000); + + ++i; + } +} + +static int +childFunc(void *args_v) +{ + struct ArgInfo * args = args_v; + + Emount("none", "/mnt", "tmpfs", MS_NODEV|MS_NOEXEC|MS_NOSUID, "size=4k"); + Echdir("/mnt"); + Emkdir("proc", 0600); + Emkdir("old", 0600); + Epivot_root(".", "old"); + Echroot("."); + Eumount2("old", MNT_DETACH); + Emkdir("old/foo",0600); + Emount("none", "/proc", "proc", 0, 0); + + // TODO: it may be be better for ctx-shutdown to: + // * generate ctx with S_CTX_INFO_INIT + // * send kill to -1 + Evc_new_s_context(args->ctx, ~0, S_CTX_INFO_LOCK|S_CTX_INFO_SCHED); + + switch (args->type) { + case tpCTX : doKillAll(args); break; + case tpPID : doKillSingle(args); break; + default : assert(false); return 1; + } + + return 0; +} + +static ctx_t +determineContext(pid_t pid) +{ + int fd[2]; + pid_t chld; + ctx_t res; + + Epipe(fd); + chld = Efork(); + + if (chld==0) { + Eclose(fd[0]); + Evc_new_s_context(1, ~0, S_CTX_INFO_LOCK|S_CTX_INFO_SCHED); + res = vc_X_getctx(pid); + Ewrite(fd[1], &res, sizeof res); + Eclose(fd[1]); + _exit(0); + } + + Eclose(fd[1]); + if (Eread(fd[0], &res, sizeof res)!=sizeof(res)) { + WRITE_MSG(2, "internal communication error while determining ctx\n"); + exit(1); + } + Eclose(fd[0]); + if (res==VC_NOCTX) { + WRITE_MSG(2, "can not determine contex for given pid\n"); + exit(1); + } + + return res; +} + +int main(int argc, char *argv[]) +{ + pid_t pid, p; + char buf[0x8000]; + int status; + struct ArgInfo args = { + .type = tpUNSET, + .interval = 500, + .shutdown = false, + .omit_init = true }; + + while (1) { + int c = getopt_long(argc, argv, "hvsac:p:i:", CMDLINE_OPTIONS, 0); + if (c==-1) break; + + switch (c) { + case 'h' : showHelp(1, argv[0], 0); + case 'v' : showVersion(); + case 'c' : + args.type = tpCTX; + args.ctx = atoi(optarg); + break; + case 'p' : + args.type = tpPID; + args.pid = atoi(optarg); + break; + case 'i' : args.interval = atoi(optarg); break; + case 's' : args.shutdown = true; break; + case 'a' : args.omit_init = false; break; + default : + WRITE_MSG(2, "Try '"); + WRITE_STR(2, argv[0]); + WRITE_MSG(2, " --help\" for more information.\n"); + return EXIT_FAILURE; + break; + } + } + + if (args.type==tpUNSET){ + WRITE_MSG(2, "Please specify a context or a pid\n"); + return EXIT_FAILURE; + } + + if (optind==argc) { + WRITE_MSG(2, "No signal specified\n"); + return EXIT_FAILURE; + } + + if (args.type==tpPID) + args.ctx = determineContext(args.pid); + + args.argc = argc-optind; + args.argv = argv+optind; + + // TODO: args.argv verification (only integers) + + if (args.argc%2 != 1) { + WRITE_MSG(2, "Wrong count of ' [ ]*' arguments specified.\n"); + return EXIT_FAILURE; + } + + pid = Eclone(childFunc, STACK_START(buf), CLONE_NEWNS|SIGCHLD, &args); + p = Ewait4(pid, &status, 0,0); + + if (WIFEXITED(status)) return WEXITSTATUS(status); + if (WIFSIGNALED(status)) return kill(getpid(), WTERMSIG(status)); + return EXIT_FAILURE; +} diff --git a/util-vserver/src/secure-umount.c b/util-vserver/src/secure-umount.c new file mode 100644 index 0000000..e2084bd --- /dev/null +++ b/util-vserver/src/secure-umount.c @@ -0,0 +1,74 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifdef HAVE_CONFIG_H +# include +#endif +#include "compat-pivot_root.h" + +#include "wrappers.h" +#include "util.h" + +int wrapper_exit_code = 1; + +static void +showHelp(int fd, char const *cmd, int res) +{ + WRITE_MSG(fd, "Usage: "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + "[--help] [--version] \n\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n"); + + exit(res); +} + +static void +showVersion() +{ + WRITE_MSG(1, + "secure-umount " VERSION " -- secure umounting of directories\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2003 Enrico Scholz\n" + VERSION_COPYRIGHT_DISCLAIMER); + exit(0); +} + +int main(int argc, char *argv[]) +{ + char const * dir; + + if (argc<2) { + WRITE_MSG(2, "Try '"); + WRITE_STR(2, argv[0]); + WRITE_MSG(2, " --help\" for more information.\n"); + return EXIT_FAILURE; + } + + if (strcmp(argv[1], "--help")==0) showHelp(1, argv[0], 0); + if (strcmp(argv[1], "--version")==0) showVersion(); + + dir = argv[1]; + if (strcmp(dir, "--")==0 && argc>=3) dir = argv[2]; + + Echroot("."); + Echdir("/"); + + Eumount2(dir, 0); + return EXIT_SUCCESS; +} diff --git a/util-vserver/src/stack-start.h b/util-vserver/src/stack-start.h new file mode 100644 index 0000000..53aa8c6 --- /dev/null +++ b/util-vserver/src/stack-start.h @@ -0,0 +1,28 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef H_UTIL_VSERVER_SRC_STACK_START_H +#define H_UTIL_VSERVER_SRC_STACK_START_H + +#ifdef HAVE_GROWING_STACK +# define STACK_START(PTR) (PTR) +#else +# define STACK_START(PTR) ((PTR)+sizeof(PTR)/sizeof(PTR[0])) +#endif + +#endif // H_UTIL_VSERVER_SRC_STACK_START_H diff --git a/util-vserver/src/wrappers-vserver.h b/util-vserver/src/wrappers-vserver.h new file mode 100644 index 0000000..a01eb04 --- /dev/null +++ b/util-vserver/src/wrappers-vserver.h @@ -0,0 +1,32 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef H_UTIL_VSERVER_SRC_WRAPPERS_VSERVER_H +#define H_UTIL_VSERVER_SRC_WRAPPERS_VSERVER_H + +#include "wrappers.h" +#include + +inline static UNUSED void +Evc_new_s_context(ctx_t ctx, unsigned int remove_cap, unsigned int flags) +{ + FatalErrnoError(vc_new_s_context(ctx,remove_cap,flags)==-1, + "vc_new_s_context()"); +} + +#endif // H_UTIL_VSERVER_SRC_WRAPPERS_VSERVER_H diff --git a/util-vserver/src/wrappers.h b/util-vserver/src/wrappers.h new file mode 100644 index 0000000..319b7c8 --- /dev/null +++ b/util-vserver/src/wrappers.h @@ -0,0 +1,174 @@ +// $Id$ --*- c++ -*-- + +// Copyright (C) 2003 Enrico Scholz +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; version 2 of the License. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + +#ifndef H_UTIL_VSERVER_SRC_WRAPPERS_H +#define H_UTIL_VSERVER_SRC_WRAPPERS_H + +#include "compat.h" +#include "compat-pivot_root.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WRAPPER_DECL UNUSED ALWAYSINLINE + +static UNUSED void +FatalErrnoError(bool condition, char const msg[]) /*@*/ +{ + if (!condition) return; + perror(msg); + + extern int wrapper_exit_code; + exit(wrapper_exit_code); +} + +inline static WRAPPER_DECL void +Eclose(int s) +{ + FatalErrnoError(close(s)==-1, "close()"); +} + +inline static WRAPPER_DECL void +Echdir(char const path[]) +{ + FatalErrnoError(chdir(path)==-1, "chdir()"); +} + +inline static WRAPPER_DECL void +Efchdir(int fd) +{ + FatalErrnoError(fchdir(fd)==-1, "fchdir()"); +} + +inline static WRAPPER_DECL void +Echroot(char const path[]) +{ + FatalErrnoError(chroot(path)==-1, "chroot()"); +} + +inline static WRAPPER_DECL void +Eexecv(char const *path, char *argv[]) +{ + FatalErrnoError(execv(path,argv)==-1, "execv()"); +} + +inline static WRAPPER_DECL int +Eopen(char const *fname, int flags, mode_t mode) +{ + int res = open(fname, flags, mode); + FatalErrnoError(res==-1, "open()"); + + return res; +} + +inline static WRAPPER_DECL void +Eumount2(char const *path, int flag) +{ + FatalErrnoError(umount2(path,flag)==-1, "umount2()"); +} + +inline static WRAPPER_DECL void +Emount(const char *source, const char *target, + const char *filesystemtype, unsigned long mountflags, + const void *data) +{ + FatalErrnoError(mount(source, target, filesystemtype, + mountflags, data)==-1, "mount()"); +} + +inline static WRAPPER_DECL void +Emkdir(const char *pathname, mode_t mode) +{ + FatalErrnoError(mkdir(pathname,mode)==-1, "mkdir()"); +} + +inline static WRAPPER_DECL void +Epivot_root(const char *new_root, const char *put_old) +{ + FatalErrnoError(pivot_root(new_root, put_old)==-1, "pivot_root()"); +} + +inline static WRAPPER_DECL pid_t +Eclone(int (*fn)(void *), void *child_stack, int flags, void *arg) +{ + pid_t res; +#ifndef __dietlibc__ + res = clone(fn, child_stack, flags, arg); +#else + res = clone((void*(*)(void*))(fn), child_stack, flags, arg); +#endif + FatalErrnoError(res==-1, "clone()"); + return res; +} + + +inline static WRAPPER_DECL pid_t +Ewait4(pid_t pid, int *status, int options, + struct rusage *rusage) +{ + pid_t res; + res = wait4(pid, status, options, rusage); + FatalErrnoError(res==-1, "wait4()"); + return res; +} + +inline static WRAPPER_DECL void +Epipe(int filedes[2]) +{ + FatalErrnoError(pipe(filedes)==-1, "pipe()"); +} + +inline static WRAPPER_DECL pid_t +Efork() +{ + pid_t res; + res = fork(); + FatalErrnoError(res==-1, "fork()"); + return res; +} + +inline static WRAPPER_DECL size_t +Eread(int fd, void *ptr, size_t len) +{ + size_t res = read(fd, ptr, len); + FatalErrnoError((ssize_t)(res)==-1, "read()"); + + return res; +} + +inline static WRAPPER_DECL size_t +Ewrite(int fd, void const *ptr, size_t len) +{ + size_t res = write(fd, ptr, len); + FatalErrnoError((ssize_t)(res)==-1, "write()"); + + return res; +} + +#undef WRAPPER_DECL + +#endif // H_UTIL_VSERVER_SRC_WRAPPERS_H