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
This commit is contained in:
Denis Vlasenko 2008-07-25 13:34:05 +00:00
parent 0f99d49ae6
commit 6a0ad25061
3 changed files with 47 additions and 18 deletions

View File

@ -46,8 +46,11 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
* even if libc receives EBADF on write attempts, it feels determined
* to output data no matter what. So it will try later,
* and possibly will clobber future output. Not good. */
if (dup2(1, 1) != 1)
return -1;
// TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR?
if (fcntl(1, F_GETFL) == -1)
return 1; /* match coreutils 6.10 (sans error msg to stderr) */
//if (dup2(1, 1) != 1) - old way
// return 1;
arg = *++argv;
if (!arg)
@ -58,8 +61,8 @@ int echo_main(int argc UNUSED_PARAM, char **argv)
char eflag = 0;
/* We must check that stdout is not closed. */
if (dup2(1, 1) != 1)
return -1;
if (fcntl(1, F_GETFL) == -1)
return 1;
while (1) {
arg = *++argv;

View File

@ -348,8 +348,11 @@ int printf_main(int argc UNUSED_PARAM, char **argv)
* even if libc receives EBADF on write attempts, it feels determined
* to output data no matter what. So it will try later,
* and possibly will clobber future output. Not good. */
if (dup2(1, 1) != 1)
return -1;
// TODO: check fcntl() & O_ACCMODE == O_WRONLY or O_RDWR?
if (fcntl(1, F_GETFL) == -1)
return 1; /* match coreutils 6.10 (sans error msg to stderr) */
//if (dup2(1, 1) != 1) - old way
// return 1;
/* bash builtin errors out on "printf '-%s-\n' foo",
* coreutils-6.9 works. Both work with "printf -- '-%s-\n' foo".

View File

@ -4889,7 +4889,7 @@ static int need_to_remember(struct redirtab *rp, int fd)
{
int i;
if (!rp) /* remebering was not requested */
if (!rp) /* remembering was not requested */
return 0;
for (i = 0; i < rp->pair_count; i++) {
@ -4901,6 +4901,28 @@ static int need_to_remember(struct redirtab *rp, int fd)
return 1;
}
/* "hidden" fd is a fd used to read scripts, or a copy of such */
static int is_hidden_fd(struct redirtab *rp, int fd)
{
int i;
struct parsefile *pf = g_parsefile;
while (pf) {
if (fd == pf->fd) {
return 1;
}
pf = pf->prev;
}
if (!rp)
return 0;
fd |= COPYFD_RESTORE;
for (i = 0; i < rp->pair_count; i++) {
if (rp->two_fd[i].copy == fd) {
return 1;
}
}
return 0;
}
/*
* Process a list of redirection commands. If the REDIR_PUSH flag is set,
* old file descriptors are stashed away so that the redirection can be
@ -4950,8 +4972,15 @@ redirect(union node *redir, int flags)
do {
fd = redir->nfile.fd;
if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
if (redir->ndup.dupfd == fd)
continue; /* redirect from/to same file descriptor */
int right_fd = redir->ndup.dupfd;
/* redirect from/to same file descriptor? */
if (right_fd == fd)
continue;
/* echo >&10 and 10 is a fd opened to the sh script? */
if (is_hidden_fd(sv, right_fd)) {
errno = EBADF; /* as if it is closed */
ash_msg_and_raise_error("%d: %m", right_fd);
}
newfd = -1;
} else {
newfd = openredirect(redir); /* always >= 0 */
@ -4988,14 +5017,8 @@ redirect(union node *redir, int flags)
/* "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 (is_hidden_fd(sv, fd))
i |= COPYFD_RESTORE;
}
if (fd == 2)
copied_fd2 = i;
@ -9026,7 +9049,7 @@ static int
preadfd(void)
{
int nr;
char *buf = g_parsefile->buf;
char *buf = g_parsefile->buf;
parsenextc = buf;
#if ENABLE_FEATURE_EDITING