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

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