The struct file f_advice member is overlaid with the devfs f_cdevpriv

data.  If vnode bypass for devfs file failed, vn_read/vn_write are
called and might try to dereference f_advice.  Limit the accesses to
f_advice to VREG vnodes only, which is the type ensured by
posix_fadvise().

The f_advice for regular files is protected by mtxpool lock.  Recheck
that f_advice is not NULL after lock is taken.

Reported and tested by:	bde
Sponsored by:	The FreeBSD Foundation
MFC after:	3 weeks
This commit is contained in:
Konstantin Belousov 2016-01-22 20:35:20 +00:00
parent 1a2dd035fb
commit 6adf19481c

View File

@ -743,12 +743,13 @@ get_advice(struct file *fp, struct uio *uio)
int ret;
ret = POSIX_FADV_NORMAL;
if (fp->f_advice == NULL)
if (fp->f_advice == NULL || fp->f_vnode->v_type != VREG)
return (ret);
mtxp = mtx_pool_find(mtxpool_sleep, fp);
mtx_lock(mtxp);
if (uio->uio_offset >= fp->f_advice->fa_start &&
if (fp->f_advice != NULL &&
uio->uio_offset >= fp->f_advice->fa_start &&
uio->uio_offset + uio->uio_resid <= fp->f_advice->fa_end)
ret = fp->f_advice->fa_advice;
mtx_unlock(mtxp);