Blame SOURCES/autofs-5.1.8-dont-use-initgroups-at-spawn.patch

743e80
autofs-5.1.8 - dont use initgroups() at spawn
743e80
743e80
From: Ian Kent <raven@themaw.net>
743e80
743e80
The initgroups(3) function isn't safe to use between fork() and
743e80
exec() in a threaded program.
743e80
743e80
Using it this way often leads to a hang for even moderate work
743e80
loads.
743e80
743e80
But the getgrouplist()/setgroups() combination can be used safely
743e80
in this case and this patch changes autofs to use these (the safety
743e80
of using of setgroups() is yet to to be documented).
743e80
743e80
A large portion of the work on this patch has been contributed
743e80
by Roberto Bergantinos <rbergant@redhat.com>.
743e80
743e80
Reported-by: Roberto Bergantinos <rbergant@redhat.com>
743e80
Fixes: 6343a3292020 ("autofs-5.1.3 - fix ordering of seteuid/setegid in do_spawn()")
743e80
Signed-off-by: Roberto Bergantinos <rbergant@redhat.com>
743e80
Signed-off-by: Ian Kent <raven@themaw.net>
743e80
---
743e80
 CHANGELOG      |    1 +
743e80
 daemon/spawn.c |   51 +++++++++++++++++++++++++++++++++++++++++++++++----
743e80
 2 files changed, 48 insertions(+), 4 deletions(-)
743e80
743e80
--- autofs-5.1.4.orig/CHANGELOG
743e80
+++ autofs-5.1.4/CHANGELOG
743e80
@@ -94,6 +94,7 @@
743e80
 - fix sysconf(3) return handling.
743e80
 - remove nonstrict parameter from tree_mapent_umount_offsets().
743e80
 - fix handling of incorrect return from umount_ent().
743e80
+- dont use initgroups() at spawn.
743e80
 
743e80
 xx/xx/2018 autofs-5.1.5
743e80
 - fix flag file permission.
743e80
--- autofs-5.1.4.orig/daemon/spawn.c
743e80
+++ autofs-5.1.4/daemon/spawn.c
743e80
@@ -26,6 +26,7 @@
743e80
 #include <sys/wait.h>
743e80
 #include <sys/stat.h>
743e80
 #include <sys/mount.h>
743e80
+#include <pwd.h>
743e80
 
743e80
 #include "automount.h"
743e80
 
743e80
@@ -335,6 +336,10 @@ static int do_spawn(unsigned logopt, uns
743e80
 	struct thread_stdenv_vars *tsv;
743e80
 	pid_t euid = 0;
743e80
 	gid_t egid = 0;
743e80
+	gid_t *groups = NULL;
743e80
+	gid_t *saved_groups = NULL;
743e80
+	int ngroups = 0;
743e80
+	int nsaved_groups = 0;
743e80
 
743e80
 	if (open_pipe(pipefd))
743e80
 		return -1;
743e80
@@ -357,6 +362,31 @@ static int do_spawn(unsigned logopt, uns
743e80
 	}
743e80
 
743e80
 	open_mutex_lock();
743e80
+
743e80
+	if (euid) {
743e80
+		struct passwd *pwd;
743e80
+
743e80
+		pwd = getpwuid(getuid());
743e80
+		if (!pwd)
743e80
+			fprintf(stderr,
743e80
+				"warning: getpwuid: can't get current username\n");
743e80
+		else {
743e80
+			/* get number of groups for current gid */
743e80
+			getgrouplist(pwd->pw_name, getgid(), NULL, &nsaved_groups);
743e80
+			saved_groups = malloc(nsaved_groups * sizeof(gid_t));
743e80
+
743e80
+			/* get current gid groups list */
743e80
+			getgrouplist(pwd->pw_name, getgid(), saved_groups, &nsaved_groups);
743e80
+		}
743e80
+
743e80
+		/* get number of groups of mount triggering process */
743e80
+		getgrouplist(tsv->user, egid, NULL, &ngroups);
743e80
+		groups = malloc(ngroups * sizeof(gid_t));
743e80
+
743e80
+		/* get groups list of mount triggering process */
743e80
+		getgrouplist(tsv->user, egid, groups, &ngroups);
743e80
+	}
743e80
+
743e80
 	f = fork();
743e80
 	if (f == 0) {
743e80
 		char **pargv = (char **) argv;
743e80
@@ -398,10 +428,13 @@ static int do_spawn(unsigned logopt, uns
743e80
 				if (!tsv->user)
743e80
 					fprintf(stderr,
743e80
 						"warning: can't init groups\n");
743e80
-				else if (initgroups(tsv->user, egid) == -1)
743e80
-					fprintf(stderr,
743e80
-						"warning: initgroups: %s\n",
743e80
-						strerror(errno));
743e80
+				else if (groups) {
743e80
+					if (setgroups(ngroups, groups) == -1)
743e80
+						fprintf(stderr,
743e80
+							"warning: setgroups: %s\n",
743e80
+							strerror(errno));
743e80
+					free(groups);
743e80
+				}
743e80
 
743e80
 				if (setegid(egid) == -1)
743e80
 					fprintf(stderr,
743e80
@@ -436,6 +469,11 @@ static int do_spawn(unsigned logopt, uns
743e80
 					strerror(errno));
743e80
 			if (pgrp >= 0)
743e80
 				setpgid(0, pgrp);
743e80
+			/* Reset groups for trigger of trailing mount */
743e80
+			if (euid && saved_groups) {
743e80
+				setgroups(nsaved_groups, saved_groups);
743e80
+				free(saved_groups);
743e80
+			}
743e80
 
743e80
 			/*
743e80
 			 * The kernel leaves mount type autofs alone because
743e80
@@ -474,6 +512,11 @@ done:
743e80
 		pthread_sigmask(SIG_SETMASK, &tmpsig, NULL);
743e80
 		open_mutex_unlock();
743e80
 
743e80
+		if (groups)
743e80
+			free(groups);
743e80
+		if (saved_groups)
743e80
+			free(saved_groups);
743e80
+
743e80
 		close(pipefd[1]);
743e80
 
743e80
 		if (f < 0) {