From 4c2db811c7f18fe1ed00ce9f37364cdde967367c Mon Sep 17 00:00:00 2001 From: Brian Bockelman Date: Sep 30 2011 20:45:34 +0000 Subject: Added the glexec-as-root patch. --- diff --git a/condor_glexec_as_root_v3.patch b/condor_glexec_as_root_v3.patch new file mode 100644 index 0000000..2dc2db4 --- /dev/null +++ b/condor_glexec_as_root_v3.patch @@ -0,0 +1,217 @@ +diff --git a/src/condor_starter.V6.1/glexec_privsep_helper.linux.cpp b/src/condor_starter.V6.1/glexec_privsep_helper.linux.cpp +index 0856c8f..42d02d2 100644 +--- a/src/condor_starter.V6.1/glexec_privsep_helper.linux.cpp ++++ b/src/condor_starter.V6.1/glexec_privsep_helper.linux.cpp +@@ -54,20 +54,31 @@ GLExecPrivSepHelper::~GLExecPrivSepHelper() + int + GLExecPrivSepHelper::proxy_valid_right_now() + { ++ ++ int result = TRUE; ++ /* Note that set_user_priv is a no-op if condor is running as ++ non-root (the "usual" mode for invoking glexec) */ ++ priv_state priv_saved = set_user_priv(); + if (!m_proxy) { + dprintf(D_FULLDEBUG, "GLExecPrivSepHelper::proxy_valid_right_now: no proxy defined\n"); +- return FALSE; ++ result = FALSE; + } else { ++ + time_t expiration_time = x509_proxy_expiration_time(m_proxy); + time_t now = time(NULL); + +- if (expiration_time < now) { +- dprintf(D_FULLDEBUG, "GLExecPrivSepHelper::proxy_valid_right_now: proxy %s already expired!\n", m_proxy); +- return FALSE; ++ if (expiration_time == -1) { ++ dprintf(D_FULLDEBUG, "GLExecPrivSepHelper::proxy_valid_right_now: Globus error when getting proxy %s expiration: %s.\n", m_proxy, x509_error_string()); ++ result = FALSE; ++ } else if (expiration_time < now) { ++ dprintf(D_FULLDEBUG, "GLExecPrivSepHelper::proxy_valid_right_now: proxy %s expired %ld seconds ago!\n", m_proxy, now - expiration_time); ++ result = FALSE; + } + } + +- return TRUE; ++ set_priv(priv_saved); ++ ++ return result; + } + + +@@ -79,17 +90,27 @@ GLExecPrivSepHelper::run_script(ArgList& args,MyString &error_desc) + return -1; + } + ++ /* Note that set_user_priv is a no-op if condor is running as ++ non-root (the "usual" mode for invoking glexec) */ ++ priv_state priv_saved = set_user_priv(); + FILE* fp = my_popen(args, "r", TRUE); ++ set_priv(priv_saved); + if (fp == NULL) { + dprintf(D_ALWAYS, + "GLExecPrivSepHelper::run_script: " +- "my_popen failure on %s\n", +- args.GetArg(0)); ++ "my_popen failure on %s: errno=%d (%s)\n", ++ args.GetArg(0), ++ errno, ++ strerror(errno)); + return -1; + } + MyString str; + while (str.readLine(fp, true)); ++ ++ priv_saved = set_user_priv(); + int ret = my_pclose(fp); ++ set_priv(priv_saved); ++ + if (ret != 0) { + str.trim(); + dprintf(D_ALWAYS, +@@ -320,17 +341,28 @@ GLExecPrivSepHelper::create_process(const char* path, + + glexec_env.MergeFrom(env); + +- if( glexec_env.GetEnv("X509_USER_PROXY",user_proxy) && +- (condor_proxy = getenv("X509_USER_PROXY")) ) ++ if( glexec_env.GetEnv("X509_USER_PROXY",user_proxy)) + { +- // glexec versions >= 0.7.0 may use X509_USER_PROXY to +- // authenticate to the mapping service. We are expected to +- // set this to the glidein (aka pilot) proxy rather than the +- // end-user proxy when invoking glexec. Since we are invoking +- // glexec with the job environment (see comment above), we +- // must treat X509_USER_PROXY specially. +- +- glexec_env.SetEnv("X509_USER_PROXY",condor_proxy); ++ if ((condor_proxy = getenv("X509_USER_PROXY"))) { ++ // glexec versions >= 0.7.0 may use X509_USER_PROXY to ++ // authenticate to the mapping service. We are expected to ++ // set this to the glidein (aka pilot) proxy rather than the ++ // end-user proxy when invoking glexec. Since we are invoking ++ // glexec with the job environment (see comment above), we ++ // must treat X509_USER_PROXY specially. ++ ++ glexec_env.SetEnv("X509_USER_PROXY",condor_proxy); ++ } ++ // We set the target proxy environment variable to point at ++ // the user proxy. Without it, newer versions of glexec will ++ // create a proxy in /tmp and not clean it up. When the glexec ++ // exec's to the target process, there will be a fresh copy ++ // of the proxy (not delegation). ++ // Note Condor will copy the proxy into into the user's sandbox, ++ // and this will get clobbered when the job actually launches. ++ // When Condor runs proxy-update, the proxy will get overwritten ++ // twice - first by glexec, then by Condor. ++ glexec_env.SetEnv("GLEXEC_TARGET_PROXY", user_proxy); + } + + int pid = daemonCore->Create_Process(m_run_script.Value(), +diff --git a/src/condor_utils/my_popen.cpp b/src/condor_utils/my_popen.cpp +index f0018c7..3206f91 100644 +--- a/src/condor_utils/my_popen.cpp ++++ b/src/condor_utils/my_popen.cpp +@@ -270,6 +270,7 @@ my_system(const char *cmd) + // UNIX versions of my_popen(v) & my_pclose + ////////////////////////////////////////////////////////////////////////// + ++#include // for O_CLOEXEC + #include // for setgroups + + static int READ_END = 0; +@@ -282,7 +283,7 @@ my_popenv_impl( const char *const args[], + uid_t privsep_uid, + Env *env_ptr = 0) + { +- int pipe_d[2]; ++ int pipe_d[2], pipe_d2[2]; + int parent_reads; + uid_t euid; + gid_t egid; +@@ -312,6 +313,32 @@ my_popenv_impl( const char *const args[], + } + } + ++ /* Create a pipe to detect execv failures */ ++ if ( pipe(pipe_d2) < 0) { ++ dprintf(D_ALWAYS, "my_popenv: Failed to create the pre-exec pipe, " ++ "errno=%d (%s)\n", errno, strerror(errno)); ++ close(pipe_d[0]); ++ close(pipe_d[1]); ++ return NULL; ++ } ++ int fd_flags; ++ if ((fd_flags = fcntl(pipe_d2[1], F_GETFD, NULL)) == -1) { ++ dprintf(D_ALWAYS, "my_popenv: Failed to get fd flags: errno=%d (%s)\n", errno, strerror(errno)); ++ close( pipe_d[0] ); ++ close( pipe_d[1] ); ++ close( pipe_d2[0] ); ++ close( pipe_d2[1] ); ++ return NULL; ++ } ++ if (fcntl(pipe_d2[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) { ++ dprintf(D_ALWAYS, "my_popenv: Failed to set new fd flags: errno=%d (%s)\n", errno, strerror(errno)); ++ close( pipe_d[0] ); ++ close( pipe_d[1] ); ++ close( pipe_d2[0] ); ++ close( pipe_d2[1] ); ++ return NULL; ++ } ++ + /* Create a new process */ + if( (pid=fork()) < 0 ) { + dprintf(D_ALWAYS, "my_popenv: Failed to fork child, errno=%d (%s)\n", +@@ -319,11 +346,14 @@ my_popenv_impl( const char *const args[], + /* Clean up file descriptors */ + close( pipe_d[0] ); + close( pipe_d[1] ); ++ close( pipe_d2[0] ); ++ close( pipe_d2[1] ); + return NULL; + } + + /* The child */ + if( pid == 0 ) { ++ close(pipe_d2[0]); + + if( parent_reads ) { + /* Close stdin, dup pipe to stdout */ +@@ -394,10 +424,36 @@ my_popenv_impl( const char *const args[], + execvp(cmd.Value(), const_cast(args) ); + } + +- _exit( ENOEXEC ); /* This isn't safe ... */ ++ /* If we get here, inform the parent of our errno */ ++ char result_buf[10]; ++ int len = snprintf(result_buf, 10, "%d", errno); ++ write(pipe_d2[1], result_buf, len); ++ ++ _exit( errno ); + } + + /* The parent */ ++ /* First, wait until the exec is called - determine status */ ++ close(pipe_d2[1]); ++ int exit_code; ++ FILE *fh; ++ if ((fh = fdopen(pipe_d2[0], "r")) == NULL) { ++ dprintf(D_ALWAYS, "my_popenv: Failed to reopen file descriptor as file handle: errno=%d (%s)", errno, strerror(errno)); ++ close(pipe_d2[0]); ++ close(pipe_d[0]); ++ close(pipe_d[1]); ++ return NULL; ++ } ++ /* Handle case where exec fails */ ++ if (fscanf(fh, "%d", &exit_code) == 1) { ++ fclose(fh); ++ close(pipe_d[0]); ++ close(pipe_d[1]); ++ errno = exit_code; ++ return NULL; ++ } ++ fclose(fh); ++ + if( parent_reads ) { + close( pipe_d[WRITE_END] ); + retp = fdopen(pipe_d[READ_END],mode);