ash,hush: ">&10" redirects to script/tty fds should not work
The fact that shell has open fds to tty and/or scripts should be unobservable, if possible. In particular, if redirect tries to dup one of them via ">&script_fd", it's better to pretend that script_fd is closed, and thus redirect fails with EBADF. Fixes these two testcase failures: ash-redir/redir_to_bad_fd.tests hush-redir/redir_to_bad_fd3.tests function old new delta redirect 1018 1129 +111 setup_redirects 250 359 +109 readtoken1 2651 2655 +4 cmdloop 185 187 +2 changepath 194 195 +1 save_fd_on_redirect 203 194 -9 evaltree 501 484 -17 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 5/2 up/down: 227/-26) Total: 201 bytes text data bss dec hex filename 914553 485 6848 921886 e111e busybox_old 914754 485 6848 922087 e11e7 busybox_unstripped Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
39
shell/ash.c
39
shell/ash.c
@@ -5503,6 +5503,31 @@ save_fd_on_redirect(int fd, int avoid_fd, struct redirtab *sq)
|
||||
return 0; /* "we did not close fd" */
|
||||
}
|
||||
|
||||
static int
|
||||
internally_opened_fd(int fd, struct redirtab *sq)
|
||||
{
|
||||
int i;
|
||||
#if JOBS
|
||||
if (fd == ttyfd)
|
||||
return 1;
|
||||
#endif
|
||||
/* If this one of script's fds? */
|
||||
if (fd != 0) {
|
||||
struct parsefile *pf = g_parsefile;
|
||||
while (pf) {
|
||||
if (fd == pf->pf_fd)
|
||||
return 1;
|
||||
pf = pf->prev;
|
||||
}
|
||||
}
|
||||
|
||||
if (sq) for (i = 0; i < sq->pair_count && sq->two_fd[i].orig_fd != EMPTY; i++) {
|
||||
if (fd == sq->two_fd[i].moved_to)
|
||||
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
|
||||
@@ -5567,15 +5592,11 @@ redirect(union node *redir, int flags)
|
||||
close(fd);
|
||||
}
|
||||
} else {
|
||||
///TODO: if _newfd_ is a script fd or saved fd, then simulate EBADF!
|
||||
//if (newfd == ttyfd) {
|
||||
// errno = EBADF;
|
||||
// ash_msg_and_raise_perror("A %d", newfd);
|
||||
//}
|
||||
//if (newfd == g_parsefile->pf_fd) {
|
||||
// errno = EBADF;
|
||||
// ash_msg_and_raise_perror("B %d", newfd);
|
||||
//}
|
||||
/* if newfd is a script fd or saved fd, simulate EBADF */
|
||||
if (internally_opened_fd(newfd, sv)) {
|
||||
errno = EBADF;
|
||||
ash_msg_and_raise_perror("%d", newfd);
|
||||
}
|
||||
dup2_or_raise(newfd, fd);
|
||||
if (close_fd >= 0) /* "N>FILE" or ">&FILE" or heredoc? */
|
||||
close(close_fd);
|
||||
|
||||
Reference in New Issue
Block a user