5f3e3129055a5ce9bf82dba5a7f05ac89be62087
[util-vserver.git] / util-vserver / src / capchroot.c
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 <stdio.h>
31 #include <string.h>
32 #include <pwd.h>
33 #include <grp.h>
34 #include <errno.h>
35 #include <unistd.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38
39 #include "linuxcaps.h"
40 #include "vserver.h"
41
42 static int my_chroot(const char *dir)
43 {
44         int ret = -1;
45         if (has_chrootsafe()){
46                 ret = call_chrootsafe(dir);
47         }else{
48             //fprintf (stderr,"Kernel do not support chrootsafe(), using chroot()\n");
49                 ret = chroot (dir);
50         }
51         return ret;
52 }
53
54 int main (int argc, char *argv[])
55 {
56         if (argc < 3){
57                 fprintf (stderr,"capchroot version %s\n",VERSION);
58                 fprintf (stderr
59                         ,"capchroot --nochroot directory [ --suid user ] command argument\n"
60                          "\n"
61                          "--nochroot remove the CAP_SYS_CHROOT capability\n"
62                          "           after the chroot system call.\n"
63                          "--suid switch to a different user (in the vserver context)\n"
64                          "       before executing the command.\n");
65         }else{
66                 const char *uid = NULL;
67                 bool nochroot = false;
68                 int dir;
69                 for (dir=1; dir<argc; dir++){
70                         const char *arg = argv[dir];
71                         if (arg[0] != '-' && arg[1] != '-'){
72                                 break;
73                         }else if (strcmp(arg,"--nochroot")==0){
74                                 nochroot = true;
75                         }else if (strcmp(arg,"--suid")==0){
76                                 dir++;
77                                 uid = argv[dir];
78                         }
79                         
80                 }
81                 // We resolve the UID before doing the chroot.
82                 // If we do the getpwnam after the chroot, we will end
83                 // up loading shared object from the vserver.
84                 // This is causing two kind of problem: Incompatibilities
85                 // and also a security flaw. The shared objects in the vserver
86                 // may be tweaked to get control of the root server ...
87                 getpwnam ("root");
88                 if (my_chroot (argv[dir]) == -1){
89                         fprintf (stderr,"Can't chroot to directory %s (%s)\n",argv[dir]
90                                 ,strerror(errno));
91                 }else{
92                         struct passwd *p = NULL;
93                         int cmd          = dir + 1;
94
95                         if (nochroot){
96                                 call_new_s_context (0,NULL,1<<CAP_SYS_CHROOT,0);
97                         }
98
99                         if (uid != NULL && strcmp(uid,"root")!=0){
100                                 p = getpwnam(uid);
101                                 if (p == NULL){
102                                         fprintf (stderr,"User not found: %s\n",uid);
103                                         exit (-1);
104                                 }
105                         }
106                         if (p != NULL) {
107                                 setgroups (0,NULL);
108                                 setgid(p->pw_gid);
109                                 setuid(p->pw_uid);
110                         }
111                         if (cmd >= argc){
112                                 fprintf (stderr,"capchroot: No command to execute, do nothing\n");
113                         }else{
114                                 execvp (argv[cmd],argv+cmd);
115                                 fprintf (stderr,"Can't execute %s (%s)\n",argv[cmd]
116                                         ,strerror(errno));
117                         }
118                 }
119         }
120         return -1;
121 }
122
123