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:
parent
ab6a210f76
commit
0b16f71074
44
bin/dd/dd.c
44
bin/dd/dd.c
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user