summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Adamson <andros@netapp.com>2015-09-23 15:52:15 -0400
committerSteve Dickson <steved@redhat.com>2015-09-23 17:12:53 -0400
commit30c37b2dd6decdd65a33b956a5ae4b548de63a6d (patch)
tree32af4a76026c64443642f7e86bca413a140d31c4
parentcbe19a1d34d4d13f41337047da26ec1ef82ed44c (diff)
downloadnfs-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.c62
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);