Avoid corrupting the dd(1) IO streams. This would happen by accidentally

outputting to the files being manipulated by opening a file in the standard IO
descriptor space.  In particular, an output file unlucky enough to be sitting
on descriptor 2 (stderr) is certain to be corrupted.

Addresses PR bin/8521, and passes the recently committed regression test
"bin/dd".
This commit is contained in:
dsainty 2003-11-15 12:44:54 +00:00
parent ab6a210f76
commit 0b16f71074

View File

@ -1,4 +1,4 @@
/* $NetBSD: dd.c,v 1.33 2003/09/14 19:20:19 jschauma Exp $ */
/* $NetBSD: dd.c,v 1.34 2003/11/15 12:44:54 dsainty Exp $ */
/*-
* Copyright (c) 1991, 1993, 1994
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1991, 1993, 1994\n\
#if 0
static char sccsid[] = "@(#)dd.c 8.5 (Berkeley) 4/2/94";
#else
__RCSID("$NetBSD: dd.c,v 1.33 2003/09/14 19:20:19 jschauma Exp $");
__RCSID("$NetBSD: dd.c,v 1.34 2003/11/15 12:44:54 dsainty Exp $");
#endif
#endif /* not lint */
@ -69,6 +69,7 @@ __RCSID("$NetBSD: dd.c,v 1.33 2003/09/14 19:20:19 jschauma Exp $");
static void dd_close(void);
static void dd_in(void);
static void getfdtype(IO *);
static int redup_clean_fd(int);
static void setup(void);
int main(int, char *[]);
@ -129,6 +130,9 @@ setup(void)
if (in.fd < 0)
err(EXIT_FAILURE, "%s", in.name);
/* NOTREACHED */
/* Ensure in.fd is outside the stdio descriptor range */
in.fd = redup_clean_fd(in.fd);
}
getfdtype(&in);
@ -159,6 +163,9 @@ setup(void)
err(EXIT_FAILURE, "%s", out.name);
/* NOTREACHED */
}
/* Ensure out.fd is outside the stdio descriptor range */
out.fd = redup_clean_fd(out.fd);
}
getfdtype(&out);
@ -249,6 +256,39 @@ getfdtype(IO *io)
io->flags |= ISPIPE; /* XXX fixed in 4.4BSD */
}
/*
* Move the parameter file descriptor to a descriptor that is outside the
* stdio descriptor range, if necessary. This is required to avoid
* accidentally outputting completion or error messages into the
* output file that were intended for the tty.
*/
static int
redup_clean_fd(int fd)
{
int newfd;
if (fd != STDIN_FILENO && fd != STDOUT_FILENO &&
fd != STDERR_FILENO)
/* File descriptor is ok, return immediately. */
return fd;
newfd = dup(fd);
if (newfd < 0) {
err(EXIT_FAILURE, "dup IO");
/* NOTREACHED */
}
/*
* Recurse, to ensure that the new descriptor is clean. Don't
* free the old descriptor(s) until we've allocated a clean
* one.
*/
newfd = redup_clean_fd(newfd);
close(fd);
return newfd;
}
static void
dd_in(void)
{