diff options
author | Andy Adamson <andros@netapp.com> | 2015-09-23 15:52:15 -0400 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2015-09-23 17:12:53 -0400 |
commit | 30c37b2dd6decdd65a33b956a5ae4b548de63a6d (patch) | |
tree | 32af4a76026c64443642f7e86bca413a140d31c4 | |
parent | cbe19a1d34d4d13f41337047da26ec1ef82ed44c (diff) | |
download | nfs-utils-30c37b2dd6decdd65a33b956a5ae4b548de63a6d.tar.gz |
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 <jlayton@poochiereds.net>
Signed-off-by: Andy Adamson <andros@netapp.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r-- | utils/gssd/gssd_proc.c | 62 |
1 files changed, 38 insertions, 24 deletions
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 : "<null>"); 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); |