[condor: 2/31] Added the glexec-as-root patch.
Brian Bockelman
bbockelm at fedoraproject.org
Fri Mar 8 01:19:47 UTC 2013
commit 4c2db811c7f18fe1ed00ce9f37364cdde967367c
Author: Brian Bockelman <bbockelm at cse.unl.edu>
Date: Fri Sep 30 15:45:34 2011 -0500
Added the glexec-as-root patch.
condor_glexec_as_root_v3.patch | 217 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 217 insertions(+), 0 deletions(-)
---
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 <fcntl.h> // for O_CLOEXEC
+ #include <grp.h> // 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<char *const*>(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);
More information about the scm-commits
mailing list