Date: Sat, 27 Jan 2018 12:00:44 -0500 From: Pedro Giffuni <pfg@FreeBSD.org> To: Warner Losh <imp@bsdimp.com> Cc: Bruce Evans <brde@optusnet.com.au>, src-committers <src-committers@freebsd.org>, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: Re: svn commit: r328346 - in head/sys: fs/ext2fs ufs/ffs ufs/ufs Message-ID: <f159b531-8df1-c24e-0255-a9c2338b2e03@FreeBSD.org> In-Reply-To: <CANCZdfqq7eS5qMWVrG=U0aJJuNc%2BGmqvxa9=_0BbNr0tAqpx=Q@mail.gmail.com> References: <201801241758.w0OHwm26063524@repo.freebsd.org> <20180126020540.B2181@besplex.bde.org> <8d5ddd06-14b2-e7e1-14dd-5e9d42f9b33c@FreeBSD.org> <20180126053133.R3207@besplex.bde.org> <21b6bdda-65b7-89da-4dd6-bed64978eba8@FreeBSD.org> <20180126214948.C1040@besplex.bde.org> <11937120-bbb4-5da1-f48c-240a6aeafbd9@FreeBSD.org> <CANCZdfqq7eS5qMWVrG=U0aJJuNc%2BGmqvxa9=_0BbNr0tAqpx=Q@mail.gmail.com>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------F212627EF6FB157D50797727 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit On 01/27/18 11:14, Warner Losh wrote: > > > On Jan 27, 2018 8:17 AM, "Pedro Giffuni" <pfg@freebsd.org > <mailto:pfg@freebsd.org>> wrote: > > > > On 01/26/18 06:36, Bruce Evans wrote: > > On Thu, 25 Jan 2018, Pedro Giffuni wrote: > > On 25/01/2018 14:24, Bruce Evans wrote: > > ... > This code only works because (if?) nfs is the only > caller and nfs never > passes insane values. > > > I am starting to think that we should simply match > uio_resid and set it to ssize_t. > Returning the value to int is certainly not the solution. > > > Of course using the correct type (int) is part of the solution. > > uio_must be checked before it is used for cookies, and after > checking it, it > is small so it fits easily in an int. It must also checked to > be nonnegative, > so that it doesn't suffer unsigned poisoning when it is > promoted, so it would > also fit in a u_int, but using u_int to store it is silly as > using 1U instead > of 1 for a count of 1. > > The bounds checking is something like: > > if (ap->uio_resid < 0) > ap->uio_resid = 0; > if (ap->a_ncookies != NULL) { > if (ap->uio_resid >= 64 * 1024) > ap->uio_resid = 64 * 1024; > ncookies = ap->uio_resid; > } > > This checks for negative values for all cases and converts to > 0 (EOF) to > preserve historical behaviour for the syscall case and to > avoid overflow > for the cookies case (in case the caller is buggy). The > correct handling > is to return EINVAL, but EOF is good enough. > > In the syscall case, uio_resid can be up to SSIZE_MAX, so > don't check it > or corrupt it by assigning it to an int or u_int. > > Limit uio_resid from above only in the cookies case. The > final limit should > be about 128K (whatever nfs uses) or maybe 1M. Don't return > EINVAL above > the limit, since nfs probably wouldn't know how to handle that > (by retrying > with a smaller size). Test its handling of short counts > instead. It is > expected than nfs asks for 128K and we supply at most 64K. > The supply is > always reduced at EOF. Hopefully nfs doesn't treat the short > count as EOF. > It should retry until we supply 0. > > Hmm ... > > We have never checked the upper bound there, which doesn't mean it > was right. > I found MAXPHYS, which seems a more reasonable limit used in the > kernel for uio_resid. > > I am checking the patch compiles and doesn't give surprises. > > > MAXPHYS is almost the right thing to check. There's per device limits > for normal I/O, but that doesn't seem to be a strict limit for readdir. > OK... new patch, this time again trying to sanitize only ncookies (which can be int or u_int, doesn't matter to me). Pedro. --------------F212627EF6FB157D50797727 Content-Type: text/x-patch; name="ufs_ncookies.diff" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="ufs_ncookies.diff" Index: sys/fs/ext2fs/ext2_lookup.c =================================================================== --- sys/fs/ext2fs/ext2_lookup.c (revision 328478) +++ sys/fs/ext2fs/ext2_lookup.c (working copy) @@ -145,7 +145,7 @@ off_t offset, startoffset; size_t readcnt, skipcnt; ssize_t startresid; - u_int ncookies; + int ncookies; int DIRBLKSIZ = VTOI(ap->a_vp)->i_e2fs->e2fs_bsize; int error; @@ -152,7 +152,11 @@ if (uio->uio_offset < 0) return (EINVAL); ip = VTOI(vp); + if (uio->uio_resid < 0) + uio->uio_resid = 0; if (ap->a_ncookies != NULL) { + if (uio->uio_resid > MAXPHYS) + uio->uio_resid = MAXPHYS; ncookies = uio->uio_resid; if (uio->uio_offset >= ip->i_size) ncookies = 0; Index: sys/ufs/ufs/ufs_vnops.c =================================================================== --- sys/ufs/ufs/ufs_vnops.c (revision 328478) +++ sys/ufs/ufs/ufs_vnops.c (working copy) @@ -2170,7 +2170,7 @@ off_t offset, startoffset; size_t readcnt, skipcnt; ssize_t startresid; - u_int ncookies; + int ncookies; int error; if (uio->uio_offset < 0) @@ -2178,7 +2178,11 @@ ip = VTOI(vp); if (ip->i_effnlink == 0) return (0); + if (uio->uio_resid < 0) + uio->uio_resid = 0; if (ap->a_ncookies != NULL) { + if (uio->uio_resid > MAXPHYS) + uio->uio_resid = MAXPHYS; ncookies = uio->uio_resid; if (uio->uio_offset >= ip->i_size) ncookies = 0; --------------F212627EF6FB157D50797727--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?f159b531-8df1-c24e-0255-a9c2338b2e03>