Blame SOURCES/autofs-5.1.3-move-open_xxxx-functions-to-spawn_c.patch

cef8f8
autofs-5.1.3 - move open_xxxx() functions to spawn.c
cef8f8
cef8f8
From: Ian Kent <raven@themaw.net>
cef8f8
cef8f8
In a bug report by John Salmon has described a race between the
cef8f8
autofs open_xxxx() functions and fork(2) that can cause file handles
cef8f8
that don't have close on exec set to leak into subprocesses.
cef8f8
cef8f8
Basically, in some cases there can be a finite time between performing
cef8f8
the open and setting the descriptor close on exec and it's this window
cef8f8
that leads to the problem.
cef8f8
cef8f8
The description went on to talk about a case where autofs can hang when
cef8f8
this happens. That is when the leaked decriptor causes poll(2) to not
cef8f8
return in another process because it is waiting for the decriptor to
cef8f8
close (on mount completion) but another execed process has the cloned
cef8f8
descriptor open.
cef8f8
cef8f8
Serializing access to the open_xxxx() functions wrt. to fork(2) calls
cef8f8
should be suficient to resolve this leakage.
cef8f8
cef8f8
This patch starts this by moving the open_xxxx() out of the automount.h
cef8f8
include file and into spawn.c.
cef8f8
cef8f8
Signed-off-by: Ian Kent <raven@themaw.net>
cef8f8
---
cef8f8
 CHANGELOG           |    1 
cef8f8
 daemon/automount.c  |    3 -
cef8f8
 daemon/spawn.c      |  125 +++++++++++++++++++++++++++++++++++++++++++++++++
cef8f8
 include/automount.h |  132 ++--------------------------------------------------
cef8f8
 4 files changed, 133 insertions(+), 128 deletions(-)
cef8f8
cef8f8
--- autofs-5.0.7.orig/CHANGELOG
cef8f8
+++ autofs-5.0.7/CHANGELOG
cef8f8
@@ -287,6 +287,7 @@
cef8f8
 - fix incorrect check in validate_program_options().
cef8f8
 - update configure to check for pipe2(2).
cef8f8
 - fix open calls not using open_xxxx() calls.
cef8f8
+- move open_xxxx() functions to spawn.c.
cef8f8
 
cef8f8
 25/07/2012 autofs-5.0.7
cef8f8
 =======================
cef8f8
--- autofs-5.0.7.orig/daemon/spawn.c
cef8f8
+++ autofs-5.0.7/daemon/spawn.c
cef8f8
@@ -49,6 +49,131 @@ void dump_core(void)
cef8f8
 }
cef8f8
 
