-/* $OpenBSD: fuse_vnops.c,v 1.69 2024/05/13 11:17:40 semarie Exp $ */
+/* $OpenBSD: fuse_vnops.c,v 1.70 2024/09/12 09:10:46 claudio Exp $ */
/*
* Copyright (c) 2012-2013 Sylvestre Gallon <ccna.syl@gmail.com>
*
struct fusefs_node *ip;
struct fusefs_mnt *fmp;
struct fusebuf *fbuf;
+ struct dirent *dp;
+ char *edp;
struct vnode *vp;
struct proc *p;
struct uio *uio;
break;
}
+ /* validate the returned dirents */
+ dp = (struct dirent *)fbuf->fb_dat;
+ edp = fbuf->fb_dat + fbuf->fb_len;
+ while ((char *)dp < edp) {
+ if ((char *)dp + offsetof(struct dirent, d_name) >= edp
+ || dp->d_reclen <= offsetof(struct dirent, d_name)
+ || (char *)dp + dp->d_reclen > edp) {
+ error = EINVAL;
+ break;
+ }
+ if (dp->d_namlen + offsetof(struct dirent, d_name) >=
+ dp->d_reclen) {
+ error = EINVAL;
+ break;
+ }
+ memset(dp->d_name + dp->d_namlen, 0, dp->d_reclen -
+ dp->d_namlen - offsetof(struct dirent, d_name));
+
+ if (memchr(dp->d_name, '/', dp->d_namlen) != NULL) {
+ error = EINVAL;
+ break;
+ }
+ dp = (struct dirent *)((char *)dp + dp->d_reclen);
+ }
+ if (error) {
+ fb_delete(fbuf);
+ break;
+ }
+
if ((error = uiomove(fbuf->fb_dat, fbuf->fb_len, uio))) {
fb_delete(fbuf);
break;