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

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