aboutsummaryrefslogtreecommitdiff
path: root/shell
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-07-24 22:34:43 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-07-24 22:34:43 +0000
commit22f741484391c3b2fd94881fd41c8c0df9749e95 (patch)
tree6d8f9ac524cefa7ebb0edeeb5e9545e4ada53e29 /shell
parent5a867317bb1cbf36d396d9cdb552212607dcc2b1 (diff)
downloadbusybox-22f741484391c3b2fd94881fd41c8c0df9749e95.tar.gz
ash: prevent exec NN>&- from closing fd used for script reading
Diffstat (limited to 'shell')
-rw-r--r--shell/ash.c33
-rw-r--r--shell/ash_test/ash-redir/redir4.right1
-rwxr-xr-xshell/ash_test/ash-redir/redir4.tests72
3 files changed, 98 insertions, 8 deletions
diff --git a/shell/ash.c b/shell/ash.c
index ec3bd0927..bd2433c88 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -4848,7 +4848,10 @@ openredirect(union node *redir)
*/
/* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD).
* old code was doing close(to) prior to copyfd() to achieve the same */
-#define COPYFD_EXACT ((int)~INT_MAX)
+enum {
+ COPYFD_EXACT = (int)~(INT_MAX),
+ COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1),
+};
static int
copyfd(int from, int to)
{
@@ -4981,7 +4984,19 @@ redirect(union node *redir, int flags)
/* EBADF: it is not open - good, remember to close it */
remember_to_close:
i = CLOSED;
- } /* else: fd is open, save its copy */
+ } else { /* fd is open, save its copy */
+ /* "exec fd>&-" should not close fds
+ * which point to script file(s).
+ * Force them to be restored afterwards */
+ struct parsefile *pf = g_parsefile;
+ while (pf) {
+ if (fd == pf->fd) {
+ i |= COPYFD_RESTORE;
+ break;
+ }
+ pf = pf->prev;
+ }
+ }
if (fd == 2)
copied_fd2 = i;
sv->two_fd[sv_pos].orig = fd;
@@ -4990,7 +5005,7 @@ redirect(union node *redir, int flags)
}
if (newfd < 0) {
/* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */
- if (redir->ndup.dupfd < 0) { /* "NN>&-" */
+ if (redir->ndup.dupfd < 0) { /* "fd>&-" */
close(fd);
} else {
copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT);
@@ -5021,17 +5036,19 @@ popredir(int drop)
rp = redirlist;
for (i = 0; i < rp->pair_count; i++) {
int fd = rp->two_fd[i].orig;
- if (rp->two_fd[i].copy == CLOSED) {
+ int copy = rp->two_fd[i].copy;
+ if (copy == CLOSED) {
if (!drop)
close(fd);
continue;
}
- if (rp->two_fd[i].copy != EMPTY) {
- if (!drop) {
+ if (copy != EMPTY) {
+ if (!drop || (copy & COPYFD_RESTORE)) {
+ copy &= ~COPYFD_RESTORE;
/*close(fd);*/
- copyfd(rp->two_fd[i].copy, fd | COPYFD_EXACT);
+ copyfd(copy, fd | COPYFD_EXACT);
}
- close(rp->two_fd[i].copy);
+ close(copy);
}
}
redirlist = rp->next;
diff --git a/shell/ash_test/ash-redir/redir4.right b/shell/ash_test/ash-redir/redir4.right
new file mode 100644
index 000000000..d86bac9de
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir4.right
@@ -0,0 +1 @@
+OK
diff --git a/shell/ash_test/ash-redir/redir4.tests b/shell/ash_test/ash-redir/redir4.tests
new file mode 100755
index 000000000..4bdf5ae27
--- /dev/null
+++ b/shell/ash_test/ash-redir/redir4.tests
@@ -0,0 +1,72 @@
+# ash uses fd 10 (usually) for reading the script
+exec 13>&-
+exec 12>&-
+exec 11>&-
+exec 10>&-
+# some amount of input is prefetched.
+# make sure final echo is far enough to not be prefetched.
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+###############################################################
+echo "OK"