The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=011efaa5cd246a67bbe6e37364baa18178a9f7bd
commit 011efaa5cd246a67bbe6e37364baa18178a9f7bd Author: Konstantin Belousov <k...@freebsd.org> AuthorDate: 2025-08-01 08:22:14 +0000 Commit: Konstantin Belousov <k...@freebsd.org> CommitDate: 2025-08-01 16:48:53 +0000 devfs readdir: handle short buffer same as UFS Return EINVAL if this is the first dirent encountered with the short buffer, or EJUSTRETURN if something was already copied out. This is needed to pass eof check in vop_readdir_post(): we are not at eof but resid was not advanced. Reported and tested by: pho (previous version) Reviewed by: markj Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D51667 --- sys/fs/devfs/devfs_vnops.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 1d744e6593c0..3a64c205186f 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -1450,6 +1450,7 @@ devfs_readdir(struct vop_readdir_args *ap) struct devfs_mount *dmp; off_t off; int *tmp_ncookies = NULL; + ssize_t startresid; if (ap->a_vp->v_type != VDIR) return (ENOTDIR); @@ -1482,6 +1483,7 @@ devfs_readdir(struct vop_readdir_args *ap) error = 0; de = ap->a_vp->v_data; off = 0; + startresid = uio->uio_resid; TAILQ_FOREACH(dd, &de->de_dlist, de_list) { KASSERT(dd->de_cdp != (void *)0xdeadc0de, ("%s %d\n", __func__, __LINE__)); if (dd->de_flags & (DE_COVERED | DE_WHITEOUT)) @@ -1494,8 +1496,13 @@ devfs_readdir(struct vop_readdir_args *ap) de = dd; dp = dd->de_dirent; MPASS(dp->d_reclen == GENERIC_DIRSIZ(dp)); - if (dp->d_reclen > uio->uio_resid) + if (dp->d_reclen > uio->uio_resid) { + /* Nothing was copied out, return EINVAL. */ + if (uio->uio_resid == startresid) + error = EINVAL; + /* Otherwise stop. */ break; + } dp->d_fileno = de->de_inode; /* NOTE: d_off is the offset for the *next* entry. */ dp->d_off = off + dp->d_reclen;