blob: 7fc0972507b43f44a70635c81e1820e6351a3aeb [file] [log] [blame]
From a3ff1534945c3898332b2481c9fd355dfbd56e1f Mon Sep 17 00:00:00 2001
From: Mike Frysinger <vapier@gentoo.org>
Date: Sat, 23 Jun 2012 11:52:51 -0700
Subject: [PATCH] libsandbox: clean up open file handles in parent tracing
process
Currently, if a non-static app sets up a pipe (with cloexec enabled) and
executes a static app, the handle to that pipe is left open in the parent
process. This causes trouble when the parent is waiting for that to be
closed immediately.
Since none of the fds in the forked parent process matter to us, we can
just go ahead and clean up all fds before we start tracing the child.
URL: http://bugs.gentoo.org/364877
Reported-by: Victor Stinner <victor.stinner@haypocalc.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
---
libsandbox/trace.c | 3 +-
libsbutil/sb_close.c | 26 +++++++++++-
libsbutil/sbutil.h | 1 +
tests/Makefile.am | 2 +
tests/pipe-fork_static_tst.c | 18 +++++++++
tests/pipe-fork_tst.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
tests/script-9.sh | 5 +++
tests/script.at | 1 +
8 files changed, 149 insertions(+), 2 deletions(-)
create mode 100644 tests/pipe-fork_static_tst.c
create mode 100644 tests/pipe-fork_tst.c
create mode 100755 tests/script-9.sh
diff --git a/libsandbox/trace.c b/libsandbox/trace.c
index 32ad2d6..dfbab18 100644
--- a/libsandbox/trace.c
+++ b/libsandbox/trace.c
@@ -504,8 +504,9 @@ void trace_main(const char *filename, char *const argv[])
/* Not all kernel versions support this, so ignore return */
ptrace(PTRACE_SETOPTIONS, trace_pid, NULL, (void *)PTRACE_O_TRACESYSGOOD);
#endif
+ sb_close_all_fds();
trace_loop();
- return;
+ sb_ebort("ISE: child should have quit, as should we\n");
}
sb_debug("child setting up ...");
diff --git a/libsbutil/sb_close.c b/libsbutil/sb_close.c
index 17a4560..5379197 100644
--- a/libsbutil/sb_close.c
+++ b/libsbutil/sb_close.c
@@ -29,3 +29,27 @@ int sb_close(int fd)
return res;
}
+
+/* Quickly close all the open fds (good for daemonization) */
+void sb_close_all_fds(void)
+{
+ DIR *dirp;
+ struct dirent *de;
+ int dfd, fd;
+ const char *fd_dir = sb_get_fd_dir();
+
+ dirp = opendir(fd_dir);
+ if (!dirp)
+ sb_ebort("could not process %s\n", fd_dir);
+ dfd = dirfd(dirp);
+
+ while ((de = readdir(dirp)) != NULL) {
+ if (de->d_name[0] == '.')
+ continue;
+ fd = atoi(de->d_name);
+ if (fd != dfd)
+ close(fd);
+ }
+
+ closedir(dirp);
+}
diff --git a/libsbutil/sbutil.h b/libsbutil/sbutil.h
index 02b88cb..479734b 100644
--- a/libsbutil/sbutil.h
+++ b/libsbutil/sbutil.h
@@ -97,6 +97,7 @@ int sb_open(const char *path, int flags, mode_t mode);
size_t sb_read(int fd, void *buf, size_t count);
size_t sb_write(int fd, const void *buf, size_t count);
int sb_close(int fd);
+void sb_close_all_fds(void);
int sb_copy_file_to_fd(const char *file, int ofd);
/* Reliable output */
--
1.8.1.2