DF-0779 / fix.diff
diff --git a/sys/vfs/tmpfs/tmpfs_vnops.c b/sys/vfs/tmpfs/tmpfs_vnops.c --- a/sys/vfs/tmpfs/tmpfs_vnops.c +++ b/sys/vfs/tmpfs/tmpfs_vnops.c @@ -1661,6 +1661,26 @@ node = VP_TO_TMPFS_DIR(vp); startoff = uio->uio_offset; + /* + * Validate the readdir cookie supplied by the caller. An NFS READDIR + * client can pass an arbitrary 64-bit cookie (see nfsrv_readdir, + * nfs_serv.c). A cookie that is not one of the reserved + * TMPFS_DIRCOOKIE_DOT/_DOTDOT/_EOF markers and does not exactly + * correspond to a live dirent would otherwise desynchronise the NFS + * cookie-generation block below from tmpfs_dir_getdents() and trip a + * KKASSERT (kernel panic). Snap such bogus cookies to EOF, matching + * the EOF semantics tmpfs_dir_getdents() already applies to cookies + * past the end of the directory. + */ + if (startoff != TMPFS_DIRCOOKIE_DOT && + startoff != TMPFS_DIRCOOKIE_DOTDOT && + startoff != TMPFS_DIRCOOKIE_EOF) { + if (tmpfs_dir_lookupbycookie(node, startoff, 1) == NULL) { + startoff = TMPFS_DIRCOOKIE_EOF; + uio->uio_offset = TMPFS_DIRCOOKIE_EOF; + } + } + if (uio->uio_offset == TMPFS_DIRCOOKIE_DOT) { error = tmpfs_dir_getdotdent(node, uio); if (error && error != EINVAL) { |