diff options
author | Denis Vlasenko | 2008-07-24 22:34:43 +0000 |
---|---|---|
committer | Denis Vlasenko | 2008-07-24 22:34:43 +0000 |
commit | 22f741484391c3b2fd94881fd41c8c0df9749e95 (patch) | |
tree | 6d8f9ac524cefa7ebb0edeeb5e9545e4ada53e29 /shell/ash.c | |
parent | 5a867317bb1cbf36d396d9cdb552212607dcc2b1 (diff) | |
download | busybox-22f741484391c3b2fd94881fd41c8c0df9749e95.zip busybox-22f741484391c3b2fd94881fd41c8c0df9749e95.tar.gz |
ash: prevent exec NN>&- from closing fd used for script reading
Diffstat (limited to 'shell/ash.c')
-rw-r--r-- | shell/ash.c | 33 |
1 files changed, 25 insertions, 8 deletions
diff --git a/shell/ash.c b/shell/ash.c index ec3bd09..bd2433c 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; |