From: Sapan Bhatia Date: Tue, 1 Dec 2009 23:14:59 +0000 (+0000) Subject: Replacing vsh to use the new version. X-Git-Url: http://git.onelab.eu/?p=util-vserver-pl.git;a=commitdiff_plain;h=ac248ea2cbaab3a8603de303d7fb3265e6d7195d Replacing vsh to use the new version. --- diff --git a/src/vserver_suid_wrapper.c b/src/vserver_suid_wrapper.c deleted file mode 100644 index 8aca65e..0000000 --- a/src/vserver_suid_wrapper.c +++ /dev/null @@ -1,61 +0,0 @@ -/* 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); - -out_exception: - printf("%s\n", strerror(errno)); - return errno; -} diff --git a/src/vsh.c b/src/vsh.c index 9a23505..71698c1 100644 --- a/src/vsh.c +++ b/src/vsh.c @@ -1,348 +1,83 @@ -/* - * Marc E. Fiuczynski - * - * 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. - */ +/* Version 2 of vsh. Basically a wrapper around 'vserver enter.' */ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include -#include -#include #include -#include -#include -#include -#include +#include +#include #include #include -#include -#include -#include -#include - -//-------------------------------------------------------------------- -#include -#include "planetlab.h" - -/* Change to root:root (before entering new context) */ -static int setuidgid_root() -{ - if (setgid(0) < 0) { - PERROR("setgid(0)"); - return -1; - } - if (setuid(0) < 0) { - PERROR("setuid(0)"); - return -1; - } - return 0; -} - -static void compute_new_root(char *base, char **root, const struct passwd *pwd) -{ - int root_len; - - root_len = - strlen(base) + strlen("/") + - strlen(pwd->pw_name) + NULLBYTE_SIZE; - (*root) = (char *)malloc(root_len); - if ((*root) == NULL) { - PERROR("malloc(%d)", root_len); - exit(1); - } - - sprintf((*root), "%s/%s", base, pwd->pw_name); - (*root)[root_len - 1] = '\0'; -} - -static int sandbox_chroot(const struct passwd *pwd) -{ - char *sandbox_root = NULL; - - compute_new_root(DEFAULT_VSERVERDIR,&sandbox_root, pwd); - if (chroot(sandbox_root) < 0) { - PERROR("chroot(%s)", sandbox_root); - exit(1); - } - if (chdir("/") < 0) { - PERROR("chdir(/)"); - exit(1); - } - return 0; -} - -static int sandbox_processes(xid_t ctx, const char *context, const struct passwd *pwd) -{ -#ifdef CONFIG_VSERVER_LEGACY - int flags; - - flags = 0; - flags |= 1; /* VX_INFO_LOCK -- cannot request a new vx_id */ - /* flags |= 4; VX_INFO_NPROC -- limit number of procs in a context */ - - (void) vc_new_s_context(ctx, 0, flags); - - /* use legacy dirty hack for capremove */ - if (vc_new_s_context(VC_SAMECTX, vc_get_insecurebcaps(), flags) == VC_NOCTX) { - PERROR("vc_new_s_context(%u, 0x%16llx, 0x%08x)", - VC_SAMECTX, vc_get_insecurebcaps(), flags); - exit(1); - } -#else - int ctx_is_new; - struct sliver_resources slr; - char hostname[HOST_NAME_MAX+1]; - int unshare_netns; - - pl_get_limits(context,&slr); - - if (gethostname(hostname, sizeof hostname) == -1) - { - PERROR("gethostname(...)"); - exit(1); - } - - /* check whether the slice has been suspended */ - if (slr.vs_cpu==0) - { - fprintf(stderr, "*** %s: %s has zero cpu resources and presumably it has been disabled/suspended ***\n", hostname, context); - exit(0); - } - - unshare_netns = pl_unshare_netns(ctx); - - (void) (sandbox_chroot(pwd)); +#include +#include +#include - if ((ctx_is_new = pl_chcontext(ctx, ~vc_get_insecurebcaps(),&slr, - unshare_netns)) < 0) - { - PERROR("pl_chcontext(%u)", ctx); - exit(1); - } - if (ctx_is_new) - { - fprintf(stderr, " *** %s: %s has not been started yet, please check back later ***\n", hostname, context); - exit(1); - } +#define VSH_PATH "/usr/sbin/vsh" +#ifndef PATH_MAX +#define PATH_MAX 4096 #endif - return 0; -} +#define VSERVER_PATH "/usr/sbin/vserver" -void runas_slice_user(struct passwd *pwd) +char* get_current_username (unsigned int uid) { - char *username = pwd->pw_name; - char *home_env, *logname_env, *mail_env, *shell_env, *user_env; - int home_len, logname_len, mail_len, shell_len, user_len; - static char *envp[10]; - - if (setgid(pwd->pw_gid) < 0) { - PERROR("setgid(%d)", pwd->pw_gid); - exit(1); - } - - if (setuid(pwd->pw_uid) < 0) { - PERROR("setuid(%d)", pwd->pw_uid); - exit(1); - } - - if (chdir(pwd->pw_dir) < 0) { - PERROR("chdir(%s)", pwd->pw_dir); - exit(1); - } - - home_len = strlen("HOME=") + strlen(pwd->pw_dir) + NULLBYTE_SIZE; - logname_len = strlen("LOGNAME=") + strlen(username) + NULLBYTE_SIZE; - mail_len = strlen("MAIL=/var/spool/mail/") + strlen(username) - + NULLBYTE_SIZE; - shell_len = strlen("SHELL=") + strlen(pwd->pw_shell) + NULLBYTE_SIZE; - user_len = strlen("USER=") + strlen(username) + NULLBYTE_SIZE; - - home_env = (char *)malloc(home_len); - logname_env = (char *)malloc(logname_len); - mail_env = (char *)malloc(mail_len); - shell_env = (char *)malloc(shell_len); - user_env = (char *)malloc(user_len); - - if ((home_env == NULL) || - (logname_env == NULL) || - (mail_env == NULL) || - (shell_env == NULL) || - (user_env == NULL)) { - PERROR("malloc"); - exit(1); - } - - sprintf(home_env, "HOME=%s", pwd->pw_dir); - sprintf(logname_env, "LOGNAME=%s", username); - sprintf(mail_env, "MAIL=/var/spool/mail/%s", username); - sprintf(shell_env, "SHELL=%s", pwd->pw_shell); - sprintf(user_env, "USER=%s", username); - - home_env[home_len - 1] = '\0'; - logname_env[logname_len - 1] = '\0'; - mail_env[mail_len - 1] = '\0'; - shell_env[shell_len - 1] = '\0'; - user_env[user_len - 1] = '\0'; - - envp[0] = home_env; - envp[1] = logname_env; - envp[2] = mail_env; - envp[3] = shell_env; - envp[4] = user_env; - envp[5] = 0; + struct passwd *passwd_entry; + if ((passwd_entry = getpwuid(uid)) == NULL) { + fprintf(stderr, "Could not look up user record for %d\n", uid); + return NULL; + } - if ((putenv(home_env) < 0) || - (putenv(logname_env) < 0) || - (putenv(mail_env) < 0) || - (putenv(shell_env) < 0) || - (putenv(user_env) < 0)) { - PERROR("vserver: putenv error "); - exit(1); - } + return (strdup(passwd_entry->pw_name)); } -void slice_enter(struct passwd *pwd) -{ - if (setuidgid_root() < 0) { /* For chroot, new_s_context */ - fprintf(stderr, "vsh: Could not become root, check that SUID flag is set on binary\n"); - exit(2); - } +char **extend_argv(int argc, char **argv, int num_extra_args) { + int argc2, i; + char **argv2; -#ifdef CONFIG_VSERVER_LEGACY - (void) (sandbox_chroot(pwd)); -#endif + argc2 = argc + num_extra_args; + argv2 = (char **) malloc(argc2 * sizeof(char *)); - if (sandbox_processes((xid_t) pwd->pw_uid, pwd->pw_name, pwd) < 0) { - fprintf(stderr, "vsh: Could not change context to %d\n", pwd->pw_uid); - exit(2); - } -} + if (!argv2) + return (char **) NULL; -//-------------------------------------------------------------------- + for (i=0; ipw_name); - if (!context) { - PERROR("strdup"); - exit(2); - } - - /* enter vserver "context" */ - slice_enter(prechroot); - - /* Get the /etc/passwd entry for this user, this time inside - * the chroot. - */ - username = context; - - pwdBuffer_len = sysconf(_SC_GETPW_R_SIZE_MAX); - if (pwdBuffer_len == -1) { - PERROR("sysconf(_SC_GETPW_R_SIZE_MAX"); - exit(1); - } - pwdBuffer = (char*)malloc(pwdBuffer_len); - if (pwdBuffer == NULL) { - PERROR("malloc(%d)", pwdBuffer_len); - exit(1); - } - - errno = 0; - if ((getpwnam_r(username,postchroot,pwdBuffer,pwdBuffer_len, &result) != 0) || - (errno != 0) || result != postchroot) { - PERROR("getpwnam_r(%s)", username); - exit(1); - } - - /* 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. - */ - runas_slice_user(postchroot); - - /* Make sure pw->pw_shell is non-NULL.*/ - if (postchroot->pw_shell == NULL || postchroot->pw_shell[0] == '\0') { - postchroot->pw_shell = (char *) DEFAULT_SHELL; + char *slice_name; + char **argv2; + int argc2; + char slice_id_str[256]; + unsigned int slice_xid; + + slice_xid = getuid(); + slice_name = get_current_username(slice_xid); + if (!slice_name) { + fprintf(stderr,"Could not look up slice name\n"); + goto out_exception; } + + argv2 = extend_argv(argc, argv, NUM_VSERVER_SUEXEC_ARGS); + if (!argv2) goto out_exception; + + + // Populate arguments + snprintf(slice_id_str, 255, "%u", slice_xid); + argv2[0] = strdup(VSERVER_PATH); + argv2[1] = strdup(slice_name); + argv2[2] = strdup("suexec"); + argv2[3] = strdup(slice_id_str); + argv2[4] = strdup("/bin/sh"); - shell = (char *)strdup(postchroot->pw_shell); - if (!shell) { - PERROR("strdup"); - exit(2); - } + if (setuid(geteuid())) goto out_exception; - /* 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("malloc(%d)", sizeof(char*)*(argc+2)); - exit(1); - } - args[0] = argv[0]; - args[1] = "-l"; - for(i=1;i