A simple replacement for the "big" vsh that was used by PlanetLab 2.0.
authorMarc Fiuczynski <mef@cs.princeton.edu>
Fri, 17 Sep 2004 09:35:52 +0000 (09:35 +0000)
committerMarc Fiuczynski <mef@cs.princeton.edu>
Fri, 17 Sep 2004 09:35:52 +0000 (09:35 +0000)
Still need to address bind mount issues.

src/vsh.c [new file with mode: 0644]

diff --git a/src/vsh.c b/src/vsh.c
new file mode 100644 (file)
index 0000000..8290c8e
--- /dev/null
+++ b/src/vsh.c
@@ -0,0 +1,123 @@
+/*
+ * Marc E. Fiuczynski <mef@cs.princeton.edu>
+ *
+ * Copyright (c) 2004 The Trustees of Princeton University (Trustees).
+ *
+ * vsh is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * vsh is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Poptop; see the file COPYING.  If not, write to the Free
+ * Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <string.h>
+#include <errno.h>
+
+#define DEFAULT_SHELL "/bin/sh"
+
+/* Exit statuses for programs like 'env' that exec other programs.
+   EXIT_FAILURE might not be 1, so use EXIT_FAIL in such programs.  */
+enum
+{
+  EXIT_CANNOT_INVOKE = 126,
+  EXIT_ENOENT = 127
+};
+
+extern void slice_enter(char *);
+extern void runas_slice_user(char *);
+
+int main(int argc, char **argv)
+{
+    char *context, *username, *shell;
+    struct passwd   *pwd;
+    uid_t           uid;
+    int index, i;
+
+    if (argv[0][0]=='-') 
+      index = 1;
+    else
+      index = 0;
+
+    if ((uid = getuid()) < 0) {
+      perror("vsh: getuid error ");
+      exit(1);
+    }
+    if ((pwd = getpwuid(uid)) == NULL) {
+      fprintf(stderr,"vsh: getpwnam error failed for %d\n",uid); 
+      exit(1);
+    }
+
+    context = (char*)strdup(pwd->pw_name);
+    if (!context) {
+      perror("vsh: strdup failed");
+      exit(2);
+    }
+
+    /* enter vserver "context" */
+    slice_enter(context);
+
+    /* Now run as username in this context. Note that for PlanetLab's
+       vserver configuration the context name also happens to be the
+       "default" username within the vserver context.
+    */
+    username = context;
+    runas_slice_user(username);
+
+    /* With the uid/gid appropriately set. Let's figure out what the
+     * shell in the vserver's /etc/passwd is for the given username.
+     */
+    if ((pwd = getpwnam(username)) == NULL) {
+        fprintf(stderr,"vsh: getpwnam error failed for %s\n",username); 
+        exit(1);
+    }
+
+    /* Make sure pw->pw_shell is non-NULL.*/
+    if (pwd->pw_shell == NULL || pwd->pw_shell[0] == '\0') {
+      pwd->pw_shell = (char *) DEFAULT_SHELL;
+    }
+
+    shell = (char *)strdup(pwd->pw_shell);
+    if (!shell) {
+      perror("vsh: strdup failed");
+      exit(2);
+    }
+
+    /* Check whether 'su' or 'sshd' invoked us as a login shell or
+       not; did this above when testing argv[0]=='-'.
+    */
+    argv[0] = shell;
+    if (index == 1) {
+      char **args;
+      args = (char**)malloc(sizeof(char*)*(argc+2));
+      if (!args) {
+       perror("vsh: malloc failed");
+      }
+      args[0] = argv[0];
+      args[1] = "-l";
+      for(i=1;i<argc+1;i++) {
+       args[i+1] = argv[i];
+      }
+      argv = args;
+    }
+    (void) execvp(shell,argv);
+    {
+      int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
+      exit (exit_status);
+    }
+
+    return 0; /* shutup compiler */
+}