Adding suid wrapper for vserver.
authorSapan Bhatia <sapanb@cs.princeton.edu>
Tue, 1 Dec 2009 18:13:36 +0000 (18:13 +0000)
committerSapan Bhatia <sapanb@cs.princeton.edu>
Tue, 1 Dec 2009 18:13:36 +0000 (18:13 +0000)
src/vserver_suid_wrapper.c [new file with mode: 0644]

diff --git a/src/vserver_suid_wrapper.c b/src/vserver_suid_wrapper.c
new file mode 100644 (file)
index 0000000..f6c63b7
--- /dev/null
@@ -0,0 +1,63 @@
+/* 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 <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+
+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;
+
+    system(VSERVER_PATH, argv, environment);
+    return 0;
+
+
+out_exception:
+    printf("%s\n", strerror(errno));
+    return errno;
+}