capchroot.c (5106B)
1 // $Id$ 2 3 // Copyright (C) 2003 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de> 4 // based on capchroot.cc by Jacques Gelinas 5 // 6 // This program is free software; you can redistribute it and/or modify 7 // it under the terms of the GNU General Public License as published by 8 // the Free Software Foundation; either version 2, or (at your option) 9 // any later version. 10 // 11 // This program is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 // 16 // You should have received a copy of the GNU General Public License 17 // along with this program; if not, write to the Free Software 18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 20 /* 21 This chroot command does very little. Once the chroot 22 system call is executed, it (option) remove the CAP_SYS_CHROOT 23 capability. Then it executes its argument 24 */ 25 26 #ifdef HAVE_CONFIG_H 27 # include <config.h> 28 #endif 29 30 #include "vserver.h" 31 #include "util.h" 32 33 #include <stdio.h> 34 #include <string.h> 35 #include <pwd.h> 36 #include <grp.h> 37 #include <errno.h> 38 #include <unistd.h> 39 #include <stdbool.h> 40 #include <stdlib.h> 41 #include <getopt.h> 42 #include <libgen.h> 43 44 #define ENSC_WRAPPERS_PREFIX "capchroot: " 45 #define ENSC_WRAPPERS_UNISTD 1 46 #define ENSC_WRAPPERS_VSERVER 1 47 #include <wrappers.h> 48 49 #define CMD_HELP 0x1000 50 #define CMD_VERSION 0x1001 51 #define CMD_NOCHROOT 0x2000 52 #define CMD_SUID 0x2001 53 54 int wrapper_exit_code = 255; 55 56 static struct option const 57 CMDLINE_OPTIONS[] = { 58 { "help", no_argument, 0, CMD_HELP }, 59 { "version", no_argument, 0, CMD_VERSION }, 60 { "nochroot", no_argument, 0, CMD_NOCHROOT }, 61 { "suid", required_argument, 0, CMD_SUID }, 62 {0,0,0,0} 63 }; 64 65 static void 66 showHelp(int fd, char const *cmd, int res) 67 { 68 VSERVER_DECLARE_CMD(cmd); 69 70 #if !defined(VC_ENABLE_API_COMPAT) && !defined(VC_ENABLE_API_LEGACY) 71 WRITE_MSG(1, "ERROR: tools were built without legacy API support; capchroot will not work!\n\n"); 72 #endif 73 74 WRITE_MSG(fd, "Usage: "); 75 WRITE_STR(fd, cmd); 76 WRITE_MSG(fd, 77 " --nochroot [--suid <user>] [--] <directory> <command> <args>*\n" 78 "\n" 79 "Options:\n" 80 " --nochroot ... remove the CAP_SYS_CHROOT capability\n" 81 " after the chroot system call.\n" 82 " --suid <user> ... switch to a different user (in the vserver\n" 83 " context) before executing the command.\n" 84 "\n" 85 "Please report bugs to " PACKAGE_BUGREPORT "\n"); 86 exit(res); 87 } 88 89 static void 90 showVersion() 91 { 92 WRITE_MSG(1, 93 "capchroot " VERSION " -- a capability aware chroot\n" 94 "This program is part of " PACKAGE_STRING "\n\n" 95 "Copyright (C) 2004 Enrico Scholz\n" 96 VERSION_COPYRIGHT_DISCLAIMER); 97 exit(0); 98 } 99 100 static UNUSED void 101 setUser(char const *user) 102 { 103 struct passwd *p = 0; 104 if (user!=0 && strcmp(user, "root")!=0 && strcmp(user, "0")!=0) { 105 errno = 0; 106 p = getpwnam(user); 107 if (p==0) { 108 if (errno==0) errno = ENOENT; 109 PERROR_Q(ENSC_WRAPPERS_PREFIX "getpwnam", user); 110 exit(wrapper_exit_code); 111 } 112 } 113 114 if (p!=0) { 115 Esetgroups(1, &p->pw_gid); 116 Esetgid(p->pw_gid); 117 Esetuid(p->pw_uid); 118 119 if (getuid()!=p->pw_uid || getgid()!=p->pw_gid) { 120 WRITE_MSG(2, ENSC_WRAPPERS_PREFIX "Something went wrong while changing uid; expected uid/gid do not match the actual one\n"); 121 exit(wrapper_exit_code); 122 } 123 } 124 } 125 126 int main (int argc, char *argv[]) 127 { 128 bool nochroot = false; 129 char const * suid_user = 0; 130 131 while (1) { 132 int c = getopt_long(argc, argv, "+", CMDLINE_OPTIONS, 0); 133 if (c==-1) break; 134 135 switch (c) { 136 case CMD_HELP : showHelp(1, argv[0], 0); 137 case CMD_VERSION : showVersion(); 138 case CMD_NOCHROOT : nochroot = true; break; 139 case CMD_SUID : suid_user = optarg; break; 140 default : 141 WRITE_MSG(2, "Try '"); 142 WRITE_STR(2, argv[0]); 143 WRITE_MSG(2, " --help' for more information.\n"); 144 return EXIT_FAILURE; 145 break; 146 } 147 } 148 149 #if defined(VC_ENABLE_API_COMPAT) || defined(VC_ENABLE_API_LEGACY) 150 if (optind==argc) 151 WRITE_MSG(2, "No directory specified; try '--help' for more information\n"); 152 else if (optind+1==argc) 153 WRITE_MSG(2, "No command specified; try '--help' for more information\n"); 154 else { 155 // We resolve the UID before doing the chroot. 156 // If we do the getpwnam after the chroot, we will end 157 // up loading shared object from the vserver. 158 // This is causing two kind of problem: Incompatibilities 159 // and also a security flaw. The shared objects in the vserver 160 // may be tweaked to get control of the root server ... 161 getpwnam("root"); 162 Echroot(argv[optind]); 163 if (nochroot) 164 Evc_new_s_context(VC_SAMECTX, 1<<VC_CAP_SYS_CHROOT,0); 165 setUser(suid_user); 166 EexecvpD(argv[optind+1], argv+optind+1); 167 } 168 #else 169 WRITE_MSG(2, "capchroot: tools were built without legacy API support; can not continue\n"); 170 #endif 171 172 return EXIT_FAILURE; 173 }