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

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