In msdosfs_read() and msdosfs_write(), don't check explicitly for

(uio_offset < 0) since this can't happen.  If this happens, then the
general code handles the problem safely (better than before for reading,
returning 0 (EOF) instead of the bogus errno EINVAL, and the same as
before for writing, returning EFBIG).

In msdosfs_read(), don't check for (uio_resid < 0).  msdosfs_write()
already didn't check.

In msdosfs_read(), document in a comment our assumptions that the caller
passed a valid uio_offset and uio_resid.  ffs checks using KASSERT(),
and that is enough sanity checking.  In the same comment, partly document
there is no need to check for the EOVERFLOW case, unlike in ffs where this
case can happen at least in theory.

In msdosfs_write(), add a comment about why the checking of
(uio_resid == 0) is explicit, unlike in ffs.

In msdosfs_write(), check for impossibly large final offsets before
checking if the file size rlimit would be exceeded, so that we don't
have an overflow bug in the rlimit check and are consistent with ffs.
We now return EFBIG instead of EFBIG plus a SIGXFSZ signal if the final
offset would be impossibly large but not so large as to cause overflow.
Overflow normally gave the benign behaviour of no signal.

Approved by:	re (kensmith) (blanket)
This commit is contained in:
bde 2007-08-07 10:35:27 +00:00
parent b236f3d925
commit 7fe18219e6

View File

@ -563,18 +563,21 @@ msdosfs_read(ap)
struct msdosfsmount *pmp = dep->de_pmp;
struct uio *uio = ap->a_uio;
if (uio->uio_offset < 0)
return (EINVAL);
if ((uoff_t)uio->uio_offset > DOS_FILESIZE_MAX)
return (0);
/*
* If they didn't ask for any data, then we are done.
*/
orig_resid = uio->uio_resid;
if (orig_resid <= 0)
if (orig_resid == 0)
return (0);
/*
* The caller is supposed to ensure that
* uio->uio_offset >= 0 and uio->uio_resid >= 0.
* We don't need to check for large offsets as in ffs because
* dep->de_FileSize <= DOS_FILESIZE_MAX < OFF_MAX, so large
* offsets cannot cause overflow even in theory.
*/
seqcount = ap->a_ioflag >> IO_SEQSHIFT;
isadir = dep->de_Attributes & ATTR_DIRECTORY;
@ -681,12 +684,21 @@ msdosfs_write(ap)
panic("msdosfs_write(): bad file type");
}
if (uio->uio_offset < 0)
return (EFBIG);
/*
* This is needed (unlike in ffs_write()) because we extend the
* file outside of the loop but we don't want to extend the file
* for writes of 0 bytes.
*/
if (uio->uio_resid == 0)
return (0);
/*
* The caller is supposed to ensure that
* uio->uio_offset >= 0 and uio->uio_resid >= 0.
*/
if ((uoff_t)uio->uio_offset + uio->uio_resid > DOS_FILESIZE_MAX)
return (EFBIG);
/*
* If they've exceeded their filesize limit, tell them about it.
*/
@ -701,9 +713,6 @@ msdosfs_write(ap)
PROC_UNLOCK(td->td_proc);
}
if ((uoff_t)uio->uio_offset + uio->uio_resid > DOS_FILESIZE_MAX)
return (EFBIG);
/*
* If the offset we are starting the write at is beyond the end of
* the file, then they've done a seek. Unix filesystems allow