cef8f8
 /*
cef8f8
+ * Use CLOEXEC flag for open(), pipe(), fopen() (read-only case) and
cef8f8
+ * socket() if possible.
cef8f8
+ */
cef8f8
+static int cloexec_works = 0;
cef8f8
+
cef8f8
+static void check_cloexec(int fd)
cef8f8
+{
cef8f8
+	if (cloexec_works == 0) {
cef8f8
+		int fl = fcntl(fd, F_GETFD);
cef8f8
+		if (fl != -1)
cef8f8
+			cloexec_works = (fl & FD_CLOEXEC) ? 1 : -1;
cef8f8
+	}
cef8f8
+	if (cloexec_works > 0)
cef8f8
+		return;
cef8f8
+	fcntl(fd, F_SETFD, FD_CLOEXEC);
cef8f8
+	return;
cef8f8
+}
cef8f8
+
cef8f8
+int open_fd(const char *path, int flags)
cef8f8
+{
cef8f8
+	int fd;
cef8f8
+
cef8f8
+#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
+	if (cloexec_works != -1)
cef8f8
+		flags |= O_CLOEXEC;
cef8f8
+#endif
cef8f8
+	fd = open(path, flags);
cef8f8
+	if (fd == -1)
cef8f8
+		return -1;
cef8f8
+	check_cloexec(fd);
cef8f8
+	return fd;
cef8f8
+}
cef8f8
+
cef8f8
+int open_fd_mode(const char *path, int flags, int mode)
cef8f8
+{
cef8f8
+	int fd;
cef8f8
+
cef8f8
+#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
+	if (cloexec_works != -1)
cef8f8
+		flags |= O_CLOEXEC;
cef8f8
+#endif
cef8f8
+	fd = open(path, flags, mode);
cef8f8
+	if (fd == -1)
cef8f8
+		return -1;
cef8f8
+	check_cloexec(fd);
cef8f8
+	return fd;
cef8f8
+}
cef8f8
+
cef8f8
+int open_pipe(int pipefd[2])
cef8f8
+{
cef8f8
+	int ret;
cef8f8
+
cef8f8
+#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) && defined(HAVE_PIPE2)
cef8f8
+	if (cloexec_works != -1) {
cef8f8
+		ret = pipe2(pipefd, O_CLOEXEC);
cef8f8
+		if (ret != -1)
cef8f8
+			return 0;
cef8f8
+		if (errno != EINVAL)
cef8f8
+			return -1;
cef8f8
+	}
cef8f8
+#endif
cef8f8
+	ret = pipe(pipefd);
cef8f8
+	if (ret == -1)
cef8f8
+		return -1;
cef8f8
+	check_cloexec(pipefd[0]);
cef8f8
+	check_cloexec(pipefd[1]);
cef8f8
+	return 0;
cef8f8
+}
cef8f8
+
cef8f8
+int open_sock(int domain, int type, int protocol)
cef8f8
+{
cef8f8
+	int fd;
cef8f8
+
cef8f8
+#ifdef SOCK_CLOEXEC
cef8f8
+	if (cloexec_works != -1)
cef8f8
+		type |= SOCK_CLOEXEC;
cef8f8
+#endif
cef8f8
+	fd = socket(domain, type, protocol);
cef8f8
+	if (fd == -1)
cef8f8
+		return -1;
cef8f8
+	check_cloexec(fd);
cef8f8
+	return fd;
cef8f8
+}
cef8f8
+
cef8f8
+FILE *open_fopen_r(const char *path)
cef8f8
+{
cef8f8
+	FILE *f;
cef8f8
+
cef8f8
+#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
+	if (cloexec_works != -1) {
cef8f8
+		f = fopen(path, "re");
cef8f8
+		if (f != NULL) {
cef8f8
+			check_cloexec(fileno(f));
cef8f8
+			return f;
cef8f8
+		}
cef8f8
+	}
cef8f8
+#endif
cef8f8
+	f = fopen(path, "r");
cef8f8
+	if (f == NULL)
cef8f8
+		return NULL;
cef8f8
+	check_cloexec(fileno(f));
cef8f8
+	return f;
cef8f8
+}
cef8f8
+
cef8f8
+FILE *open_setmntent_r(const char *table)
cef8f8
+{
cef8f8
+	FILE *tab;
cef8f8
+
cef8f8
+#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
+	if (cloexec_works != -1) {
cef8f8
+		tab = setmntent(table, "re");
cef8f8
+		if (tab != NULL) {
cef8f8
+			check_cloexec(fileno(tab));
cef8f8
+			return tab;
cef8f8
+		}
cef8f8
+	}
cef8f8
+#endif
cef8f8
+	tab = fopen(table, "r");
cef8f8
+	if (tab == NULL)
cef8f8
+		return NULL;
cef8f8
+	check_cloexec(fileno(tab));
cef8f8
+	return tab;
cef8f8
+}
cef8f8
+
cef8f8
+/*
cef8f8
  * Used by subprocesses which exec to avoid carrying over the main
cef8f8
  * daemon's signalling environment
cef8f8
  */
cef8f8
--- autofs-5.0.7.orig/include/automount.h
cef8f8
+++ autofs-5.0.7/include/automount.h
cef8f8
@@ -8,6 +8,7 @@
cef8f8
 #ifndef AUTOMOUNT_H
cef8f8
 #define AUTOMOUNT_H
cef8f8
 
cef8f8
+#include <stdio.h>
cef8f8
 #include <paths.h>
cef8f8
 #include <limits.h>
cef8f8
 #include <time.h>
