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

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