COMMAND

    vfs

SYSTEMS AFFECTED

    FreeBSD  2.2.*   and  FreeBSD-stable   before  1998/05/31,   BSDI,
    NetBSD 1.1 and prior

PROBLEM

    NFS can  be used  to mount  remote file  systems. Apart from being
    remote,  it  acts  like  a  normal  UFS file system. Among others,
    this  means  that  creating  hard  links  can  be done in NFS file
    systems.   Arend-Jan  Wijtzes  found  following.   When  linking a
    device like /dev/null to  a file on a  NFS mounted fs the  machine
    freeses.

    When creating hard links on  file systems, the kernel checks  that
    both the original file and the link to it are located on the  same
    file system. Unfortunately,  there is an  error in the  NFS kernel
    code in FreeBSD  2.2.* systems that  performs this check  so it is
    possible to crash a FreeBSD 2.2.* system by hard linking a  device
    special files to a file on an NFS mounted file system.

SOLUTION

    This problem was fixed in NetBSD before 1.2.

    This was corrected on FreeBSD-current as of 1998/05/31.  Patches
    can be found on:

        ftp://ftp.freebsd.org/pub/FreeBSD/CERT/patches/SA-98:05/

    Patch for 2.2.5 and 2.2.6 systems:

    Index: nfs_vnops.c
    ===================================================================
    RCS file: /home/cvsup/freebsd/CVS/src/sys/nfs/nfs_vnops.c,v
    retrieving revision 1.36.2.6
    retrieving revision 1.36.2.7
    diff -u -r1.36.2.6 -r1.36.2.7
    --- nfs_vnops.c       1998/05/13 05:48:45     1.36.2.6
    +++ nfs_vnops.c       1998/05/31 00:07:29     1.36.2.7
    @@ -1755,17 +1755,8 @@
                  struct componentname *a_cnp;
          } */ *ap;
     {
    -#if defined(__NetBSD__)
    -     /*
    -      * Since the args are reversed in the VOP_LINK() calls,
    -      * switch them back. Argh!
    -      */
    -     register struct vnode *vp = ap->a_tdvp;
    -     register struct vnode *tdvp = ap->a_vp;
    -#else
          register struct vnode *vp = ap->a_vp;
          register struct vnode *tdvp = ap->a_tdvp;
    -#endif
          register struct componentname *cnp = ap->a_cnp;
          register u_long *tl;
          register caddr_t cp;
    @@ -1776,11 +1767,8 @@
          int v3 = NFS_ISV3(vp);

          if (vp->v_mount != tdvp->v_mount) {
    -             VOP_ABORTOP(vp, cnp);
    -             if (tdvp == vp)
    -                     vrele(tdvp);
    -             else
    -                     vput(tdvp);
    +             VOP_ABORTOP(tdvp, cnp);
    +             vput(tdvp);
                  return (EXDEV);
          }