Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 18 Jul 2017 17:35:29 +0000 (UTC)
From:      Ngie Cooper <ngie@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r321139 - in stable/11/bin/dd: . tests
Message-ID:  <201707181735.v6IHZTTR058103@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: ngie
Date: Tue Jul 18 17:35:29 2017
New Revision: 321139
URL: https://svnweb.freebsd.org/changeset/base/321139

Log:
  MFC r302500,r319339,r319543,r319544,r319551,r321138:
  
  r302500 (by cem):
  
  dd(1): Enable access to SIZE_T_MAX character devices
  
  On machines where SIZE_T_MAX exceeds OFF_MAX (signed 64-bit), permit seeking
  character devices to negative off_t values.  This enables dd(1) to interact
  with kernel KVA in /dev/kmem on amd64, for example.
  
  r319339 (by asomers):
  
  Fix integer overflow detection in dd
  
  dd(1) tried to detect whether the seek offset would overflow, but it failed
  to account for the case where the provided argument was negative and the
  file was a regular file (negative seeks are allowed for character devices).
  I fixed it, and added a regression test.
  
  CID:		1368659
  
  r319543:
  
  Stylistic tweaks
  
  Move opening braces of functions from the last column to column 0.
  
  MFC with:	r319339
  
  r319544:
  
  Mark :seek_overflow as an expected failure
  
  MFC with:	r319339
  PR:		219757
  
  r319551 (by asomers):
  
  Fix bin/dd/dd2_tests:seek_overflow on UFS and TMPFS
  
  Split the postive and negative parts into separate test cases.  The positive
  test case can only run on ZFS, because only ZFS supports files that large.
  
  PR:		219757
  
  r321138:
  
  Remove unnecessary make logic added in r319339
  
  This makes the change cleaner and easier to backport to ^/stable/10.

Added:
  stable/11/bin/dd/tests/dd2_test.sh
     - copied, changed from r319339, head/bin/dd/tests/dd2_test.sh
Modified:
  stable/11/bin/dd/args.c
  stable/11/bin/dd/position.c
  stable/11/bin/dd/tests/Makefile
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/bin/dd/args.c
==============================================================================
--- stable/11/bin/dd/args.c	Tue Jul 18 17:29:12 2017	(r321138)
+++ stable/11/bin/dd/args.c	Tue Jul 18 17:35:29 2017	(r321139)
@@ -167,14 +167,6 @@ jcl(char **argv)
 			errx(1, "cbs meaningless if not doing record operations");
 	} else
 		cfunc = def;
-
-	/*
-	 * Bail out if the calculation of a file offset would overflow.
-	 */
-	if (in.offset > OFF_MAX / (ssize_t)in.dbsz ||
-	    out.offset > OFF_MAX / (ssize_t)out.dbsz)
-		errx(1, "seek offsets cannot be larger than %jd",
-		    (intmax_t)OFF_MAX);
 }
 
 static int

Modified: stable/11/bin/dd/position.c
==============================================================================
--- stable/11/bin/dd/position.c	Tue Jul 18 17:29:12 2017	(r321138)
+++ stable/11/bin/dd/position.c	Tue Jul 18 17:35:29 2017	(r321139)
@@ -45,12 +45,41 @@ __FBSDID("$FreeBSD$");
 #include <err.h>
 #include <errno.h>
 #include <inttypes.h>
+#include <limits.h>
 #include <signal.h>
 #include <unistd.h>
 
 #include "dd.h"
 #include "extern.h"
 
