Date: Sun, 26 Nov 2000 19:04:53 +0100 From: Thomas Moestl <tmoestl@gmx.net> To: freebsd-hackers@freebsd.org Subject: [PATCH] Fix for panics in lookup() after forced unmount Message-ID: <20001126190453.A1157@crow.dom2ip.de>
next in thread | raw e-mail | index | archive | help
Hi, I think I have a sufficient fix for PR kern/19572. Could somebody please Review/Comment this? To quote: > Description > Executing cd ../cdrom from /cdrom directory after cycle of mount-umount- > mount cycle causes trap 12 (page fault while in kernel mode) and hence > causes kernel panic. > How-To-Repeat > chdir to /cdrom (which) is default mount point for cdrom as per fstab. > mount /cdrom and do ls > now umount -f /cdrom (force as we will be /cdrom) > doing ls will give error( . not a directory) > do mount /cdrom to mount the cdrom once again (we are still in /cdrom dir) > now do ls will give error once again > now do cd ../ (tab in case of bash or esc in case of csh) to do file > completion. > This will result in trap 12 (page fault in kernel mode) and thus > results in kernel panic. Actually, the panic will occur after a simple forced unmount of the current working directory and subsequent try to access "..". This is because the vnode of the cwd was cleared and it's v_mount member was set to NULL. This member is however dereferenced in the handling for the ".." special case in lookup(), causing a panic. The fix is rather trivial, just check the member before using it and return an appropriate error. In the following patch, I use EBADF. Btw, after taking a look into the OpenBSD and NetBSD repos, I think they might have the same problem. Is there any standard channel to pass bug reports to them from FreeBSD, or should I just use the normal submit procedure? - Thomas The patch: ------------------------------------------------------------------------ *** old/kern/vfs_lookup.c Sat Nov 25 23:55:39 2000 --- new/kern/vfs_lookup.c Sun Nov 26 00:58:15 2000 *************** *** 403,408 **** --- 403,412 ---- if ((dp->v_flag & VROOT) == 0 || (cnp->cn_flags & NOCROSSMOUNT)) break; + if (dp->v_mount == NULL) { /* forced unmount */ + error = EBADF; + goto bad; + } tdp = dp; dp = dp->v_mount->mnt_vnodecovered; vput(tdp); *************** *** 424,430 **** printf("not found\n"); #endif if ((error == ENOENT) && ! (dp->v_flag & VROOT) && (dp->v_mount->mnt_flag & MNT_UNION)) { tdp = dp; dp = dp->v_mount->mnt_vnodecovered; --- 428,434 ---- printf("not found\n"); #endif if ((error == ENOENT) && ! (dp->v_flag & VROOT) && (dp->v_mount != NULL) && (dp->v_mount->mnt_flag & MNT_UNION)) { tdp = dp; dp = dp->v_mount->mnt_vnodecovered; *************** *** 502,507 **** --- 506,517 ---- ((cnp->cn_flags & FOLLOW) || trailing_slash || *ndp->ni_next == '/')) { cnp->cn_flags |= ISSYMLINK; + if (dp->v_mount == NULL) { + /* We can't know whether the directory was mounted with + * NOSYMFOLLOW, so we can't follow safely. */ + error = EBADF; + goto bad2; + } if (dp->v_mount->mnt_flag & MNT_NOSYMFOLLOW) { error = EACCES; goto bad2; To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001126190453.A1157>