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

Reply via email to