/* Suid wrapper for the vserver shell script. This code checks and ensures that it may only be called by /usr/sbin/vsh. All safety checks need to be implemented in vsh */ #include #include #include #include #include typedef enum CREDS { CREDS_OK, CREDS_BAD, CREDS_ERR } creds_t; /* Ensure that the pid corresponds to the vsh executable, which * transfers users from root to slice context. */ #define VSH_PATH "/usr/sbin/vsh" #ifndef PATH_MAX #define PATH_MAX 4096 #endif creds_t get_pid_creds(int pid) { char exe_link_path[PATH_MAX], exe_path[PATH_MAX]; snprintf(exe_link_path,PATH_MAX - 1, "/proc/%d/exe", pid); if (readlink(exe_link_path, exe_path, PATH_MAX-1) == -1) return CREDS_ERR; else if (strncmp(exe_path, VSH_PATH, sizeof(VSH_PATH)) != 0) return CREDS_BAD; else return CREDS_OK; } #define VSERVER_PATH "/usr/sbin/vserver" int main(int argc, char **argv, char **environment) { environment = (char **) NULL; int ppid = getppid(); creds_t caller_creds; if (ppid == -1) goto out_exception; caller_creds = get_pid_creds(ppid); if (caller_creds == CREDS_BAD) { errno = EPERM; goto out_exception; } else if (caller_creds == CREDS_ERR) goto out_exception; if (setuid(geteuid())) goto out_exception; execve(VSERVER_PATH, argv, environment); return 0; out_exception: printf("%s\n", strerror(errno)); return errno; }