aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2018-03-28 18:35:07 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2018-04-01 13:04:11 +0200
commitb1aa377a3f23e5e547cd142bb82a81b811c788a2 (patch)
treed7e8b99fcfca0a3e558c48af6021ce5fab6fef1a
parent2afdcc77ccdd60f2632d2ee79c47517536a14a07 (diff)
downloadbusybox-w32-b1aa377a3f23e5e547cd142bb82a81b811c788a2.tar.gz
busybox-w32-b1aa377a3f23e5e547cd142bb82a81b811c788a2.tar.bz2
busybox-w32-b1aa377a3f23e5e547cd142bb82a81b811c788a2.zip
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>
-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 b73a79975..699b6c0ee 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -239,6 +239,9 @@ typedef long arith_t;
239# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__ 239# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
240#endif 240#endif
241 241
242#ifndef F_DUPFD_CLOEXEC
243# define F_DUPFD_CLOEXEC F_DUPFD
244#endif
242#ifndef PIPE_BUF 245#ifndef PIPE_BUF
243# define PIPE_BUF 4096 /* amount of buffering in a pipe */ 246# define PIPE_BUF 4096 /* amount of buffering in a pipe */
244#endif 247#endif
@@ -5392,12 +5395,15 @@ dup2_or_raise(int from, int to)
5392 return newfd; 5395 return newfd;
5393} 5396}
5394static int 5397static int
5395fcntl_F_DUPFD(int fd, int avoid_fd) 5398dup_CLOEXEC(int fd, int avoid_fd)
5396{ 5399{
5397 int newfd; 5400 int newfd;
5398 repeat: 5401 repeat:
5399 newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); 5402 newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
5400 if (newfd < 0) { 5403 if (newfd >= 0) {
5404 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
5405 fcntl(newfd, F_SETFD, FD_CLOEXEC);
5406 } else { /* newfd < 0 */
5401 if (errno == EBUSY) 5407 if (errno == EBUSY)
5402 goto repeat; 5408 goto repeat;
5403 if (errno == EINTR) 5409 if (errno == EINTR)
@@ -5513,7 +5519,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5513 for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) { 5519 for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
5514 /* If we collide with an already moved fd... */ 5520 /* If we collide with an already moved fd... */
5515 if (fd == sq->two_fd[i].moved_to) { 5521 if (fd == sq->two_fd[i].moved_to) {
5516 new_fd = fcntl_F_DUPFD(fd, avoid_fd); 5522 new_fd = dup_CLOEXEC(fd, avoid_fd);
5517 sq->two_fd[i].moved_to = new_fd; 5523 sq->two_fd[i].moved_to = new_fd;
5518 TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd)); 5524 TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
5519 if (new_fd < 0) /* what? */ 5525 if (new_fd < 0) /* what? */
@@ -5528,7 +5534,7 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
5528 } 5534 }
5529 5535
5530 /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */ 5536 /* If this fd is open, we move and remember it; if it's closed, new_fd = CLOSED (-1) */
5531 new_fd = fcntl_F_DUPFD(fd, avoid_fd); 5537 new_fd = dup_CLOEXEC(fd, avoid_fd);
5532 TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd)); 5538 TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
5533 if (new_fd < 0) { 5539 if (new_fd < 0) {
5534 if (errno != EBADF) 5540 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 000000000..46ab7f5d1
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.right
@@ -0,0 +1,5 @@
1/proc/self/fd
2/proc/self/fd/0
3/proc/self/fd/1
4/proc/self/fd/2
5/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 000000000..544c810e3
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests
@@ -0,0 +1,6 @@
1# The "find" should not see "saved" (duplicated) fd #1
2# Explicitly use bbox find, since other implementations of "find"
3# may open other descriptors as well.
4busybox find /proc/self/fd >tmp_$$.out
5cat tmp_$$.out
6rm -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 000000000..46ab7f5d1
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.right
@@ -0,0 +1,5 @@
1/proc/self/fd
2/proc/self/fd/0
3/proc/self/fd/1
4/proc/self/fd/2
5/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 000000000..43777cade
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests
@@ -0,0 +1,6 @@
1# The "find" should not see "saved" (duplicated) fd #1
2# Explicitly use bbox find, since other implementations of "find"
3# may open other descriptors as well.
4{ busybox find /proc/self/fd; } >tmp_$$.out
5cat tmp_$$.out
6rm -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 000000000..46ab7f5d1
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.right
@@ -0,0 +1,5 @@
1/proc/self/fd
2/proc/self/fd/0
3/proc/self/fd/1
4/proc/self/fd/2
5/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 000000000..0a21173bd
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests
@@ -0,0 +1,6 @@
1# The "find" should not see "saved" (duplicated) fd #1
2# Explicitly use bbox find, since other implementations of "find"
3# may open other descriptors as well.
4{ busybox find /proc/self/fd; true; } >tmp_$$.out
5cat tmp_$$.out
6rm -f tmp_$$.out
diff --git a/shell/hush.c b/shell/hush.c
index df1b046ab..b76b8fda4 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -1478,12 +1478,15 @@ static void free_strings(char **strings)
1478 free(strings); 1478 free(strings);
1479} 1479}
1480 1480
1481static int fcntl_F_DUPFD(int fd, int avoid_fd) 1481static int dup_CLOEXEC(int fd, int avoid_fd)
1482{ 1482{
1483 int newfd; 1483 int newfd;
1484 repeat: 1484 repeat:
1485 newfd = fcntl(fd, F_DUPFD, avoid_fd + 1); 1485 newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
1486 if (newfd < 0) { 1486 if (newfd >= 0) {
1487 if (F_DUPFD_CLOEXEC == F_DUPFD) /* if old libc (w/o F_DUPFD_CLOEXEC) */
1488 fcntl(newfd, F_SETFD, FD_CLOEXEC);
1489 } else { /* newfd < 0 */
1487 if (errno == EBUSY) 1490 if (errno == EBUSY)
1488 goto repeat; 1491 goto repeat;
1489 if (errno == EINTR) 1492 if (errno == EINTR)
@@ -6766,7 +6769,7 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
6766 if (sq) for (; sq[i].orig_fd >= 0; i++) { 6769 if (sq) for (; sq[i].orig_fd >= 0; i++) {
6767 /* If we collide with an already moved fd... */ 6770 /* If we collide with an already moved fd... */
6768 if (fd == sq[i].moved_to) { 6771 if (fd == sq[i].moved_to) {
6769 sq[i].moved_to = fcntl_F_DUPFD(sq[i].moved_to, avoid_fd); 6772 sq[i].moved_to = dup_CLOEXEC(sq[i].moved_to, avoid_fd);
6770 debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to); 6773 debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
6771 if (sq[i].moved_to < 0) /* what? */ 6774 if (sq[i].moved_to < 0) /* what? */
6772 xfunc_die(); 6775 xfunc_die();
@@ -6780,7 +6783,7 @@ static struct squirrel *add_squirrel(struct squirrel *sq, int fd, int avoid_fd)
6780 } 6783 }
6781 6784
6782 /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */ 6785 /* If this fd is open, we move and remember it; if it's closed, moved_to = -1 */
6783 moved_to = fcntl_F_DUPFD(fd, avoid_fd); 6786 moved_to = dup_CLOEXEC(fd, avoid_fd);
6784 debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to); 6787 debug_printf_redir("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, moved_to);
6785 if (moved_to < 0 && errno != EBADF) 6788 if (moved_to < 0 && errno != EBADF)
6786 xfunc_die(); 6789 xfunc_die();
@@ -7429,6 +7432,10 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
7429 */ 7432 */
7430 close_saved_fds_and_FILE_fds(); 7433 close_saved_fds_and_FILE_fds();
7431//FIXME: should also close saved redir fds 7434//FIXME: should also close saved redir fds
7435//This casuses test failures in
7436//redir_children_should_not_see_saved_fd_2.tests
7437//redir_children_should_not_see_saved_fd_3.tests
7438//if you replace "busybox find" with just "find" in them
7432 /* Without this, "rm -i FILE" can't be ^C'ed: */ 7439 /* Without this, "rm -i FILE" can't be ^C'ed: */
7433 switch_off_special_sigs(G.special_sig_mask); 7440 switch_off_special_sigs(G.special_sig_mask);
7434 debug_printf_exec("running applet '%s'\n", argv[0]); 7441 debug_printf_exec("running applet '%s'\n", argv[0]);
@@ -9133,7 +9140,7 @@ int hush_main(int argc, char **argv)
9133 G_saved_tty_pgrp = 0; 9140 G_saved_tty_pgrp = 0;
9134 9141
9135 /* try to dup stdin to high fd#, >= 255 */ 9142 /* try to dup stdin to high fd#, >= 255 */
9136 G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254); 9143 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
9137 if (G_interactive_fd < 0) { 9144 if (G_interactive_fd < 0) {
9138 /* try to dup to any fd */ 9145 /* try to dup to any fd */
9139 G_interactive_fd = dup(STDIN_FILENO); 9146 G_interactive_fd = dup(STDIN_FILENO);
@@ -9206,10 +9213,10 @@ int hush_main(int argc, char **argv)
9206#elif ENABLE_HUSH_INTERACTIVE 9213#elif ENABLE_HUSH_INTERACTIVE
9207 /* No job control compiled in, only prompt/line editing */ 9214 /* No job control compiled in, only prompt/line editing */
9208 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { 9215 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
9209 G_interactive_fd = fcntl_F_DUPFD(STDIN_FILENO, 254); 9216 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO, 254);
9210 if (G_interactive_fd < 0) { 9217 if (G_interactive_fd < 0) {
9211 /* try to dup to any fd */ 9218 /* try to dup to any fd */
9212 G_interactive_fd = dup(STDIN_FILENO); 9219 G_interactive_fd = dup_CLOEXEC(STDIN_FILENO);
9213 if (G_interactive_fd < 0) 9220 if (G_interactive_fd < 0)
9214 /* give up */ 9221 /* give up */
9215 G_interactive_fd = 0; 9222 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 000000000..46ab7f5d1
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.right
@@ -0,0 +1,5 @@
1/proc/self/fd
2/proc/self/fd/0
3/proc/self/fd/1
4/proc/self/fd/2
5/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 000000000..544c810e3
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_1.tests
@@ -0,0 +1,6 @@
1# The "find" should not see "saved" (duplicated) fd #1
2# Explicitly use bbox find, since other implementations of "find"
3# may open other descriptors as well.
4busybox find /proc/self/fd >tmp_$$.out
5cat tmp_$$.out
6rm -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 000000000..46ab7f5d1
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.right
@@ -0,0 +1,5 @@
1/proc/self/fd
2/proc/self/fd/0
3/proc/self/fd/1
4/proc/self/fd/2
5/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 000000000..43777cade
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_2.tests
@@ -0,0 +1,6 @@
1# The "find" should not see "saved" (duplicated) fd #1
2# Explicitly use bbox find, since other implementations of "find"
3# may open other descriptors as well.
4{ busybox find /proc/self/fd; } >tmp_$$.out
5cat tmp_$$.out
6rm -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 000000000..46ab7f5d1
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.right
@@ -0,0 +1,5 @@
1/proc/self/fd
2/proc/self/fd/0
3/proc/self/fd/1
4/proc/self/fd/2
5/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 000000000..0a21173bd
--- /dev/null
+++ b/shell/hush_test/hush-redir/redir_children_should_not_see_saved_fd_3.tests
@@ -0,0 +1,6 @@
1# The "find" should not see "saved" (duplicated) fd #1
2# Explicitly use bbox find, since other implementations of "find"
3# may open other descriptors as well.
4{ busybox find /proc/self/fd; true; } >tmp_$$.out
5cat tmp_$$.out
6rm -f tmp_$$.out