132 lines
3.6 KiB
Diff
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.4.orig/CHANGELOG
|
|
+++ autofs-5.1.4/CHANGELOG
|
|
@@ -94,6 +94,7 @@
|
|
- fix sysconf(3) return handling.
|
|
- remove nonstrict parameter from tree_mapent_umount_offsets().
|
|
- fix handling of incorrect return from umount_ent().
|
|
+- dont use initgroups() at spawn.
|
|
|
|
xx/xx/2018 autofs-5.1.5
|
|
- fix flag file permission.
|
|
--- autofs-5.1.4.orig/daemon/spawn.c
|
|
+++ autofs-5.1.4/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) {
|