From 30c37b2dd6decdd65a33b956a5ae4b548de63a6d Mon Sep 17 00:00:00 2001 From: Andy Adamson Date: Wed, 23 Sep 2015 15:52:15 -0400 Subject: GSSD only fork when uid is not zero commit f9cac65972da588d5218236de60a7be11247a8aa added the fork to process_krb5_upcall so that the child assumes the uid of the principal requesting service. When machine credentials are used, a gssd_k5_kt_princ entry is added to a global list and used by future upcalls to note when valid machine credentials have been obtained. When a child process performs this task, the entry to the global list is lost upon exit, and all upcalls for machine credentials re-fetch a TGT, even when a valid TGT is in the machine kerberos credential cache. Since forking is not necessary when the principal has uid=0, solve the gssd_k5_kt_princ_list issue by only forking when the uid != 0. Acked-by: Jeff Layton Signed-off-by: Andy Adamson Signed-off-by: Steve Dickson --- utils/gssd/gssd_proc.c | 62 +++++++++++++++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 24 deletions(-) (limited to 'utils/gssd/gssd_proc.c') diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index 36aff5d..11168b2 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -603,33 +603,11 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname, gss_buffer_desc token; int err, downcall_err = -EACCES; OM_uint32 maj_stat, min_stat, lifetime_rec; - pid_t pid; + pid_t pid, childpid = -1; gss_name_t gacceptor = GSS_C_NO_NAME; gss_OID mech; gss_buffer_desc acceptor = {0}; - pid = fork(); - switch(pid) { - case 0: - /* Child: fall through to rest of function */ - break; - case -1: - /* fork() failed! */ - printerr(0, "WARNING: unable to fork() to handle upcall: %s\n", - strerror(errno)); - return; - default: - /* Parent: just wait on child to exit and return */ - do { - pid = wait(&err); - } while(pid == -1 && errno != -ECHILD); - - if (WIFSIGNALED(err)) - printerr(0, "WARNING: forked child was killed with signal %d\n", - WTERMSIG(err)); - return; - } - printerr(1, "handling krb5 upcall (%s)\n", clp->relpath); token.length = 0; @@ -661,6 +639,37 @@ process_krb5_upcall(struct clnt_info *clp, uid_t uid, int fd, char *tgtname, service ? service : ""); if (uid != 0 || (uid == 0 && root_uses_machine_creds == 0 && service == NULL)) { + + /* already running as uid 0 */ + if (uid == 0) + goto no_fork; + + pid = fork(); + switch(pid) { + case 0: + /* Child: fall through to rest of function */ + childpid = getpid(); + unsetenv("KRB5CCNAME"); + printerr(1, "CHILD forked pid %d \n", childpid); + break; + case -1: + /* fork() failed! */ + printerr(0, "WARNING: unable to fork() to handle" + "upcall: %s\n", strerror(errno)); + return; + default: + /* Parent: just wait on child to exit and return */ + do { + pid = wait(&err); + } while(pid == -1 && errno != -ECHILD); + + if (WIFSIGNALED(err)) + printerr(0, "WARNING: forked child was killed" + "with signal %d\n", WTERMSIG(err)); + return; + } +no_fork: + auth = krb5_not_machine_creds(clp, uid, tgtname, &downcall_err, &err, &rpc_clnt); if (err) @@ -727,7 +736,12 @@ out: AUTH_DESTROY(auth); if (rpc_clnt) clnt_destroy(rpc_clnt); - exit(0); + + pid = getpid(); + if (pid == childpid) + exit(0); + else + return; out_return_error: do_error_downcall(fd, uid, downcall_err); -- cgit