diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-24 22:34:43 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-24 22:34:43 +0000 |
commit | 22f741484391c3b2fd94881fd41c8c0df9749e95 (patch) | |
tree | 6d8f9ac524cefa7ebb0edeeb5e9545e4ada53e29 /shell/ash.c | |
parent | 5a867317bb1cbf36d396d9cdb552212607dcc2b1 (diff) | |
download | busybox-w32-22f741484391c3b2fd94881fd41c8c0df9749e95.tar.gz busybox-w32-22f741484391c3b2fd94881fd41c8c0df9749e95.tar.bz2 busybox-w32-22f741484391c3b2fd94881fd41c8c0df9749e95.zip |
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 ec3bd0927..bd2433c88 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -4848,7 +4848,10 @@ openredirect(union node *redir) | |||
4848 | */ | 4848 | */ |
4849 | /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD). | 4849 | /* 0x800..00: bit to set in "to" to request dup2 instead of fcntl(F_DUPFD). |
4850 | * old code was doing close(to) prior to copyfd() to achieve the same */ | 4850 | * old code was doing close(to) prior to copyfd() to achieve the same */ |
4851 | #define COPYFD_EXACT ((int)~INT_MAX) | 4851 | enum { |
4852 | COPYFD_EXACT = (int)~(INT_MAX), | ||
4853 | COPYFD_RESTORE = (int)((unsigned)COPYFD_EXACT >> 1), | ||
4854 | }; | ||
4852 | static int | 4855 | static int |
4853 | copyfd(int from, int to) | 4856 | copyfd(int from, int to) |
4854 | { | 4857 | { |
@@ -4981,7 +4984,19 @@ redirect(union node *redir, int flags) | |||
4981 | /* EBADF: it is not open - good, remember to close it */ | 4984 | /* EBADF: it is not open - good, remember to close it */ |
4982 | remember_to_close: | 4985 | remember_to_close: |
4983 | i = CLOSED; | 4986 | i = CLOSED; |
4984 | } /* else: fd is open, save its copy */ | 4987 | } else { /* fd is open, save its copy */ |
4988 | /* "exec fd>&-" should not close fds | ||
4989 | * which point to script file(s). | ||
4990 | * Force them to be restored afterwards */ | ||
4991 | struct parsefile *pf = g_parsefile; | ||
4992 | while (pf) { | ||
4993 | if (fd == pf->fd) { | ||
4994 | i |= COPYFD_RESTORE; | ||
4995 | break; | ||
4996 | } | ||
4997 | pf = pf->prev; | ||
4998 | } | ||
4999 | } | ||
4985 | if (fd == 2) | 5000 | if (fd == 2) |
4986 | copied_fd2 = i; | 5001 | copied_fd2 = i; |
4987 | sv->two_fd[sv_pos].orig = fd; | 5002 | sv->two_fd[sv_pos].orig = fd; |
@@ -4990,7 +5005,7 @@ redirect(union node *redir, int flags) | |||
4990 | } | 5005 | } |
4991 | if (newfd < 0) { | 5006 | if (newfd < 0) { |
4992 | /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */ | 5007 | /* NTOFD/NFROMFD: copy redir->ndup.dupfd to fd */ |
4993 | if (redir->ndup.dupfd < 0) { /* "NN>&-" */ | 5008 | if (redir->ndup.dupfd < 0) { /* "fd>&-" */ |
4994 | close(fd); | 5009 | close(fd); |
4995 | } else { | 5010 | } else { |
4996 | copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT); | 5011 | copyfd(redir->ndup.dupfd, fd | COPYFD_EXACT); |
@@ -5021,17 +5036,19 @@ popredir(int drop) | |||
5021 | rp = redirlist; | 5036 | rp = redirlist; |
5022 | for (i = 0; i < rp->pair_count; i++) { | 5037 | for (i = 0; i < rp->pair_count; i++) { |
5023 | int fd = rp->two_fd[i].orig; | 5038 | int fd = rp->two_fd[i].orig; |
5024 | if (rp->two_fd[i].copy == CLOSED) { | 5039 | int copy = rp->two_fd[i].copy; |
5040 | if (copy == CLOSED) { | ||
5025 | if (!drop) | 5041 | if (!drop) |
5026 | close(fd); | 5042 | close(fd); |
5027 | continue; | 5043 | continue; |
5028 | } | 5044 | } |
5029 | if (rp->two_fd[i].copy != EMPTY) { | 5045 | if (copy != EMPTY) { |
5030 | if (!drop) { | 5046 | if (!drop || (copy & COPYFD_RESTORE)) { |
5047 | copy &= ~COPYFD_RESTORE; | ||
5031 | /*close(fd);*/ | 5048 | /*close(fd);*/ |
5032 | copyfd(rp->two_fd[i].copy, fd | COPYFD_EXACT); | 5049 | copyfd(copy, fd | COPYFD_EXACT); |
5033 | } | 5050 | } |
5034 | close(rp->two_fd[i].copy); | 5051 | close(copy); |
5035 | } | 5052 | } |
5036 | } | 5053 | } |
5037 | redirlist = rp->next; | 5054 | redirlist = rp->next; |