summaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenys Vlasenko2018-03-28 18:35:07 +0200
committerDenys Vlasenko2018-03-28 18:35:07 +0200
commit9acd63c92cbc4bd0a3ddbb6a61e512eadc29239d (patch)
tree9bf53c82f5fccd4a5ed13915b8039080c563ce07 /shell
parente4defe826be49b8ef19912ba4cb291bfe9166e0f (diff)
downloadbusybox-9acd63c92cbc4bd0a3ddbb6a61e512eadc29239d.zip
busybox-9acd63c92cbc4bd0a3ddbb6a61e512eadc29239d.tar.gz
ash,hush: fix "saved" redirected fds still visible in children
Based on a patch by Mark Marshall <mark.marshall@omicronenergy.com> function old new delta dup_CLOEXEC - 49 +49 fcntl_F_DUPFD 46 - -46 Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c16
-rw-r--r--shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right5
-rwxr-xr-xshell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests6
-rw-r--r--shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right5
-rwxr-xr-xshell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests6
-rw-r--r--shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right5
-rwxr-xr-xshell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests6
-rw-r--r--shell/hush.c23
-rw-r--r--shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right5
-rwxr-xr-xshell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests6
-rw-r--r--shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right5
-rwxr-xr-xshell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests6
-rw-r--r--shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right5
-rwxr-xr-xshell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests6
14 files changed, 92 insertions, 13 deletions
diff --git a/shell/ash.c b/shell/ash.c
index 5e281b5..85690e5 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -255,6 +255,9 @@ typedef long arith_t;
# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
#endif
+#ifndef F_DUPFD_CLOEXEC
+# define F_DUPFD_CLOEXEC F_DUPFD
+#endif
#ifndef PIPE_BUF
# define PIPE_BUF 4096 /* amount of buffering in a pipe */
#endif
@@ -5448,12 +5451,15 @@ dup2_or_raise(int from, int to)
return newfd;
}
static int
-fcntl_F_DUPFD(int fd, int avoid_fd)
+dup_CLOEXEC(int fd, int avoid_fd)
{
int newfd;
repeat:
- newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
- if (newfd < 0) {
+ newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
+ if (newfd >= 0) {
+ if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
+ fcntl(newfd, F_SETFD, FD_CLOEXEC);
+ } else { /* newfd < 0 */
if (errno == EBUSY)
goto repeat;
if (errno == EINTR)
@@ -5569,7 +5575,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
/* If we collide with an already moved fd... */
if (fd == sq->two_fd[i].moved_to) {
- new_fd = fcntl_F_DUPFD(fd, avoid_fd);
+ new_fd = dup_CLOEXEC(fd, avoid_fd);
sq->two_fd[i].moved_to = new_fd;
TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
if (new_fd < 0) /* what? */
@@ -5584,7 +5590,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
}
/* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
- new_fd = fcntl_F_DUPFD(fd, avoid_fd);
+ new_fd = dup_CLOEXEC(fd, avoid_fd);
TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
if (new_fd < 0) {
if (errno != EBADF)
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right
new file mode 100644
index 0000000..46ab7f5
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right
@@ -0,0 +1,5 @@
+/proc/self/fd
+/proc/self/fd/0
+/proc/self/fd/1
+/proc/self/fd/2
+/proc/self/fd/3
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests
new file mode 100755
index 0000000..544c810
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests
@@ -0,0 +1,6 @@
+# The "find" should not see "saved" (duplicated) fd #1
+# Explicitly use bbox find, since other implementations of "find"
+# may open other descriptors as well.
+busybox find /proc/self/fd >tmp_$$.out
+cat tmp_$$.out
+rm -f tmp_$$.out
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right
new file mode 100644
index 0000000..46ab7f5
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right
@@ -0,0 +1,5 @@
+/proc/self/fd
+/proc/self/fd/0
+/proc/self/fd/1
+/proc/self/fd/2
+/proc/self/fd/3
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests
new file mode 100755
index 0000000..43777ca
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests
@@ -0,0 +1,6 @@
+# The "find" should not see "saved" (duplicated) fd #1
+# Explicitly use bbox find, since other implementations of "find"
+# may open other descriptors as well.
+{ busybox find /proc/self/fd; } >tmp_$$.out
+cat tmp_$$.out
+rm -f tmp_$$.out
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right
new file mode 100644
index 0000000..46ab7f5
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right
@@ -0,0 +1,5 @@
+/proc/self/fd
+/proc/self/fd/0
+/proc/self/fd/1
+/proc/self/fd/2
+/proc/self/fd/3
diff --git a/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests
new file mode 100755
index 0000000..0a21173
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests
@@ -0,0 +1,6 @@
+# The "find" should not see "saved" (duplicated) fd #1
+# Explicitly use bbox find, since other implementations of "find"
+# may open other descriptors as well.
+{ busybox find /proc/self/fd; true; } >tmp_$$.out
+cat tmp_$$.out
+rm -f tmp_$$.out
diff --git a/shell/hush.c b/shell/hush.c
index 6e64efb..012ec21 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1501,12 +1501,15 @@ static void free_strings(char **strings)
free(strings);
}
-static int fcntl_F_DUPFD(int fd, int avoid_fd)
+static int dup_CLOEXEC(int fd, int avoid_fd)
{
int newfd;
repeat:
- newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
- if (newfd < 0) {
+ newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
+ if (newfd >= 0) {
+ if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
+ fcntl(newfd, F_SETFD, FD_CLOEXEC);
+ } else { /* newfd < 0 */
if (errno == EBUSY)
goto repeat;
if (errno == EINTR)
@@ -6890,7 +6893,7 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
if (sq) for (; sq[i].orig_fd >= 0; i++) {
/* If we collide with an already moved fd... */
if (fd == sq[i].moved_to) {
- sq[i].moved_to = fcntl_F_DUPFD(sq[i].moved_to, avoid_fd);
+ sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd);
debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
if (sq[i].moved_to < 0) /* what? */
xfunc_die();
@@ -6904,7 +6907,7 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
}
/* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
- moved_to = fcntl_F_DUPFD(fd, avoid_fd);
+ moved_to = dup_CLOEXEC(fd, avoid_fd);
debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
if (moved_to < 0 && errno != EBADF)
xfunc_die();
@@ -7622,6 +7625,10 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
*/
close_saved_fds_and_FILE_fds();
//FIXME: should also close saved redir fds
+//This casuses test failures in
+//redir_children_should_not_see_saved_fd_2.tests
+//redir_children_should_not_see_saved_fd_3.tests
+//if you replace "busybox find" with just "find" in them
/* Without this, "rm -i FILE" can't be ^C'ed: */
switch_off_special_sigs(G.special_sig_mask);
debug_printf_exec("running applet '%s'\n", argv[0]);
@@ -9347,7 +9354,7 @@ int hush_main(int argc, char **argv)
G_saved_tty_pgrp = 0;
/* try to dup stdin to high fd#, >= 255 */
- G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254);
+ G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
if (G_interactive_fd < 0) {
/* try to dup to any fd */
G_interactive_fd = dup(STDIN_FILENO);
@@ -9420,10 +9427,10 @@ int hush_main(int argc, char **argv)
#elif ENABLE_HUSH_INTERACTIVE
/* No job control compiled in, only prompt/line editing */
if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
- G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254);
+ G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
if (G_interactive_fd < 0) {
/* try to dup to any fd */
- G_interactive_fd = dup(STDIN_FILENO);
+ G_interactive_fd = dup_CLOEXEC(STDIN_FILENO);
if (G_interactive_fd < 0)
/* give up */
G_interactive_fd = 0;
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right
new file mode 100644
index 0000000..46ab7f5
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right
@@ -0,0 +1,5 @@
+/proc/self/fd
+/proc/self/fd/0
+/proc/self/fd/1
+/proc/self/fd/2
+/proc/self/fd/3
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests
new file mode 100755
index 0000000..544c810
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests
@@ -0,0 +1,6 @@
+# The "find" should not see "saved" (duplicated) fd #1
+# Explicitly use bbox find, since other implementations of "find"
+# may open other descriptors as well.
+busybox find /proc/self/fd >tmp_$$.out
+cat tmp_$$.out
+rm -f tmp_$$.out
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right
new file mode 100644
index 0000000..46ab7f5
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right
@@ -0,0 +1,5 @@
+/proc/self/fd
+/proc/self/fd/0
+/proc/self/fd/1
+/proc/self/fd/2
+/proc/self/fd/3
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests
new file mode 100755
index 0000000..43777ca
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests
@@ -0,0 +1,6 @@
+# The "find" should not see "saved" (duplicated) fd #1
+# Explicitly use bbox find, since other implementations of "find"
+# may open other descriptors as well.
+{ busybox find /proc/self/fd; } >tmp_$$.out
+cat tmp_$$.out
+rm -f tmp_$$.out
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right
new file mode 100644
index 0000000..46ab7f5
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right
@@ -0,0 +1,5 @@
+/proc/self/fd
+/proc/self/fd/0
+/proc/self/fd/1
+/proc/self/fd/2
+/proc/self/fd/3
diff --git a/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests
new file mode 100755
index 0000000..0a21173
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests
@@ -0,0 +1,6 @@
+# The "find" should not see "saved" (duplicated) fd #1
+# Explicitly use bbox find, since other implementations of "find"
+# may open other descriptors as well.
+{ busybox find /proc/self/fd; true; } >tmp_$$.out
+cat tmp_$$.out
+rm -f tmp_$$.out