From 568cabf98a11e2e594243a309a9ffd7729a2b213 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Tue, 3 Jan 2017 11:18:23 +0100 Subject: ash: fix error code regression The commit 'ash,hush: set exit code 127 in "sh /does/not/exist" case' only partly implemented the dash commit '[ERROR] Allow the originator of EXERROR to set the exit status'. This resulted in incorrect error codes for a syntax error: $ ) $ echo $? 0 or a redirection error for a special builtin: $ rm -f xxx $ eval cat Reported-by: Martijn Dekker Signed-off-by: Denys Vlasenko --- shell/ash_test/ash-misc/exitcode2.right | 4 ++++ shell/ash_test/ash-misc/exitcode2.tests | 12 ++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 shell/ash_test/ash-misc/exitcode2.right create mode 100755 shell/ash_test/ash-misc/exitcode2.tests (limited to 'shell/ash_test') diff --git a/shell/ash_test/ash-misc/exitcode2.right b/shell/ash_test/ash-misc/exitcode2.right new file mode 100644 index 000000000..f7cb983c6 --- /dev/null +++ b/shell/ash_test/ash-misc/exitcode2.right @@ -0,0 +1,4 @@ +./test.sh: line 1: syntax error: unexpected ")" +Done:2 +./exitcode2.tests: line 11: can't open does_not_exist: no such file +Done:1 diff --git a/shell/ash_test/ash-misc/exitcode2.tests b/shell/ash_test/ash-misc/exitcode2.tests new file mode 100755 index 000000000..79a6ebd50 --- /dev/null +++ b/shell/ash_test/ash-misc/exitcode2.tests @@ -0,0 +1,12 @@ +# syntax error should return status 2 +cat >test.sh < Date: Sat, 7 Jan 2017 10:15:01 +0100 Subject: ash: fix open fds leaking in redirects. Closes 9561 commit e19923f6652a638ac39c84012e97f52cf5a7568e deleted clearredir() call in shellexec(): ash: [REDIR] Remove redundant CLOEXEC calls Upstream commit: Now that we're marking file descriptors as CLOEXEC in savefd, we no longer need to close them on exec or in setinputfd. but it missed one place where we don't set CLOEXEC. Fixing this. Signed-off-by: Denys Vlasenko --- shell/ash.c | 11 +++++++---- shell/ash_test/ash-redir/redir_leak.right | 6 ++++++ shell/ash_test/ash-redir/redir_leak.tests | 10 ++++++++++ shell/hush_test/hush-redir/redir_leak.right | 6 ++++++ shell/hush_test/hush-redir/redir_leak.tests | 10 ++++++++++ 5 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 shell/ash_test/ash-redir/redir_leak.right create mode 100755 shell/ash_test/ash-redir/redir_leak.tests create mode 100644 shell/hush_test/hush-redir/redir_leak.right create mode 100755 shell/hush_test/hush-redir/redir_leak.tests (limited to 'shell/ash_test') 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) /* Careful to not accidentally "save" * to the same fd as right side fd in N>&M */ int minfd = right_fd < 10 ? 10 : right_fd + 1; +#if defined(F_DUPFD_CLOEXEC) + i = fcntl(fd, F_DUPFD_CLOEXEC, minfd); +#else i = fcntl(fd, F_DUPFD, minfd); -/* You'd expect copy to be CLOEXECed. Currently these extra "saved" fds - * are closed in popredir() in the child, preventing them from leaking - * into child. (popredir() also cleans up the mess in case of failures) - */ +#endif if (i == -1) { i = errno; if (i != EBADF) { @@ -5445,6 +5445,9 @@ redirect(union node *redir, int flags) remember_to_close: i = CLOSED; } else { /* fd is open, save its copy */ +#if !defined(F_DUPFD_CLOEXEC) + fcntl(i, F_SETFD, FD_CLOEXEC); +#endif /* "exec fd>&-" should not close fds * which point to script file(s). * 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 @@ +4 +4 +4 +4 +4 +4 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 @@ +# Each of these should show only four lines: +# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls. +# This test detects bugs where redirects leave stray open fds. + +ls -1 /proc/self/fd | wc -l +ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l +ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l +echo "`ls -1 /proc/self/fd `" | wc -l +echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l +echo "`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 @@ +4 +4 +4 +4 +4 +4 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 @@ +# Each of these should show only four lines: +# fds 0,1,2 are stdio; fd 3 is open by opendir() in ls. +# This test detects bugs where redirects leave stray open fds. + +ls -1 /proc/self/fd | wc -l +ls -1 /proc/self/fd >/proc/self/fd/1 | wc -l +ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 | wc -l +echo "`ls -1 /proc/self/fd `" | wc -l +echo "`ls -1 /proc/self/fd >/proc/self/fd/1 `" | wc -l +echo "`ls -1 /proc/self/fd >/proc/self/fd/1 2>&1 `" | wc -l -- cgit v1.2.3-55-g6feb