Fri Apr 19 00:45:41 2024 UTC (20d)
dounmount: Avoid &((struct vnode_impl *)NULL)->vi_vnode.

Member access of a null pointer is undefined, even if the result
should also be null because vi_vnode is at the start of vnode_impl.

Reported-by: syzbot+a4b2d13c0d6d4dac2d07@syzkaller.appspotmail.com
https://syzkaller.appspot.com/bug?extid=a4b2d13c0d6d4dac2d07


(riastradh)
diff -r1.104 -r1.105 src/sys/kern/vfs_mount.c

cvs diff -r1.104 -r1.105 src/sys/kern/vfs_mount.c (expand / switch to unified diff)

--- src/sys/kern/vfs_mount.c 2024/01/17 10:17:29 1.104
+++ src/sys/kern/vfs_mount.c 2024/04/19 00:45:41 1.105
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: vfs_mount.c,v 1.104 2024/01/17 10:17:29 hannken Exp $ */ 1/* $NetBSD: vfs_mount.c,v 1.105 2024/04/19 00:45:41 riastradh Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1997-2020 The NetBSD Foundation, Inc. 4 * Copyright (c) 1997-2020 The NetBSD Foundation, Inc.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to The NetBSD Foundation 7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9 * NASA Ames Research Center, by Charles M. Hannum, and by Andrew Doran. 9 * NASA Ames Research Center, by Charles M. Hannum, and by Andrew Doran.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
@@ -57,27 +57,27 @@ @@ -57,27 +57,27 @@
57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 57 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 58 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 59 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 60 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 61 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 62 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 63 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
64 * SUCH DAMAGE. 64 * SUCH DAMAGE.
65 * 65 *
66 * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94 66 * @(#)vfs_subr.c 8.13 (Berkeley) 4/18/94
67 */ 67 */
68 68
69#include <sys/cdefs.h> 69#include <sys/cdefs.h>
70__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.104 2024/01/17 10:17:29 hannken Exp $"); 70__KERNEL_RCSID(0, "$NetBSD: vfs_mount.c,v 1.105 2024/04/19 00:45:41 riastradh Exp $");
71 71
72#include "veriexec.h" 72#include "veriexec.h"
73 73
74#include <sys/param.h> 74#include <sys/param.h>
75#include <sys/kernel.h> 75#include <sys/kernel.h>
76 76
77#include <sys/atomic.h> 77#include <sys/atomic.h>
78#include <sys/buf.h> 78#include <sys/buf.h>
79#include <sys/conf.h> 79#include <sys/conf.h>
80#include <sys/fcntl.h> 80#include <sys/fcntl.h>
81#include <sys/filedesc.h> 81#include <sys/filedesc.h>
82#include <sys/device.h> 82#include <sys/device.h>
83#include <sys/kauth.h> 83#include <sys/kauth.h>
@@ -926,27 +926,28 @@ err_mounted: @@ -926,27 +926,28 @@ err_mounted:
926 926
927 return error; 927 return error;
928} 928}
929 929
930/* 930/*
931 * Do the actual file system unmount. File system is assumed to have 931 * Do the actual file system unmount. File system is assumed to have
932 * been locked by the caller. 932 * been locked by the caller.
933 * 933 *
934 * => Caller hold reference to the mount, explicitly for dounmount(). 934 * => Caller hold reference to the mount, explicitly for dounmount().
935 */ 935 */
936int 936int
937dounmount(struct mount *mp, int flags, struct lwp *l) 937dounmount(struct mount *mp, int flags, struct lwp *l)
938{ 938{
939 vnode_t *coveredvp, *vp; 939 struct vnode *coveredvp, *vp;
 940 struct vnode_impl *vip;
940 int error, async, used_syncer, used_extattr; 941 int error, async, used_syncer, used_extattr;
941 const bool was_suspended = fstrans_is_owner(mp); 942 const bool was_suspended = fstrans_is_owner(mp);
942 943
943#if NVERIEXEC > 0 944#if NVERIEXEC > 0
944 error = veriexec_unmountchk(mp); 945 error = veriexec_unmountchk(mp);
945 if (error) 946 if (error)
946 return (error); 947 return (error);
947#endif /* NVERIEXEC > 0 */ 948#endif /* NVERIEXEC > 0 */
948 949
949 if (!was_suspended) { 950 if (!was_suspended) {
950 error = vfs_suspend(mp, 0); 951 error = vfs_suspend(mp, 0);
951 if (error) { 952 if (error) {
952 return error; 953 return error;
@@ -993,27 +994,29 @@ dounmount(struct mount *mp, int flags, s @@ -993,27 +994,29 @@ dounmount(struct mount *mp, int flags, s
993 /* 994 /*
994 * mark filesystem as gone to prevent further umounts 995 * mark filesystem as gone to prevent further umounts
995 * after mnt_umounting lock is gone, this also prevents 996 * after mnt_umounting lock is gone, this also prevents
996 * vfs_busy() from succeeding. 997 * vfs_busy() from succeeding.
997 */ 998 */
998 mp->mnt_iflag |= IMNT_GONE; 999 mp->mnt_iflag |= IMNT_GONE;
999 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) { 1000 if ((coveredvp = mp->mnt_vnodecovered) != NULLVP) {
1000 coveredvp->v_mountedhere = NULL; 1001 coveredvp->v_mountedhere = NULL;
1001 } 1002 }
1002 if (!was_suspended) 1003 if (!was_suspended)
1003 vfs_resume(mp); 1004 vfs_resume(mp);
1004 1005
1005 mountlist_remove(mp); 1006 mountlist_remove(mp);
1006 if ((vp = VIMPL_TO_VNODE(TAILQ_FIRST(&mp->mnt_vnodelist))) != NULL) { 1007
 1008 if ((vip = TAILQ_FIRST(&mp->mnt_vnodelist)) != NULL) {
 1009 vp = VIMPL_TO_VNODE(vip);
1007 vprint("dangling", vp); 1010 vprint("dangling", vp);
1008 panic("unmount: dangling vnode"); 1011 panic("unmount: dangling vnode");
1009 } 1012 }
1010 vfs_hooks_unmount(mp); 1013 vfs_hooks_unmount(mp);
1011 1014
1012 vfs_set_lowermount(mp, NULL); 1015 vfs_set_lowermount(mp, NULL);
1013 vfs_rele(mp); /* reference from mount() */ 1016 vfs_rele(mp); /* reference from mount() */
1014 if (coveredvp != NULLVP) { 1017 if (coveredvp != NULLVP) {
1015 vrele(coveredvp); 1018 vrele(coveredvp);
1016 } 1019 }
1017 return (0); 1020 return (0);
1018} 1021}
1019 1022