f6c63b7c2750a34e8d2ccaac1a2a3976e95783b8
[util-vserver-pl.git] / src / vserver_suid_wrapper.c
1 /* Suid wrapper for the vserver shell script. This code checks and ensures
2    that it may only be called by /usr/sbin/vsh. All safety checks need to be implemented
3    in vsh */
4
5 #include <unistd.h>
6 #include <sys/types.h>
7 #include <sys/stat.h>
8 #include <stdio.h>
9 #include <errno.h>
10
11 typedef enum CREDS { CREDS_OK, CREDS_BAD, CREDS_ERR } creds_t;
12
13 /* Ensure that the pid corresponds to the vsh executable, which
14  * transfers users from root to slice context. */
15
16 #define VSH_PATH    "/usr/sbin/vsh"
17 #ifndef PATH_MAX
18 #define PATH_MAX    4096
19 #endif
20
21 creds_t get_pid_creds(int pid) {
22     char exe_link_path[PATH_MAX], exe_path[PATH_MAX];
23     snprintf(exe_link_path,PATH_MAX - 1, "/proc/%d/exe", pid);
24     if (readlink(exe_link_path, exe_path, PATH_MAX-1) == -1) 
25         return CREDS_ERR;
26     else if (strncmp(exe_path, VSH_PATH, sizeof(VSH_PATH)) != 0) 
27         return CREDS_BAD;
28     else 
29         return CREDS_OK;
30 }
31
32 #define VSERVER_PATH    "/usr/sbin/vserver"
33
34 int main(int argc, char **argv, char **environment)
35 {
36     environment = (char **) NULL;
37
38     int ppid = getppid();
39     creds_t caller_creds;
40
41     if (ppid == -1)
42         goto out_exception;
43
44     caller_creds = get_pid_creds(ppid);  
45
46     if (caller_creds == CREDS_BAD) {
47         errno = EPERM;
48         goto out_exception;
49     }
50     else if (caller_creds == CREDS_ERR)
51         goto out_exception;
52
53     if (setuid(geteuid()))
54         goto out_exception;
55
56     system(VSERVER_PATH, argv, environment);
57     return 0;
58
59
60 out_exception:
61     printf("%s\n", strerror(errno));
62     return errno;
63 }