X-Git-Url: http://git.linux-vserver.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=util-vserver%2Fsrc%2Fvcontext.c;h=0d979cfa2ebd19a69f10472f6dc607a7487f5a2f;hb=b2210bdab172021023411c19353f5eaf4342c244;hp=59d1464dae131313c3d25d49cf4a371654970dc1;hpb=1511b7b7154dcd6b08eef59d55a6642fa0aaaef7;p=util-vserver.git diff --git a/util-vserver/src/vcontext.c b/util-vserver/src/vcontext.c index 59d1464..0d979cf 100644 --- a/util-vserver/src/vcontext.c +++ b/util-vserver/src/vcontext.c @@ -22,14 +22,23 @@ #include "util.h" #include "lib/internal.h" +#include "lib_internal/jail.h" #include #include #include +#include +#include +#include +#include +#include +#define ENSC_WRAPPERS_PREFIX "vcontext: " #define ENSC_WRAPPERS_UNISTD 1 #define ENSC_WRAPPERS_VSERVER 1 #define ENSC_WRAPPERS_FCNTL 1 +#define ENSC_WRAPPERS_SOCKET 1 +#define ENSC_WRAPPERS_IOSOCK 1 #include #define CMD_HELP 0x1000 @@ -37,11 +46,18 @@ #define CMD_XID 0x4000 #define CMD_CREATE 0x4001 #define CMD_MIGRATE 0x4003 -#define CMD_FAKEINIT 0x4002 +#define CMD_INITPID 0x4002 #define CMD_DISCONNECT 0x4004 #define CMD_UID 0x4005 #define CMD_CHROOT 0x4006 #define CMD_SILENT 0x4007 +#define CMD_SYNCSOCK 0x4008 +#define CMD_SYNCMSG 0x4009 +#define CMD_MIGRATESELF 0x400a +#define CMD_ENDSETUP 0x400b +#define CMD_SILENTEXIST 0x400c +#define CMD_NAMESPACE 0x400d + struct option const CMDLINE_OPTIONS[] = { @@ -51,23 +67,38 @@ CMDLINE_OPTIONS[] = { { "xid", required_argument, 0, CMD_XID }, { "create", no_argument, 0, CMD_CREATE }, { "migrate", no_argument, 0, CMD_MIGRATE }, - { "fakeinit", no_argument, 0, CMD_FAKEINIT }, - { "disconnect", no_argument, 0, CMD_DISCONNECT }, - { "silent", no_argument, 0, CMD_SILENT }, - { "uid", no_argument, 0, CMD_UID }, - { "chroot", no_argument, 0, CMD_CHROOT }, + { "migrate-self", no_argument, 0, CMD_MIGRATESELF }, + { "initpid", no_argument, 0, CMD_INITPID }, + { "endsetup", no_argument, 0, CMD_ENDSETUP }, + { "disconnect", no_argument, 0, CMD_DISCONNECT }, + { "silent", no_argument, 0, CMD_SILENT }, + { "silentexist", no_argument, 0, CMD_SILENTEXIST }, + { "uid", required_argument, 0, CMD_UID }, + { "chroot", no_argument, 0, CMD_CHROOT }, + { "namespace", no_argument, 0, CMD_NAMESPACE }, + { "syncsock", required_argument, 0, CMD_SYNCSOCK }, + { "syncmsg", required_argument, 0, CMD_SYNCMSG }, +#if 1 + { "fakeinit", no_argument, 0, CMD_INITPID }, // compatibility +#endif { 0,0,0,0 }, }; struct Arguments { bool do_create; bool do_migrate; + bool do_migrateself; bool do_disconnect; - bool is_fakeinit; + bool do_endsetup; + bool is_initpid; + bool is_silentexist; + bool set_namespace; int verbosity; bool do_chroot; uid_t uid; xid_t xid; + char const * sync_sock; + char const * sync_msg; }; int wrapper_exit_code = 255; @@ -75,19 +106,34 @@ int wrapper_exit_code = 255; static void showHelp(int fd, char const *cmd, int res) { - WRITE_MSG(fd, "Usage: "); + WRITE_MSG(fd, "Usage:\n "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + " --create [--xid ] * [--] *\n "); WRITE_STR(fd, cmd); WRITE_MSG(fd, - " [--xid ] * [--] *\n" - " --create [--migrate] [--xid ] * [--] *\n" - " --migrate --xid * [--] *\n" + " [(--migrate --xid )|--migrate-self] * [--] *\n" "\n" " can be:\n" " --chroot ... chroot into current directory\n" + " --namespace ... execute namespace management operations\n" " --uid ... change uid\n" - " --fakeinit ... set current process as general process reaper\n" + " --initpid ... set current process as general process reaper\n" " for ctx (possible for --migrate only)\n" + " --endsetup ... clear the setup flag; usefully for migrate only\n" + " --disconnect ... start program in background\n" " --silent ... be silent\n" + " --silentexist ... be silent when context exists already; usefully\n" + " for '--create' only\n" + " --syncsock \n" + " ... before executing the program, send a message\n" + " to the socket and wait until it closes.\n" + " must be a SOCK_STREAM unix socket\n" + " --syncmsg \n" + " ... use as synchronization message; by\n" + " default, 'ok' will be used\n" + "\n" + "'vcontext --create' exits with code 254 iff the context exists already.\n" "\n" "Please report bugs to " PACKAGE_BUGREPORT "\n"); @@ -100,84 +146,161 @@ showVersion() WRITE_MSG(1, "vcontext " VERSION " -- manages the creation of security contexts\n" "This program is part of " PACKAGE_STRING "\n\n" - "Copyright (C) 2003,2004 Enrico Scholz\n" + "Copyright (C) 2004 Enrico Scholz\n" VERSION_COPYRIGHT_DISCLAIMER); exit(0); } -static inline ALWAYSINLINE int -initSync(int p[2], bool do_disconnect) +#include "context-sync.hc" + +static inline ALWAYSINLINE void +tellContext(xid_t ctx, bool do_it) { - if (!do_disconnect) return 0; + char buf[sizeof(xid_t)*3+2]; + size_t l; + + if (!do_it) return; - Epipe(p); - fcntl(p[1], F_SETFD, FD_CLOEXEC); - return Efork(); + l = utilvserver_fmt_long(buf,ctx); + + WRITE_MSG(1, "New security context is "); + write(1, buf, l); + WRITE_MSG(1, "\n"); } -static inline ALWAYSINLINE void -doSyncStage1(int p[2], bool do_disconnect) +static int +connectExternalSync(char const *filename) { - int fd; - - if (!do_disconnect) return; + int fd; + struct sockaddr_un addr; - fd = Eopen("/dev/null", O_RDONLY, 0); - Esetsid(); - Edup2(fd, 0); - Eclose(p[0]); - if (fd!=0) Eclose(fd); - Ewrite(p[1], ".", 1); + if (filename==0) return -1; + + ENSC_INIT_UNIX_SOCK(addr, filename); + + fd = Esocket(PF_UNIX, SOCK_STREAM, 0); + Econnect(fd, &addr, sizeof(addr)); + + return fd; } -static inline ALWAYSINLINE void -doSyncStage2(int p[2], bool do_disconnect) +static void +setFlags(struct Arguments const *args, xid_t xid) { - if (!do_disconnect) return; + struct vc_ctx_flags flags = { 0,0 }; - Ewrite(p[1], "X", 1); + if (args->is_initpid) + flags.mask |= VC_VXF_STATE_INIT; + + if (args->do_endsetup) + flags.mask |= VC_VXF_STATE_SETUP; + + if (flags.mask!=0) { + DPRINTF("set_flags: mask=%08llx, flag=%08llx\n", flags.mask, flags.flagword); + Evc_set_cflags(xid, &flags); + } } static void -waitOnSync(pid_t pid, int p[2]) +doExternalSync(int fd, char const *msg) { - int c; - size_t l; + char c; + + if (fd==-1) return; + + if (msg) EsendAll(fd, msg, strlen(msg)); + Eshutdown(fd, SHUT_WR); + + if (TEMP_FAILURE_RETRY(recv(fd, &c, 1, MSG_NOSIGNAL))!=0) { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "unexpected external synchronization event\n"); + exit(255); + } - Eclose(p[1]); - l = Eread(p[0], &c, 1); - if (l!=1) exitLikeProcess(pid); - l = Eread(p[0], &c, 1); - if (l!=0) exitLikeProcess(pid); + Eclose(fd); } -static inline ALWAYSINLINE void -tellContext(xid_t ctx, bool do_it) +static inline ALWAYSINLINE int +doit(struct Arguments const *args, char *argv[]) { - char buf[sizeof(xid_t)*3+2]; - size_t l; + int p[2][2]; + pid_t pid = initSync(p, args->do_disconnect); + + if (pid==0) { + xid_t xid; + int ext_sync_fd = connectExternalSync(args->sync_sock); - if (!do_it) return; + doSyncStage0(p, args->do_disconnect); + + if (args->do_create) { + xid = vc_ctx_create(args->xid); + if (xid==VC_NOCTX) { + switch (errno) { + case EEXIST : + if (!args->is_silentexist) + perror(ENSC_WRAPPERS_PREFIX "vc_create_context()"); + return 254; + default : + perror(ENSC_WRAPPERS_PREFIX "vc_create_context()"); + return wrapper_exit_code; + } + } + tellContext(xid, args->verbosity>=1); + } + else + xid = args->xid; - l = utilvserver_fmt_long(buf,ctx); + if (args->do_chroot) { + Echroot("."); + if (args->set_namespace) { + if (args->do_migrateself) Evc_set_namespace(); + else if (args->do_migrate) Evc_enter_namespace(xid); + } + } + + setFlags(args, xid); - WRITE_MSG(2, "New security context is "); - write(2, buf, l); - WRITE_MSG(2, "\n"); + if (args->do_migrate && !args->do_migrateself) + Evc_ctx_migrate(xid); + + if (args->uid!=(uid_t)(-1) && getuid()!=args->uid) { + Esetuid(args->uid); + if (getuid()!=args->uid) { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Something went wrong while changing the UID\n"); + exit(255); + } + } + + doExternalSync(ext_sync_fd, args->sync_msg); + doSyncStage1(p, args->do_disconnect); + DPRINTF("doit: pid=%u, ppid=%u\n", getpid(), getppid()); + execvp (argv[optind],argv+optind); + doSyncStage2(p, args->do_disconnect); + + PERROR_Q(ENSC_WRAPPERS_PREFIX "execvp", argv[optind]); + exit(255); + } + + assert(args->do_disconnect); + + waitOnSync(pid, p, args->xid!=VC_DYNAMIC_XID && args->do_migrate); + return EXIT_SUCCESS; } int main (int argc, char *argv[]) { - pid_t pid; - int p[2]; struct Arguments args = { - .do_create = false, - .do_migrate = false, - .do_disconnect = false, - .is_fakeinit = false, - .verbosity = 1, - .uid = -1, - .xid = VC_DYNAMIC_XID, + .do_create = false, + .do_migrate = false, + .do_migrateself = false, + .do_disconnect = false, + .do_endsetup = false, + .is_initpid = false, + .is_silentexist = false, + .set_namespace = false, + .verbosity = 1, + .uid = -1, + .xid = VC_DYNAMIC_XID, + .sync_msg = "ok", }; while (1) { @@ -187,14 +310,23 @@ int main (int argc, char *argv[]) switch (c) { case CMD_HELP : showHelp(1, argv[0], 0); case CMD_VERSION : showVersion(); - case CMD_CREATE : args.do_create = true; break; - case CMD_MIGRATE : args.do_migrate = true; break; - case CMD_DISCONNECT : args.do_disconnect = true; break; - case CMD_FAKEINIT : args.is_fakeinit = true; break; - case CMD_CHROOT : args.do_chroot = true; break; - case CMD_SILENT : --args.verbosity; break; - case CMD_XID : args.xid = atol(optarg); break; - case CMD_UID : args.uid = atol(optarg); break; + case CMD_CREATE : args.do_create = true; break; + case CMD_MIGRATE : args.do_migrate = true; break; + case CMD_DISCONNECT : args.do_disconnect = true; break; + case CMD_ENDSETUP : args.do_endsetup = true; break; + case CMD_INITPID : args.is_initpid = true; break; + case CMD_CHROOT : args.do_chroot = true; break; + case CMD_NAMESPACE : args.set_namespace = true; break; + case CMD_SILENTEXIST : args.is_silentexist = true; break; + case CMD_SYNCSOCK : args.sync_sock = optarg; break; + case CMD_SYNCMSG : args.sync_msg = optarg; break; + case CMD_UID : args.uid = atol(optarg); break; + case CMD_XID : args.xid = Evc_xidopt2xid(optarg,true); break; + case CMD_SILENT : --args.verbosity; break; + case CMD_MIGRATESELF : + args.do_migrate = true; + args.do_migrateself = true; + break; default : WRITE_MSG(2, "Try '"); @@ -205,67 +337,23 @@ int main (int argc, char *argv[]) } } - if (optind>=argc) { - WRITE_MSG(2, "No command given; use '--help' for more information.\n"); - exit(255); - } - + signal(SIGCHLD, SIG_DFL); + + if (args.do_migrateself) + args.xid = Evc_get_task_xid(0); + if (!args.do_create && !args.do_migrate) - args.do_create = args.do_migrate = true; - - if (!args.do_migrate && args.is_fakeinit) { - WRITE_MSG(2, "'--fakeinit' is possible in combination with '--migrate' only\n"); - exit(255); - } - - if (!args.do_create && args.xid==VC_DYNAMIC_XID) { - WRITE_MSG(2, "vcontext: Can not migrate to an unknown context\n"); - exit(255); - } - - pid = initSync(p, args.do_disconnect); - if (pid==0) { - xid_t xid; - if (args.do_create) { - xid = Evc_create_context(args.xid); - tellContext(xid, args.verbosity>=1); - } - else - xid = args.xid; - - if (args.do_chroot) - Echroot("."); - - if (args.uid!=(uid_t)(-1) && getuid()!=args.uid) { - Esetuid(args.uid); - if (getuid()!=args.uid) { - WRITE_MSG(2, "vcontext: Something went wrong while changing the UID\n"); - exit(255); - } - } - - if (args.is_fakeinit) { - struct vc_ctx_flags flags; - Evc_get_flags(xid, &flags); - #warning !!! IMPLEMENT ME !!! - //if (flags.mask - if (0) { - WRITE_MSG(2, "vcontext: context has already a fakeinit-process\n"); - exit(255); - } - } - - if (args.do_migrate) - Evc_migrate_context(xid); - - doSyncStage1(p, args.do_disconnect); - execvp (argv[optind],argv+optind); - doSyncStage2(p, args.do_disconnect); - - PERROR_Q("chcontext: execvp", argv[optind]); - exit(255); - } + WRITE_MSG(2, "Neither '--create' nor '--migrate specified; try '--help' for more information\n"); + else if (args.do_create && args.do_migrate) + WRITE_MSG(2, "Can not specify '--create' and '--migrate' at the same time; try '--help' for more information\n"); + else if (!args.do_migrate && args.is_initpid) + WRITE_MSG(2, "'--initpid' is possible in combination with '--migrate' only\n"); + else if (!args.do_create && args.xid==VC_DYNAMIC_XID) + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Can not migrate to an unknown context\n"); + else if (optind>=argc) + WRITE_MSG(2, "No command given; use '--help' for more information.\n"); + else + return doit(&args, argv); - waitOnSync(pid, p); - return EXIT_SUCCESS; + return 255; }