svn commit: r366278 - head/sys/kern

Rick Macklem rmacklem at FreeBSD.org
Wed Sep 30 02:18:09 UTC 2020


Author: rmacklem
Date: Wed Sep 30 02:18:09 2020
New Revision: 366278
URL: https://svnweb.freebsd.org/changeset/base/366278

Log:
  Make copy_file_range(2) Linux compatible for overflow of offset + len.
  
  Without this patch, if a call to copy_file_range(2) specifies an input file
  offset + len that would wrap around, EINVAL is returned.
  I thought that was the Linux behaviour, but recent testing showed that
  Linux accepts this case and does the copy_file_range() to EOF.
  
  This patch changes the FreeBSD code to exhibit the same behaviour as
  Linux for this case.
  
  Reviewed by:	asomers, kib
  Differential Revision:	https://reviews.freebsd.org/D26569

Modified:
  head/sys/kern/vfs_vnops.c

Modified: head/sys/kern/vfs_vnops.c
==============================================================================
--- head/sys/kern/vfs_vnops.c	Wed Sep 30 00:56:08 2020	(r366277)
+++ head/sys/kern/vfs_vnops.c	Wed Sep 30 02:18:09 2020	(r366278)
@@ -2790,25 +2790,31 @@ vn_copy_file_range(struct vnode *invp, off_t *inoffp, 
 {
 	int error;
 	size_t len;
-	uint64_t uvalin, uvalout;
+	uint64_t uval;
 
 	len = *lenp;
 	*lenp = 0;		/* For error returns. */
 	error = 0;
 
 	/* Do some sanity checks on the arguments. */
-	uvalin = *inoffp;
-	uvalin += len;
-	uvalout = *outoffp;
-	uvalout += len;
 	if (invp->v_type == VDIR || outvp->v_type == VDIR)
 		error = EISDIR;
-	else if (*inoffp < 0 || uvalin > INT64_MAX || uvalin <
-	    (uint64_t)*inoffp || *outoffp < 0 || uvalout > INT64_MAX ||
-	    uvalout < (uint64_t)*outoffp || invp->v_type != VREG ||
-	    outvp->v_type != VREG)
+	else if (*inoffp < 0 || *outoffp < 0 ||
+	    invp->v_type != VREG || outvp->v_type != VREG)
 		error = EINVAL;
 	if (error != 0)
+		goto out;
+
+	/* Ensure offset + len does not wrap around. */
+	uval = *inoffp;
+	uval += len;
+	if (uval > INT64_MAX)
+		len = INT64_MAX - *inoffp;
+	uval = *outoffp;
+	uval += len;
+	if (uval > INT64_MAX)
+		len = INT64_MAX - *outoffp;
+	if (len == 0)
 		goto out;
 
 	/*


More information about the svn-src-head mailing list