diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-25 13:34:05 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-07-25 13:34:05 +0000 |
commit | 6a0ad2506116f4ddc3f9f617a90ba04a57eeef88 (patch) | |
tree | bb40f8aa8574d4aef536cfe930517c0bf44e28a7 | |
parent | 0f99d49ae680e675809428deace3c4fe839d323c (diff) | |
download | busybox-w32-6a0ad2506116f4ddc3f9f617a90ba04a57eeef88.tar.gz busybox-w32-6a0ad2506116f4ddc3f9f617a90ba04a57eeef88.tar.bz2 busybox-w32-6a0ad2506116f4ddc3f9f617a90ba04a57eeef88.zip |
ash: dont allow e.g. exec <&10 to attach to stript's fd!
function old new delta
is_hidden_fd - 61 +61
redirect 1135 1164 +29
popstring 134 140 +6
printf_main 635 637 +2
evalvar 1374 1376 +2
echo_main 294 296 +2
------------------------------------------------------------------------------
(add/remove: 1/0 grow/shrink: 5/0 up/down: 102/0) Total: 102 bytes
-rw-r--r-- | coreutils/echo.c | 11 | ||||
-rw-r--r-- | coreutils/printf.c | 7 | ||||
-rw-r--r-- | shell/ash.c | 47 |
3 files changed, 47 insertions, 18 deletions
diff --git a/coreutils/echo.c b/coreutils/echo.c index 36cb6b3af..decca095f 100644 --- a/coreutils/echo.c +++ b/coreutils/echo.c | |||
@@ -46,8 +46,11 @@ int echo_main(int argc UNUSED_PARAM, char **argv) | |||
46 | * even if libc receives EBADF on write attempts, it feels determined | 46 | * even if libc receives EBADF on write attempts, it feels determined |
47 | * to output data no matter what. So it will try later, | 47 | * to output data no matter what. So it will try later, |
48 | * and possibly will clobber future output. Not good. */ | 48 | * and possibly will clobber future output. Not good. */ |
49 | if (dup2(1, 1) != 1) | 49 | // TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR? |
50 | return -1; | 50 | if (fcntl(1, F_GETFL) == -1) |
51 | return 1; /* match coreutils 6.10 (sans error msg to stderr) */ | ||
52 | //if (dup2(1, 1) != 1) - old way | ||
53 | // return 1; | ||
51 | 54 | ||
52 | arg = *++argv; | 55 | arg = *++argv; |
53 | if (!arg) | 56 | if (!arg) |
@@ -58,8 +61,8 @@ int echo_main(int argc UNUSED_PARAM, char **argv) | |||
58 | char eflag = 0; | 61 | char eflag = 0; |
59 | 62 | ||
60 | /* We must check that stdout is not closed. */ | 63 | /* We must check that stdout is not closed. */ |
61 | if (dup2(1, 1) != 1) | 64 | if (fcntl(1, F_GETFL) == -1) |
62 | return -1; | 65 | return 1; |
63 | 66 | ||
64 | while (1) { | 67 | while (1) { |
65 | arg = *++argv; | 68 | arg = *++argv; |
diff --git a/coreutils/printf.c b/coreutils/printf.c index 72acbc751..76524f706 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c | |||
@@ -348,8 +348,11 @@ int printf_main(int argc UNUSED_PARAM, char **argv) | |||
348 | * even if libc receives EBADF on write attempts, it feels determined | 348 | * even if libc receives EBADF on write attempts, it feels determined |
349 | * to output data no matter what. So it will try later, | 349 | * to output data no matter what. So it will try later, |
350 | * and possibly will clobber future output. Not good. */ | 350 | * and possibly will clobber future output. Not good. */ |
351 | if (dup2(1, 1) != 1) | 351 | // TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR? |
352 | return -1; | 352 | if (fcntl(1, F_GETFL) == -1) |
353 | return 1; /* match coreutils 6.10 (sans error msg to stderr) */ | ||
354 | //if (dup2(1, 1) != 1) - old way | ||
355 | // return 1; | ||
353 | 356 | ||
354 | /* bash builtin errors out on "printf '-%s-\n' foo", | 357 | /* bash builtin errors out on "printf '-%s-\n' foo", |
355 | * coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo". | 358 | * coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo". |
diff --git a/shell/ash.c b/shell/ash.c index bd2433c88..11174683e 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -4889,7 +4889,7 @@ static int need_to_remember(struct redirtab *rp, int fd) | |||
4889 | { | 4889 | { |
4890 | int i; | 4890 | int i; |
4891 | 4891 | ||
4892 | if (!rp) /* remebering was not requested */ | 4892 | if (!rp) /* remembering was not requested */ |
4893 | return 0; | 4893 | return 0; |
4894 | 4894 | ||
4895 | for (i = 0; i < rp->pair_count; i++) { | 4895 | for (i = 0; i < rp->pair_count; i++) { |
@@ -4901,6 +4901,28 @@ static int need_to_remember(struct redirtab *rp, int fd) | |||
4901 | return 1; | 4901 | return 1; |
4902 | } | 4902 | } |
4903 | 4903 | ||
4904 | /* "hidden" fd is a fd used to read scripts, or a copy of such */ | ||
4905 | static int is_hidden_fd(struct redirtab *rp, int fd) | ||
4906 | { | ||
4907 | int i; | ||
4908 | struct parsefile *pf = g_parsefile; | ||
4909 | while (pf) { | ||
4910 | if (fd == pf->fd) { | ||
4911 | return 1; | ||
4912 | } | ||
4913 | pf = pf->prev; | ||
4914 | } | ||
4915 | if (!rp) | ||
4916 | return 0; | ||
4917 | fd |= COPYFD_RESTORE; | ||
4918 | for (i = 0; i < rp->pair_count; i++) { | ||
4919 | if (rp->two_fd[i].copy == fd) { | ||
4920 | return 1; | ||
4921 | } | ||
4922 | } | ||
4923 | return 0; | ||
4924 | } | ||
4925 | |||
4904 | /* | 4926 | /* |
4905 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, | 4927 | * Process a list of redirection commands. If the REDIR_PUSH flag is set, |
4906 | * old file descriptors are stashed away so that the redirection can be | 4928 | * old file descriptors are stashed away so that the redirection can be |
@@ -4950,8 +4972,15 @@ redirect(union node *redir, int flags) | |||
4950 | do { | 4972 | do { |
4951 | fd = redir->nfile.fd; | 4973 | fd = redir->nfile.fd; |
4952 | if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { | 4974 | if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { |
4953 | if (redir->ndup.dupfd == fd) | 4975 | int right_fd = redir->ndup.dupfd; |
4954 | continue; /* redirect from/to same file descriptor */ | 4976 | /* redirect from/to same file descriptor? */ |
4977 | if (right_fd == fd) | ||
4978 | continue; | ||
4979 | /* echo >&10 and 10 is a fd opened to the sh script? */ | ||
4980 | if (is_hidden_fd(sv, right_fd)) { | ||
4981 | errno = EBADF; /* as if it is closed */ | ||
4982 | ash_msg_and_raise_error("%d: %m", right_fd); | ||
4983 | } | ||
4955 | newfd = -1; | 4984 | newfd = -1; |
4956 | } else { | 4985 | } else { |
4957 | newfd = openredirect(redir); /* always >= 0 */ | 4986 | newfd = openredirect(redir); /* always >= 0 */ |
@@ -4988,14 +5017,8 @@ redirect(union node *redir, int flags) | |||
4988 | /* "exec fd>&-" should not close fds | 5017 | /* "exec fd>&-" should not close fds |
4989 | * which point to script file(s). | 5018 | * which point to script file(s). |
4990 | * Force them to be restored afterwards */ | 5019 | * Force them to be restored afterwards */ |
4991 | struct parsefile *pf = g_parsefile; | 5020 | if (is_hidden_fd(sv, fd)) |
4992 | while (pf) { | 5021 | i |= COPYFD_RESTORE; |
4993 | if (fd == pf->fd) { | ||
4994 | i |= COPYFD_RESTORE; | ||
4995 | break; | ||
4996 | } | ||
4997 | pf = pf->prev; | ||
4998 | } | ||
4999 | } | 5022 | } |
5000 | if (fd == 2) | 5023 | if (fd == 2) |
5001 | copied_fd2 = i; | 5024 | copied_fd2 = i; |
@@ -9026,7 +9049,7 @@ static int | |||
9026 | preadfd(void) | 9049 | preadfd(void) |
9027 | { | 9050 | { |
9028 | int nr; | 9051 | int nr; |
9029 | char *buf = g_parsefile->buf; | 9052 | char *buf = g_parsefile->buf; |
9030 | parsenextc = buf; | 9053 | parsenextc = buf; |
9031 | 9054 | ||
9032 | #if ENABLE_FEATURE_EDITING | 9055 | #if ENABLE_FEATURE_EDITING |