autofs/autofs-5.1.8-dont-use-initgroups-at-spawn.patch
Ian Kent 511169a715 libnss_sss: threads stuck at sss_nss_lock from initgroups
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2087535

In threaded programs it's required to not call functions that are
not async-thread safe between fork(2) and exec(3).

Unfortunately initgroups(3) is not async-thread safe but is called
between these two functions and it leads to automount(8) hanging.

But getgroups(2) and setgroups(2) can be used for this and even though
setgroups(2) is not listed as async-thread safe it is in fact safe to
call here.

This MR changes automount(8) to use getgroups(2)/setgroups(2) instead
if initgroups(3) and testing shows that this resolves the hang problem.

Resolves: rhbz#2087535

Signed-off-by: Ian Kent ikent@redhat.com
2022-05-30 10:28:50 +08:00

132 lines
3.6 KiB
Diff

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