If stdin/stdout aren't open on startup, open them to /dev/null
Otherwise, -oLOGFILE may end up using one of them. This conflicts with the previous change, which closes stdin/out in strace. * strace.c (init): If fcntl(F_GETFD) fails on stdin or stdout, sanitize them: open /dev/null and dup it until fds 0,1,2 are all used up. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
This commit is contained in:
33
strace.c
33
strace.c
@ -1184,6 +1184,16 @@ exec_or_die(void)
|
|||||||
perror_msg_and_die("exec");
|
perror_msg_and_die("exec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int open_dev_null(void)
|
||||||
|
{
|
||||||
|
int fd = open("/dev/null", O_RDWR);
|
||||||
|
if (fd < 0) /* /dev not populated? Give me _something_... */
|
||||||
|
fd = open("/", O_RDWR);
|
||||||
|
if (fd < 0) /* shouldn't happen... */
|
||||||
|
perror_msg_and_die("Can't open '/'");
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
startup_child(char **argv)
|
startup_child(char **argv)
|
||||||
{
|
{
|
||||||
@ -1365,9 +1375,7 @@ startup_child(char **argv)
|
|||||||
* will reuse them, unexpectedly making a newly opened object "stdin").
|
* will reuse them, unexpectedly making a newly opened object "stdin").
|
||||||
*/
|
*/
|
||||||
close(0);
|
close(0);
|
||||||
if (open("/dev/null", O_RDWR) != 0) /* /dev not populated? */
|
open_dev_null(); /* opens to fd#0 */
|
||||||
if (open("/", O_RDONLY) != 0) /* shouldn't happen... */
|
|
||||||
perror_msg_and_die("Can't open '/'");
|
|
||||||
dup2(0, 1);
|
dup2(0, 1);
|
||||||
#if 0
|
#if 0
|
||||||
/* A good idea too, but we sometimes need to print error messages */
|
/* A good idea too, but we sometimes need to print error messages */
|
||||||
@ -1715,6 +1723,25 @@ init(int argc, char *argv[])
|
|||||||
error_msg("ptrace_setoptions = %#x", ptrace_setoptions);
|
error_msg("ptrace_setoptions = %#x", ptrace_setoptions);
|
||||||
test_ptrace_seize();
|
test_ptrace_seize();
|
||||||
|
|
||||||
|
if (fcntl(0, F_GETFD) == -1 || fcntl(1, F_GETFD) == -1) {
|
||||||
|
/*
|
||||||
|
* Something weird with our stdin and/or stdout -
|
||||||
|
* for example, may be not open? In this case,
|
||||||
|
* ensure that none of the future opens uses them.
|
||||||
|
*
|
||||||
|
* This was seen in the wild when /proc/sys/kernel/core_pattern
|
||||||
|
* was set to "|/bin/strace -o/tmp/LOG PROG":
|
||||||
|
* kernel runs coredump helper with fd#0 open but fd#1 closed (!),
|
||||||
|
* therefore LOG gets opened to fd#1, and fd#1 is closed by
|
||||||
|
* "don't hold up stdin/out open" code soon after.
|
||||||
|
*/
|
||||||
|
int fd = open_dev_null();
|
||||||
|
while (fd >= 0 && fd < 2)
|
||||||
|
fd = dup(fd);
|
||||||
|
if (fd > 2)
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
/* Check if they want to redirect the output. */
|
/* Check if they want to redirect the output. */
|
||||||
if (outfname) {
|
if (outfname) {
|
||||||
/* See if they want to pipe the output. */
|
/* See if they want to pipe the output. */
|
||||||
|
Reference in New Issue
Block a user