cef8f8
@@ -256,6 +257,12 @@ int spawnv(unsigned logopt, const char *
cef8f8
 int spawn_mount(unsigned logopt, ...);
cef8f8
 int spawn_bind_mount(unsigned logopt, ...);
cef8f8
 int spawn_umount(unsigned logopt, ...);
cef8f8
+int open_fd(const char *, int);
cef8f8
+int open_fd_mode(const char *, int, int);
cef8f8
+int open_pipe(int[2]);
cef8f8
+int open_sock(int, int, int);
cef8f8
+FILE *open_fopen_r(const char *);
cef8f8
+FILE *open_setmntent_r(const char *);
cef8f8
 void reset_signals(void);
cef8f8
 int do_mount(struct autofs_point *ap, const char *root, const char *name,
cef8f8
 	     int name_len, const char *what, const char *fstype,
cef8f8
@@ -600,130 +607,5 @@ int alarm_start_handler(void);
cef8f8
 int alarm_add(struct autofs_point *ap, time_t seconds);
cef8f8
 void alarm_delete(struct autofs_point *ap);
cef8f8
 
cef8f8
-/*
cef8f8
- * Use CLOEXEC flag for open(), pipe(), fopen() (read-only case) and
cef8f8
- * socket() if possible.
cef8f8
- */
cef8f8
-static int cloexec_works;
cef8f8
-
cef8f8
-static inline void check_cloexec(int fd)
cef8f8
-{
cef8f8
-	if (cloexec_works == 0) {
cef8f8
-		int fl = fcntl(fd, F_GETFD);
cef8f8
-		if (fl != -1)
cef8f8
-			cloexec_works = (fl & FD_CLOEXEC) ? 1 : -1;
cef8f8
-	}
cef8f8
-	if (cloexec_works > 0)
cef8f8
-		return;
cef8f8
-	fcntl(fd, F_SETFD, FD_CLOEXEC);
cef8f8
-	return;
cef8f8
-}
cef8f8
-
cef8f8
-static inline int open_fd(const char *path, int flags)
cef8f8
-{
cef8f8
-	int fd;
cef8f8
-
cef8f8
-#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
-	if (cloexec_works != -1)
cef8f8
-		flags |= O_CLOEXEC;
cef8f8
-#endif
cef8f8
-	fd = open(path, flags);
cef8f8
-	if (fd == -1)
cef8f8
-		return -1;
cef8f8
-	check_cloexec(fd);
cef8f8
-	return fd;
cef8f8
-}
cef8f8
-
cef8f8
-static inline int open_fd_mode(const char *path, int flags, int mode)
cef8f8
-{
cef8f8
-	int fd;
cef8f8
-
cef8f8
-#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
-	if (cloexec_works != -1)
cef8f8
-		flags |= O_CLOEXEC;
cef8f8
-#endif
cef8f8
-	fd = open(path, flags, mode);
cef8f8
-	if (fd == -1)
cef8f8
-		return -1;
cef8f8
-	check_cloexec(fd);
cef8f8
-	return fd;
cef8f8
-}
cef8f8
-
cef8f8
-static inline int open_pipe(int pipefd[2])
cef8f8
-{
cef8f8
-	int ret;
cef8f8
-
cef8f8
-#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC) && defined(HAVE_PIPE2)
cef8f8
-	if (cloexec_works != -1) {
cef8f8
-		ret = pipe2(pipefd, O_CLOEXEC);
cef8f8
-		if (ret != -1)
cef8f8
-			return 0;
cef8f8
-		if (errno != EINVAL)
cef8f8
-			return -1;
cef8f8
-	}
cef8f8
-#endif
cef8f8
-	ret = pipe(pipefd);
cef8f8
-	if (ret == -1)
cef8f8
-		return -1;
cef8f8
-	check_cloexec(pipefd[0]);
cef8f8
-	check_cloexec(pipefd[1]);
cef8f8
-	return 0;
cef8f8
-}
cef8f8
-
cef8f8
-static inline int open_sock(int domain, int type, int protocol)
cef8f8
-{
cef8f8
-	int fd;
cef8f8
-
cef8f8
-#ifdef SOCK_CLOEXEC
cef8f8
-	if (cloexec_works != -1)
cef8f8
-		type |= SOCK_CLOEXEC;
cef8f8
-#endif
cef8f8
-	fd = socket(domain, type, protocol);
cef8f8
-	if (fd == -1)
cef8f8
-		return -1;
cef8f8
-	check_cloexec(fd);
cef8f8
-	return fd;
cef8f8
-}
cef8f8
-
cef8f8
-static inline FILE *open_fopen_r(const char *path)
cef8f8
-{
cef8f8
-	FILE *f;
cef8f8
-
cef8f8
-#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
-	if (cloexec_works != -1) {
cef8f8
-		f = fopen(path, "re");
cef8f8
-		if (f != NULL) {
cef8f8
-			check_cloexec(fileno(f));
cef8f8
-			return f;
cef8f8
-		}
cef8f8
-	}
cef8f8
-#endif
cef8f8
-	f = fopen(path, "r");
cef8f8
-	if (f == NULL)
cef8f8
-		return NULL;
cef8f8
-	check_cloexec(fileno(f));
cef8f8
-	return f;
cef8f8
-}
cef8f8
-
cef8f8
-static inline FILE *open_setmntent_r(const char *table)
cef8f8
-{
cef8f8
-	FILE *tab;
cef8f8
-
cef8f8
-#if defined(O_CLOEXEC) && defined(SOCK_CLOEXEC)
cef8f8
-	if (cloexec_works != -1) {
cef8f8
-		tab = setmntent(table, "re");
cef8f8
-		if (tab != NULL) {
cef8f8
-			check_cloexec(fileno(tab));
cef8f8
-			return tab;
cef8f8
-		}
cef8f8
-	}
cef8f8
-#endif
cef8f8
-	tab = fopen(table, "r");
cef8f8
-	if (tab == NULL)
cef8f8
-		return NULL;
cef8f8
-	check_cloexec(fileno(tab));
cef8f8
-	return tab;
cef8f8
-}
cef8f8
-
cef8f8
 #endif
cef8f8
 
cef8f8
--- autofs-5.0.7.orig/daemon/automount.c
cef8f8
+++ autofs-5.0.7/daemon/automount.c
cef8f8
@@ -75,9 +75,6 @@ static sigset_t block_sigs;
cef8f8
 /* Pre-calculated kernel packet length */
cef8f8
 static size_t kpkt_len;
cef8f8
 
cef8f8
-/* Does kernel know about SOCK_CLOEXEC and friends */
cef8f8
-static int cloexec_works = 0;
cef8f8
-
cef8f8
 /* Attributes for creating detached and joinable threads */
cef8f8
 pthread_attr_t th_attr;
cef8f8
 pthread_attr_t th_attr_detached;