+static off_t
+seek_offset(IO *io)
+{
+	off_t n;
+	size_t sz;
+
+	n = io->offset;
+	sz = io->dbsz;
+
+	_Static_assert(sizeof(io->offset) == sizeof(int64_t), "64-bit off_t");
+
+	/*
+	 * If the lseek offset will be negative, verify that this is a special
+	 * device file.  Some such files (e.g. /dev/kmem) permit "negative"
+	 * offsets.
+	 *
+	 * Bail out if the calculation of a file offset would overflow.
+	 */
+	if ((io->flags & ISCHR) == 0 && (n < 0 || n > OFF_MAX / (ssize_t)sz))
+		errx(1, "seek offsets cannot be larger than %jd",
+		    (intmax_t)OFF_MAX);
+	else if ((io->flags & ISCHR) != 0 && (uint64_t)n > UINT64_MAX / sz)
+		errx(1, "seek offsets cannot be larger than %ju",
+		    (uintmax_t)UINT64_MAX);
+
+	return ((off_t)( (uint64_t)n * sz ));
+}
+
 /*
  * Position input/output data streams before starting the copy.  Device type
  * dependent.  Seekable devices use lseek, and the rest position by reading.
@@ -68,7 +97,7 @@ pos_in(void)
 	/* If known to be seekable, try to seek on it. */
 	if (in.flags & ISSEEK) {
 		errno = 0;
-		if (lseek(in.fd, in.offset * in.dbsz, SEEK_CUR) == -1 &&
+		if (lseek(in.fd, seek_offset(&in), SEEK_CUR) == -1 &&
 		    errno != 0)
 			err(1, "%s", in.name);
 		return;
@@ -136,7 +165,7 @@ pos_out(void)
 	 */
 	if (out.flags & (ISSEEK | ISPIPE)) {
 		errno = 0;
-		if (lseek(out.fd, out.offset * out.dbsz, SEEK_CUR) == -1 &&
+		if (lseek(out.fd, seek_offset(&out), SEEK_CUR) == -1 &&
 		    errno != 0)
 			err(1, "%s", out.name);
 		return;

Modified: stable/11/bin/dd/tests/Makefile
==============================================================================
--- stable/11/bin/dd/tests/Makefile	Tue Jul 18 17:29:12 2017	(r321138)
+++ stable/11/bin/dd/tests/Makefile	Tue Jul 18 17:35:29 2017	(r321139)
@@ -1,5 +1,6 @@
 # $FreeBSD$
 
+ATF_TESTS_SH=	dd2_test
 NETBSD_ATF_TESTS_SH=	dd_test
 
 .include <netbsd-tests.test.mk>

Copied and modified: stable/11/bin/dd/tests/dd2_test.sh (from r319339, head/bin/dd/tests/dd2_test.sh)
==============================================================================
--- head/bin/dd/tests/dd2_test.sh	Wed May 31 16:07:32 2017	(r319339, copy source)
+++ stable/11/bin/dd/tests/dd2_test.sh	Tue Jul 18 17:35:29 2017	(r321139)
@@ -26,17 +26,35 @@
 # $FreeBSD$
 
 
-atf_test_case seek_overflow
-seek_overflow_head() {
-	atf_set "descr" "dd(1) should reject too-large seek values"
+atf_test_case max_seek
+max_seek_head()
+{
+	atf_set "descr" "dd(1) can seek by the maximum amount"
 }
-seek_overflow_body() {
+max_seek_body()
+{
+	case `df -T . | tail -n 1 | cut -wf 2` in
+		"ufs")
+			atf_skip "UFS's maximum file size is too small";;
+		"zfs") ;; # ZFS is fine
+		"tmpfs")
+			atf_skip "tmpfs can't create arbitrarily large spare files";;
+		*) atf_skip "Unknown file system";;
+	esac
+
 	touch f.in
-	# Positive tests
 	seek=`echo "2^63 / 4096 - 1" | bc`
 	atf_check -s exit:0 -e ignore dd if=f.in of=f.out bs=4096 seek=$seek
+}
 
-	# Negative tests
+atf_test_case seek_overflow
+seek_overflow_head()
+{
+	atf_set "descr" "dd(1) should reject too-large seek values"
+}
+seek_overflow_body()
+{
+	touch f.in
 	seek=`echo "2^63 / 4096" | bc`
 	atf_check -s not-exit:0 -e match:"seek offsets cannot be larger than" \
 		dd if=f.in of=f.out bs=4096 seek=$seek
@@ -46,5 +64,6 @@ seek_overflow_body() {
 
 atf_init_test_cases()
 {
-        atf_add_test_case seek_overflow
+	atf_add_test_case max_seek
+	atf_add_test_case seek_overflow
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201707181735.v6IHZTTR058103>