diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2018-03-28 18:35:07 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2018-04-01 13:04:11 +0200 |
commit | b1aa377a3f23e5e547cd142bb82a81b811c788a2 (patch) | |
tree | d7e8b99fcfca0a3e558c48af6021ce5fab6fef1a | |
parent | 2afdcc77ccdd60f2632d2ee79c47517536a14a07 (diff) | |
download | busybox-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>
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 | } |
5394 | static int | 5397 | static int |
5395 | fcntl_F_DUPFD(int fd, int avoid_fd) | 5398 | dup_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. | ||
4 | busybox find /proc/self/fd >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | 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 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 | ||
5 | cat tmp_$$.out | ||
6 | 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 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 | ||
5 | cat tmp_$$.out | ||
6 | rm -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 | ||
1481 | static int fcntl_F_DUPFD(int fd, int avoid_fd) | 1481 | static 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. | ||
4 | busybox find /proc/self/fd >tmp_$$.out | ||
5 | cat tmp_$$.out | ||
6 | 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 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 | ||
5 | cat tmp_$$.out | ||
6 | 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 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 | ||
5 | cat tmp_$$.out | ||
6 | rm -f tmp_$$.out | ||