git: 51b8ffb95c4f - main - fdesc_allocvp(): fix potential use after free
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 24 Mar 2023 17:47:41 UTC
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=51b8ffb95c4fe45f6825d551bd093889820a8115 commit 51b8ffb95c4fe45f6825d551bd093889820a8115 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2023-03-21 21:24:06 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2023-03-24 17:46:53 +0000 fdesc_allocvp(): fix potential use after free Just owning the interlock is not enough for vget() to operate on the vnode race-free with vgone(), the vnode should be held. Use vget_prep()/vget_finish() to avoid vholding the vnode explicitly, and drop LK_INTERLOCK. Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D39207 --- sys/fs/fdescfs/fdesc_vnops.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c index d3c7951672cf..afefaff8acf4 100644 --- a/sys/fs/fdescfs/fdesc_vnops.c +++ b/sys/fs/fdescfs/fdesc_vnops.c @@ -147,6 +147,7 @@ fdesc_allocvp(fdntype ftype, unsigned fd_fd, int ix, struct mount *mp, struct fdhashhead *fc; struct fdescnode *fd, *fd2; struct vnode *vp, *vp2; + enum vgetstate vgs; int error; fc = FD_NHASH(ix); @@ -166,9 +167,9 @@ loop: if (fd->fd_ix == ix && fd->fd_vnode->v_mount == mp) { /* Get reference to vnode in case it's being free'd */ vp = fd->fd_vnode; - VI_LOCK(vp); + vgs = vget_prep(vp); mtx_unlock(&fdesc_hashmtx); - if (vget(vp, LK_EXCLUSIVE | LK_INTERLOCK)) + if (vget_finish(vp, LK_EXCLUSIVE, vgs) != 0) goto loop; *vpp = vp; return (0); @@ -218,9 +219,9 @@ loop: if (fd2->fd_ix == ix && fd2->fd_vnode->v_mount == mp) { /* Get reference to vnode in case it's being free'd */ vp2 = fd2->fd_vnode; - VI_LOCK(vp2); + vgs = vget_prep(vp2); mtx_unlock(&fdesc_hashmtx); - error = vget(vp2, LK_EXCLUSIVE | LK_INTERLOCK); + error = vget_finish(vp2, LK_EXCLUSIVE, vgs); /* Someone beat us, dec use count and wait for reclaim */ vgone(vp); vput(vp);