X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=src%2Fcapchroot.c;fp=src%2Fcapchroot.c;h=69dbe3725fdbf6d33bedd5b6286b1424fec2b818;hb=8cf13bb177d92c93eb73dc8939777150536c2d00;hp=5b8d738677b41cfa3f92b4f62231ff8f955c44c9;hpb=6bf3f95de36c804c97716b2d0bdf10680c559044;p=util-vserver.git diff --git a/src/capchroot.c b/src/capchroot.c index 5b8d738..69dbe37 100644 --- a/src/capchroot.c +++ b/src/capchroot.c @@ -1,4 +1,4 @@ -// $Id: capchroot.c,v 1.1.4.2 2003/11/28 23:08:43 ensc Exp $ +// $Id: capchroot.c,v 1.7 2004/03/24 01:41:28 ensc Exp $ // Copyright (C) 2003 Enrico Scholz // based on capchroot.cc by Jacques Gelinas @@ -22,10 +22,13 @@ system call is executed, it (option) remove the CAP_SYS_CHROOT capability. Then it executes its argument */ + #ifdef HAVE_CONFIG_H # include #endif -#include "compat.h" + +#include "vserver.h" +#include "util.h" #include #include @@ -35,77 +38,127 @@ #include #include #include +#include +#include -#include "linuxcaps.h" -#include "vserver.h" +#define ENSC_WRAPPERS_PREFIX "capchroot: " +#define ENSC_WRAPPERS_UNISTD 1 +#define ENSC_WRAPPERS_VSERVER 1 +#include -int main (int argc, char *argv[]) +#define CMD_HELP 0x1000 +#define CMD_VERSION 0x1001 +#define CMD_NOCHROOT 0x2000 +#define CMD_SUID 0x2001 + +int wrapper_exit_code = 255; + +static struct option const +CMDLINE_OPTIONS[] = { + { "help", no_argument, 0, CMD_HELP }, + { "version", no_argument, 0, CMD_VERSION }, + { "nochroot", no_argument, 0, CMD_NOCHROOT }, + { "suid", required_argument, 0, CMD_SUID }, + {0,0,0,0} +}; + +static void +showHelp(int fd, char const *cmd, int res) +{ + VSERVER_DECLARE_CMD(cmd); + WRITE_MSG(fd, "Usage: "); + WRITE_STR(fd, cmd); + WRITE_MSG(fd, + " --nochroot [--suid ] [--] *\n" + "\n" + "Options:\n" + " --nochroot ... remove the CAP_SYS_CHROOT capability\n" + " after the chroot system call.\n" + " --suid ... switch to a different user (in the vserver\n" + " context) before executing the command.\n" + "\n" + "Please report bugs to " PACKAGE_BUGREPORT "\n"); + exit(res); +} + +static void +showVersion() { - 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; dirpw_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; + WRITE_MSG(1, + "capchroot " VERSION " -- a capability aware chroot\n" + "This program is part of " PACKAGE_STRING "\n\n" + "Copyright (C) 2004 Enrico Scholz\n" + VERSION_COPYRIGHT_DISCLAIMER); + exit(0); +} + +static void +setUser(char const *user) +{ + struct passwd *p = 0; + if (user!=0 && strcmp(user, "root")!=0) { + errno = 0; + p = getpwnam(user); + if (p==0) { + if (errno==0) errno = ENOENT; + PERROR_Q(ENSC_WRAPPERS_PREFIX "getpwnam", user); + exit(wrapper_exit_code); + } + } + + if (p!=0) { + Esetgroups(1, &p->pw_gid); + Esetgid(p->pw_gid); + Esetuid(p->pw_uid); + + if (getuid()!=p->pw_uid || getgid()!=p->pw_gid) { + WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Something went wrong while changing uid; expected uid/gid do not match the actual one\n"); + exit(wrapper_exit_code); + } + } } + +int main (int argc, char *argv[]) +{ + bool nochroot = false; + char const * suid_user = 0; + + while (1) { + int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); + if (c==-1) break; + switch (c) { + case CMD_HELP : showHelp(1, argv[0], 0); + case CMD_VERSION : showVersion(); + case CMD_NOCHROOT : nochroot = true; break; + case CMD_SUID : suid_user = optarg; break; + default : + WRITE_MSG(2, "Try '"); + WRITE_STR(2, argv[0]); + WRITE_MSG(2, " --help\" for more information.\n"); + return EXIT_FAILURE; + break; + } + } + if (optind==argc) + WRITE_MSG(2, "No directory specified; try '--help' for more information\n"); + else if (optind+1==argc) + WRITE_MSG(2, "No command specified; try '--help' for more information\n"); + else { + // 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"); + Echroot(argv[optind]); + if (nochroot) + Evc_new_s_context(VC_SAMECTX, 1<