aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--shell/ash.c11
-rw-r--r--shell/ash_test/ash-redir/redir_leak.right6
-rwxr-xr-xshell/ash_test/ash-redir/redir_leak.tests10
-rw-r--r--shell/hush_test/hush-redir/redir_leak.right6
-rwxr-xr-xshell/hush_test/hush-redir/redir_leak.tests10
5 files changed, 39 insertions, 4 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 7c53946ce..e6d02f69c 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -5426,11 +5426,11 @@ redirect(union node *redir, int flags)
5426 /* Careful to not accidentally "save" 5426 /* Careful to not accidentally "save"
5427 * to the same fd as right side fd in N>&M */ 5427 * to the same fd as right side fd in N>&M */
5428 int minfd = right_fd < 10 ? 10 : right_fd + 1; 5428 int minfd = right_fd < 10 ? 10 : right_fd + 1;
5429#if defined(F_DUPFD_CLOEXEC)
5430 i = fcntl(fd, F_DUPFD_CLOEXEC, minfd);
5431#else
5429 i = fcntl(fd, F_DUPFD, minfd); 5432 i = fcntl(fd, F_DUPFD, minfd);
5430/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds 5433#endif
5431 * are closed in popredir() in the child, preventing them from leaking
5432 * into child. (popredir() also cleans up the mess in case of failures)
5433 */
5434 if (i == -1) { 5434 if (i == -1) {
5435 i = errno; 5435 i = errno;
5436 if (i != EBADF) { 5436 if (i != EBADF) {
@@ -5445,6 +5445,9 @@ redirect(union node *redir, int flags)
5445 remember_to_close: 5445 remember_to_close:
5446 i = CLOSED; 5446 i = CLOSED;
5447 } else { /* fd is open, save its copy */ 5447 } else { /* fd is open, save its copy */
5448#if !defined(F_DUPFD_CLOEXEC)
5449 fcntl(i, F_SETFD, FD_CLOEXEC);
5450#endif
5448 /* "exec fd>&-" should not close fds 5451 /* "exec fd>&-" should not close fds
5449 * which point to script file(s). 5452 * which point to script file(s).
5450 * Force them to be restored afterwards */ 5453 * Force them to be restored afterwards */
diff --git a/shell/ash_test/ash-redir/redir_leak.right b/shell/ash_test/ash-redir/redir_leak.right
new file mode 100644
index 000000000..b1c48292b
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_leak.right
@@ -0,0 +1,6 @@
14
24
34
44
54
64
diff --git a/shell/ash_test/ash-redir/redir_leak.tests b/shell/ash_test/ash-redir/redir_leak.tests
new file mode 100755
index 000000000..c8a9c6343
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_leak.tests
@@ -0,0 +1,10 @@
1# Each of these should show only four lines:
2# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls.
3# This test detects bugs where redirects leave stray open fds.
4
5ls -1 /proc/self/fd | wc -l
6ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l
7ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l
8echo "`ls -1 /proc/self/fd `" | wc -l
9echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l
10echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l
diff --git a/shell/hush_test/hush-redir/redir_leak.right b/shell/hush_test/hush-redir/redir_leak.right
new file mode 100644
index 000000000..b1c48292b
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_leak.right
@@ -0,0 +1,6 @@
14
24
34
44
54
64
diff --git a/shell/hush_test/hush-redir/redir_leak.tests b/shell/hush_test/hush-redir/redir_leak.tests
new file mode 100755
index 000000000..c8a9c6343
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_leak.tests
@@ -0,0 +1,10 @@
1# Each of these should show only four lines:
2# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls.
3# This test detects bugs where redirects leave stray open fds.
4
5ls -1 /proc/self/fd | wc -l
6ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l
7ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l
8echo "`ls -1 /proc/self/fd `" | wc -l
9echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l
10echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l