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-all
mailing list