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>
This commit is contained in:
parent
e4defe826b
commit
9acd63c92c
16
shell/ash.c
16
shell/ash.c
@ -255,6 +255,9 @@ typedef long arith_t;
|
|||||||
# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
|
# define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef F_DUPFD_CLOEXEC
|
||||||
|
# define F_DUPFD_CLOEXEC F_DUPFD
|
||||||
|
#endif
|
||||||
#ifndef PIPE_BUF
|
#ifndef PIPE_BUF
|
||||||
# define PIPE_BUF 4096 /* amount of buffering in a pipe */
|
# define PIPE_BUF 4096 /* amount of buffering in a pipe */
|
||||||
#endif
|
#endif
|
||||||
@ -5448,12 +5451,15 @@ dup2_or_raise(int from, int to)
|
|||||||
return newfd;
|
return newfd;
|
||||||
}
|
}
|
||||||
static int
|
static int
|
||||||
fcntl_F_DUPFD(int fd, int avoid_fd)
|
dup_CLOEXEC(int fd, int avoid_fd)
|
||||||
{
|
{
|
||||||
int newfd;
|
int newfd;
|
||||||
repeat:
|
repeat:
|
||||||
newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
|
newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
|
||||||
if (newfd < 0) {
|
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)
|
if (errno == EBUSY)
|
||||||
goto repeat;
|
goto repeat;
|
||||||
if (errno == EINTR)
|
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++) {
|
for (i = 0; sq->two_fd[i].orig_fd != EMPTY; i++) {
|
||||||
/* If we collide with an already moved fd... */
|
/* If we collide with an already moved fd... */
|
||||||
if (fd == sq->two_fd[i].moved_to) {
|
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;
|
sq->two_fd[i].moved_to = new_fd;
|
||||||
TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
|
TRACE(("redirect_fd %d: already busy, moving to %d\n", fd, new_fd));
|
||||||
if (new_fd < 0) /* what? */
|
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) */
|
/* 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));
|
TRACE(("redirect_fd %d: previous fd is moved to %d (-1 if it was closed)\n", fd, new_fd));
|
||||||
if (new_fd < 0) {
|
if (new_fd < 0) {
|
||||||
if (errno != EBADF)
|
if (errno != EBADF)
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
/proc/self/fd
|
||||||
|
/proc/self/fd/0
|
||||||
|
/proc/self/fd/1
|
||||||
|
/proc/self/fd/2
|
||||||
|
/proc/self/fd/3
|
6
shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests
Executable file
6
shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_1.tests
Executable file
@ -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
|
@ -0,0 +1,5 @@
|
|||||||
|
/proc/self/fd
|
||||||
|
/proc/self/fd/0
|
||||||
|
/proc/self/fd/1
|
||||||
|
/proc/self/fd/2
|
||||||
|
/proc/self/fd/3
|
6
shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests
Executable file
6
shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_2.tests
Executable file
@ -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
|
@ -0,0 +1,5 @@
|
|||||||
|
/proc/self/fd
|
||||||
|
/proc/self/fd/0
|
||||||
|
/proc/self/fd/1
|
||||||
|
/proc/self/fd/2
|
||||||
|
/proc/self/fd/3
|
6
shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests
Executable file
6
shell/ash_test/ash-redir/redir_children_should_not_see_saved_fd_3.tests
Executable file
@ -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
|
23
shell/hush.c
23
shell/hush.c
@ -1501,12 +1501,15 @@ static void free_strings(char **strings)
|
|||||||
free(strings);
|
free(strings);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fcntl_F_DUPFD(int fd, int avoid_fd)
|
static int dup_CLOEXEC(int fd, int avoid_fd)
|
||||||
{
|
{
|
||||||
int newfd;
|
int newfd;
|
||||||
repeat:
|
repeat:
|
||||||
newfd = fcntl(fd, F_DUPFD, avoid_fd + 1);
|
newfd = fcntl(fd, F_DUPFD_CLOEXEC, avoid_fd + 1);
|
||||||
if (newfd < 0) {
|
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)
|
if (errno == EBUSY)
|
||||||
goto repeat;
|
goto repeat;
|
||||||
if (errno == EINTR)
|
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 (sq) for (; sq[i].orig_fd >= 0; i++) {
|
||||||
/* If we collide with an already moved fd... */
|
/* If we collide with an already moved fd... */
|
||||||
if (fd == sq[i].moved_to) {
|
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);
|
debug_printf_redir("redirect_fd %d: already busy, moving to %d\n", fd, sq[i].moved_to);
|
||||||
if (sq[i].moved_to < 0) /* what? */
|
if (sq[i].moved_to < 0) /* what? */
|
||||||
xfunc_die();
|
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 */
|
/* 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);
|
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)
|
if (moved_to < 0 && errno != EBADF)
|
||||||
xfunc_die();
|
xfunc_die();
|
||||||
@ -7622,6 +7625,10 @@ static NOINLINE void pseudo_exec_argv(nommu_save_t *nommu_save,
|
|||||||
*/
|
*/
|
||||||
close_saved_fds_and_FILE_fds();
|
close_saved_fds_and_FILE_fds();
|
||||||
//FIXME: should also close saved redir 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: */
|
/* Without this, "rm -i FILE" can't be ^C'ed: */
|
||||||
switch_off_special_sigs(G.special_sig_mask);
|
switch_off_special_sigs(G.special_sig_mask);
|
||||||
debug_printf_exec("running applet '%s'\n", argv[0]);
|
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;
|
G_saved_tty_pgrp = 0;
|
||||||
|
|
||||||
/* try to dup stdin to high fd#, >= 255 */
|
/* 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) {
|
if (G_interactive_fd < 0) {
|
||||||
/* try to dup to any fd */
|
/* try to dup to any fd */
|
||||||
G_interactive_fd = dup(STDIN_FILENO);
|
G_interactive_fd = dup(STDIN_FILENO);
|
||||||
@ -9420,10 +9427,10 @@ int hush_main(int argc, char **argv)
|
|||||||
#elif ENABLE_HUSH_INTERACTIVE
|
#elif ENABLE_HUSH_INTERACTIVE
|
||||||
/* No job control compiled in, only prompt/line editing */
|
/* No job control compiled in, only prompt/line editing */
|
||||||
if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
|
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) {
|
if (G_interactive_fd < 0) {
|
||||||
/* try to dup to any fd */
|
/* try to dup to any fd */
|
||||||
G_interactive_fd = dup(STDIN_FILENO);
|
G_interactive_fd = dup_CLOEXEC(STDIN_FILENO);
|
||||||
if (G_interactive_fd < 0)
|
if (G_interactive_fd < 0)
|
||||||
/* give up */
|
/* give up */
|
||||||
G_interactive_fd = 0;
|
G_interactive_fd = 0;
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
/proc/self/fd
|
||||||
|
/proc/self/fd/0
|
||||||
|
/proc/self/fd/1
|
||||||
|
/proc/self/fd/2
|
||||||
|
/proc/self/fd/3
|
@ -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
|
@ -0,0 +1,5 @@
|
|||||||
|
/proc/self/fd
|
||||||
|
/proc/self/fd/0
|
||||||
|
/proc/self/fd/1
|
||||||
|
/proc/self/fd/2
|
||||||
|
/proc/self/fd/3
|
@ -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
|
@ -0,0 +1,5 @@
|
|||||||
|
/proc/self/fd
|
||||||
|
/proc/self/fd/0
|
||||||
|
/proc/self/fd/1
|
||||||
|
/proc/self/fd/2
|
||||||
|
/proc/self/fd/3
|
@ -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
|
Loading…
Reference in New Issue
Block a user