From: claudio Date: Thu, 12 Sep 2024 09:10:46 +0000 (+0000) Subject: Do a basic sanity check that dirents returned via fuse are kind of sane. X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=00475b9b7a5913f394433f708ebd3dff5b5824cf;p=openbsd Do a basic sanity check that dirents returned via fuse are kind of sane. Ensure that file names passed back by readdir do not include a '/' character. The '/' char is the path separator and is not allowed in any filename. On top of this also check that d_reclen and d_namlen are kind of sane and zero out the padding bytes after d_name. OK beck@ --- diff --git a/sys/miscfs/fuse/fuse_vnops.c b/sys/miscfs/fuse/fuse_vnops.c index 8c38ab55c41..c1592e7f5e7 100644 --- a/sys/miscfs/fuse/fuse_vnops.c +++ b/sys/miscfs/fuse/fuse_vnops.c @@ -1,4 +1,4 @@ -/* $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 * @@ -752,6 +752,8 @@ fusefs_readdir(void *v) 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; @@ -806,6 +808,35 @@ fusefs_readdir(void *v) 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;