Subject: kern/4439: incorrect link count of dirs that only exist in upper layer of unionfs
To: None <gnats-bugs@gnats.netbsd.org>
From: Dave Huang <khym@bga.com>
List: netbsd-bugs
Date: 11/06/1997 06:39:54
>Number:         4439
>Category:       kern
>Synopsis:       incorrect link count of dirs that only exist in upper layer of unionfs
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Thu Nov  6 05:20:04 1997
>Last-Modified:
>Originator:     Dave Huang
>Organization:
Name: Dave Huang     |   Mammal, mammal / their names are called /
INet: khym@bga.com   |   they raise a paw / the bat, the cat /
FurryMUCK: Dahan     |   dolphin and dog / koala bear and hog -- TMBG
Dahan: Hani G Y+C 22 Y++ L+++ W- C++ T++ A+ E+ S++ V++ F- Q+++ P+ B+ PA+ PL++
>Release:        NetBSD-1.3_ALPHA as of November 5, 1997
>Environment:
	
System: NetBSD dahan.metonymy.com 1.3_ALPHA NetBSD 1.3_ALPHA (SPIFF) #156: Thu Nov 6 06:24:34 CST 1997 khym@dahan.metonymy.com:/usr/src.local/sys/arch/i386/compile/SPIFF i386


>Description:
	The link count of directories that only exist in the upper
layer of a union filesystem is garbage.

union_getattr() in union_vnops.c has the following comment:
/*
 * Some programs walk the filesystem hierarchy by counting
 * links to directories to avoid stat'ing all the time.
 * This means the link count on directories needs to be "correct".
 * The only way to do that is to call getattr on both layers
 * and fix up the link count.  The link count will not necessarily
 * be accurate but will be large enough to defeat the tree walkers.
 */

But if the directory doesn't exist in the lower layer, it uses the
contents of an uninitialized structure for the lower layer's link
count.

>How-To-Repeat:
dahan /tmp# pwd
/tmp
dahan /tmp# mkdir top bottom
dahan /tmp# mount -t union /tmp/top /tmp/bottom
dahan /tmp# mkdir bottom/dir
dahan /tmp# ls -l bottom
total 1
drwx------  4028275317 root  wheel  512 Nov  2 04:15 dir/
dahan /tmp# umount /tmp/bottom
dahan /tmp# ls -l top bottom
bottom:

top:
total 1
drwx------  2 root  wheel  512 Nov  2 04:15 dir/

However, Matthias Drochner tried the above and wasn't able to
duplicate the problem on his system... so I dunno what's going on.
I've done a "sup -o", so my sources should be up-to-date.

>Fix:
Make sure va.va_nlink is initialized before trying to use it. Perhaps
something like this:
--- /usr/src/sys/miscfs/union/union_vnops.c	Fri Oct 10 07:26:34 1997
+++ union_vnops.c	Thu Nov  6 06:24:01 1997
@@ -811,6 +811,8 @@
 		vp = NULLVP;
 	}
 
+	va.va_nlink = 0;
+
 	if (vp != NULLVP) {
 		error = VOP_GETATTR(vp, vap, ap->a_cred, ap->a_p);
 		if (error)


Or maybe initialize it inside this block... *shrug*
	} else if (vp->v_type == VDIR) {
		vp = un->un_lowervp;
		vap = &va;
	} else {
>Audit-Trail:
>Unformatted: