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 [EMAIL PROTECTED]
with "unsubscribe freebsd-hackers" in the body of the message