[03/10] gssd: Cleanup on exit to support valgrind.
diff mbox series

Message ID 20200701182803.14947-4-nazard@nazar.ca
State New
Headers show
Series
  • Misc fixes & cleanups for nfs-utils
Related show

Commit Message

Doug Nazar July 1, 2020, 6:27 p.m. UTC
Signed-off-by: Doug Nazar <nazard@nazar.ca>
---
 utils/gssd/gssd.c      | 46 +++++++++++++++++++++++++++++++------
 utils/gssd/krb5_util.c | 52 ++++++++++++++++++++++++------------------
 utils/gssd/krb5_util.h |  2 +-
 3 files changed, 70 insertions(+), 30 deletions(-)

Patch
diff mbox series

diff --git a/utils/gssd/gssd.c b/utils/gssd/gssd.c
index f8f21f74..54d9b5de 100644
--- a/utils/gssd/gssd.c
+++ b/utils/gssd/gssd.c
@@ -91,6 +91,7 @@  char *ccachedir = NULL;
 static bool avoid_dns = true;
 static bool use_gssproxy = false;
 pthread_mutex_t clp_lock = PTHREAD_MUTEX_INITIALIZER;
+static bool signal_received = false;
 static struct event_base *evbase = NULL;
 
 TAILQ_HEAD(topdir_list_head, topdir) topdir_list;
@@ -872,10 +873,16 @@  found:
 static void
 sig_die(int signal)
 {
-	if (root_uses_machine_creds)
-		gssd_destroy_krb5_machine_creds();
+	if (signal_received)
+	{
+		gssd_destroy_krb5_principals(root_uses_machine_creds);
+		printerr(1, "forced exiting on signal %d\n", signal);
+		exit(0);
+	}
+
+	signal_received = true;
 	printerr(1, "exiting on signal %d\n", signal);
-	exit(0);
+	event_base_loopexit(evbase, NULL);
 }
 
 static void
@@ -932,6 +939,7 @@  main(int argc, char *argv[])
 	int rpc_verbosity = 0;
 	int opt;
 	int i;
+	int rc;
 	extern char *optarg;
 	char *progname;
 	struct event *sighup_ev;
@@ -1109,9 +1117,33 @@  main(int argc, char *argv[])
 	gssd_scan();
 	daemon_ready();
 
-	event_base_dispatch(evbase);
+	rc = event_base_dispatch(evbase);
 
-	printerr(0, "ERROR: event_dispatch() returned!\n");
-	return EXIT_FAILURE;
-}
+	printerr(0, "event_dispatch() returned %i!\n", rc);
 
+	gssd_destroy_krb5_principals(root_uses_machine_creds);
+
+	while (!TAILQ_EMPTY(&topdir_list)) {
+		struct topdir *tdi = TAILQ_FIRST(&topdir_list);
+		TAILQ_REMOVE(&topdir_list, tdi, list);
+		while (!TAILQ_EMPTY(&tdi->clnt_list)) {
+			struct clnt_info *clp = TAILQ_FIRST(&tdi->clnt_list);
+			TAILQ_REMOVE(&tdi->clnt_list, clp, list);
+			gssd_destroy_client(clp);
+		}
+		free(tdi);
+	}
+
+	event_free(inotify_ev);
+	event_free(sighup_ev);
+	event_base_free(evbase);
+
+	close(inotify_fd);
+	close(pipefs_fd);
+	closedir(pipefs_dir);
+
+	free(preferred_realm);
+	free(ccachesearch);
+
+	return rc < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
+}
diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c
index 8c73748c..c49c6672 100644
--- a/utils/gssd/krb5_util.c
+++ b/utils/gssd/krb5_util.c
@@ -1226,7 +1226,7 @@  gssd_free_krb5_machine_cred_list(char **list)
  * Called upon exit.  Destroys machine credentials.
  */
 void
-gssd_destroy_krb5_machine_creds(void)
+gssd_destroy_krb5_principals(int destroy_machine_creds)
 {
 	krb5_context context;
 	krb5_error_code code = 0;
@@ -1238,33 +1238,41 @@  gssd_destroy_krb5_machine_creds(void)
 	if (code) {
 		k5err = gssd_k5_err_msg(NULL, code);
 		printerr(0, "ERROR: %s while initializing krb5\n", k5err);
-		goto out;
+		free(k5err);
+		return;
 	}
 
-	for (ple = gssd_k5_kt_princ_list; ple; ple = ple->next) {
-		if (!ple->ccname)
-			continue;
-		if ((code = krb5_cc_resolve(context, ple->ccname, &ccache))) {
-			k5err = gssd_k5_err_msg(context, code);
-			printerr(0, "WARNING: %s while resolving credential "
-				    "cache '%s' for destruction\n", k5err,
-				    ple->ccname);
-			krb5_free_string(context, k5err);
-			k5err = NULL;
-			continue;
-		}
+	pthread_mutex_lock(&ple_lock);
+	while (gssd_k5_kt_princ_list) {
+		ple = gssd_k5_kt_princ_list;
+		gssd_k5_kt_princ_list = ple->next;
 
-		if ((code = krb5_cc_destroy(context, ccache))) {
-			k5err = gssd_k5_err_msg(context, code);
-			printerr(0, "WARNING: %s while destroying credential "
-				    "cache '%s'\n", k5err, ple->ccname);
-			krb5_free_string(context, k5err);
-			k5err = NULL;
+		if (destroy_machine_creds && ple->ccname) {
+			if ((code = krb5_cc_resolve(context, ple->ccname, &ccache))) {
+				k5err = gssd_k5_err_msg(context, code);
+				printerr(0, "WARNING: %s while resolving credential "
+					    "cache '%s' for destruction\n", k5err,
+					    ple->ccname);
+				free(k5err);
+				k5err = NULL;
+			}
+
+			if (!code && (code = krb5_cc_destroy(context, ccache))) {
+				k5err = gssd_k5_err_msg(context, code);
+				printerr(0, "WARNING: %s while destroying credential "
+					    "cache '%s'\n", k5err, ple->ccname);
+				free(k5err);
+				k5err = NULL;
+			}
 		}
+
+		krb5_free_principal(context, ple->princ);
+		free(ple->ccname);
+		free(ple->realm);
+		free(ple);
 	}
+	pthread_mutex_unlock(&ple_lock);
 	krb5_free_context(context);
-  out:
-	krb5_free_string(context, k5err);
 }
 
 /*
diff --git a/utils/gssd/krb5_util.h b/utils/gssd/krb5_util.h
index b000b444..e127cc84 100644
--- a/utils/gssd/krb5_util.h
+++ b/utils/gssd/krb5_util.h
@@ -27,7 +27,7 @@  int gssd_setup_krb5_user_gss_ccache(uid_t uid, char *servername,
 				     char *dirname);
 int  gssd_get_krb5_machine_cred_list(char ***list);
 void gssd_free_krb5_machine_cred_list(char **list);
-void gssd_destroy_krb5_machine_creds(void);
+void gssd_destroy_krb5_principals(int destroy_machine_creds);
 int  gssd_refresh_krb5_machine_credential(char *hostname,
 					  struct gssd_k5_kt_princ *ple, 
 					  char *service, char *srchost);