Subject: kern/1722: NFS mount on local filesystem may crash
To: None <gnats-bugs@gnats.netbsd.org>
From: None <osymh@gemini.oscs.montana.edu>
List: netbsd-bugs
Date: 11/03/1995 02:34:43
>Number:         1722
>Category:       kern
>Synopsis:       Mounting an NFS filesystem over a local filesystem can crash
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Nov  3 04:50:01 1995
>Last-Modified:
>Originator:     Michael L. Hitch
>Organization:
	Information Technology Center
	Montana State University
>Release:        October 27, 1995
>Environment:
	
System: NetBSD amiga2.oscs.montana.edu 1.1_ALPHA NetBSD 1.1_ALPHA (ZEUS) #951027-0: Fri Oct 27 21:08:32 MDT 1995 root@amiga2.oscs.montana.edu:/opt/tmp/src/sys/arch/amiga/compile/ZEUS amiga


>Description:
	If an NFS filesystem is mounted on the same mount point that a
	local filesystem is mounted on, the system may crash.  What
	appears to be happening is that mountd is doing a "delete export"
	on all currently mounted filesystems prior to processing all
	the exported filesystem entries.  When an NFS filesystem
	is mounted on the same directory as a local filesystem, the
	mount() syscall from mountd uses the filesystem type from the
	getmntinfo() call.  The filesystem type for the local filesystem
	could be ufs, so the mount() arguments are initialized using
	the ufs_args structure.  The kernel determines the *_mount()
	routine to call by looking up the path in the mounted filesystem.
	Because the NFS filesystem was mounted last, the kernel will
	call nfs_mount() with incorrect arguments.  In the specific
	crash I have been seeing, the arguments passed from mountd
	contained garbage that cause nfs_mount() to attempt using some
	uninitialized structures in the mount data (specifically, a timer
	queue which had never been set up) and promptly crashed.
>How-To-Repeat:
	Mount a local filesystem (i.e. /dev/sd1g on /mnt), then mount a
	remove file system on the same directory (i.e. remote:/xyz /mnt).
	If the correct (incorrect?) garbage is present, the system will
	crash.
>Fix:
	I don't know what the proper fix would be.  I was able to work
	around the problem by zeroing out the mount argument list in
	mountd.  That resulted in the nfs_args flags being cleared so
	that nfs_mount() wouldn't execute what it had been doing previously.

*** /usr/src/sbin/mountd/mountd.c	Wed Nov  1 05:26:35 1995
--- mountd.c	Sun Oct 29 11:32:49 1995
***************
*** 649,658 ****
  		} targs;
  
  		if (!strncmp(fsp->f_fstypename, MOUNT_MFS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_FFS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_MSDOS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_ADOSFS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_CD9660, MFSNAMELEN)) {
  			targs.ua.fspec = NULL;
  			targs.ua.export.ex_flags = MNT_DELEXPORT;
  			if (mount(fsp->f_fstypename, fsp->f_mntonname,
--- 649,659 ----
  		} targs;
  
  		if (!strncmp(fsp->f_fstypename, MOUNT_MFS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_FFS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_MSDOS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_ADOSFS, MFSNAMELEN) ||
  		    !strncmp(fsp->f_fstypename, MOUNT_CD9660, MFSNAMELEN)) {
+ 		    	bzero((char *)&targs, sizeof(targs));
  			targs.ua.fspec = NULL;
  			targs.ua.export.ex_flags = MNT_DELEXPORT;
  			if (mount(fsp->f_fstypename, fsp->f_mntonname,


	Part of the problem is the difference in the nfs_args structure
	and the other *_args structure (ufs_args, etc).  Most *_args
	have common arguements (the fspec pointer, and the export_args
	structure which include a flags entry).  Mountd and the kernel
	get confused about the mount() arguements because mountd thinks
	the path is for a local filesystem, but the kernel name lookup
	returns the last mounted filesystem, which would be the NFS
	filesystem.
>Audit-Trail:
>Unformatted: