NetBSD Problem Report #1677

From gnats  Mon Oct 23 19:28:14 1995
Received: from bloom-beacon.MIT.EDU by pain.lcs.mit.edu (8.6.9/8.6.9) with ESMTP id TAA29725 for <gnats-bugs@gnats.netbsd.org>; Mon, 23 Oct 1995 19:27:47 -0400
Message-Id: <199510232310.TAA00701@pattern.arlington.ma.us>
Date: Mon, 23 Oct 1995 19:10:21 -0400
From: John Kohl <jtk@kolvir.arlington.ma.us>
Reply-To: jtk@kolvir.arlington.ma.us
To: gnats-bugs@gnats.netbsd.org
Cc: Trevin Beattie <trevin@xmission.com>, jsp@sequent.com
Subject: union FS can return bogus value for lookup of `.', causing later panic
X-Send-Pr-Version: 3.95

>Number:         1677
>Category:       kern
>Synopsis:       union FS can return bogus value for lookup of `.', causing later panic
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Oct 23 19:35:03 +0000 1995
>Closed-Date:    
>Last-Modified:  Sat May 21 17:25:01 +0000 2022
>Originator:     John Kohl
>Release:        1.1_ALPHA
>Organization:
NetBSD Kernel Hackers `R` Us
>Environment:

System: NetBSD pattern 1.1_ALPHA NetBSD 1.1_ALPHA (PATTERN) #195: Sun Oct 22 13:31:09 EDT 1995 jtk@pattern:/u1/NetBSD-current/src/sys/arch/i386/compile/PATTERN i386


>Description:
If the union FS is looking up `.' in a directory  which is searchable in
the top level but unsearchable in the bottom level, it returns a union vnode
that is not the same as the starting vnode.  This returned vnode is only
half-locked, in that another union vnode points to the same lower layer
vnode.

Because the lower layer could not be looked up, union_lookup() called
union_allocvp() with lowervp == NULLVP.  This resulted in
union_allocvp() failing to find the "real" cached vnode for `.' and it
creates a new one.  The new one has UN_LOCKED set, and the uppervp is
indeed locked, but the lock was taken on behalf of the "real" vnode for `.'

This causes trouble in things like sys_lstat() and it kin which have
code like:
	NDINIT(&nd, LOOKUP, NOFOLLOW | LOCKLEAF | LOCKPARENT, UIO_USERSPACE,
	    SCARG(uap, path), p);
	if (error = namei(&nd))
		return (error);
	vp = nd.ni_vp;
	dvp = nd.ni_dvp;
		if (dvp == vp)
			vrele(dvp);
		else
			vput(dvp);
		error = vn_stat(vp, &sb, p);
		vput(vp);
		if (error)
			return (error);

The second vput() results in a panic from UFS (if DIAGNOSTIC) when it
attempts to unlock an unlocked UFS vnode.

>How-To-Repeat:
1) in the lower layer:
	mkdir Foo
	chmod 700 Foo
	chown otheruser Foo
2) in the upper layer:
	mkdir Foo
3) mount the union FS
4) ls -la /union_mountpoint/Foo
5) watch the machine croak

>Fix:
Not sure what the "right thing" is.  Maybe short-circuit `.'?

What about other cases where some user might not have the appropriate
lookup permissions in the lower layer?  It seems like we must never let
union_allocvp() be called in such a way as to generate two union vnodes
for the same underlying object.
>Release-Note:
>Audit-Trail:
From: coypu@sdf.org
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: kern/1677: union FS can return bogus value for lookup of `.',
 causing later panic
Date: Sun, 26 Mar 2017 19:40:53 +0000

 I believe this bug was fixed, I can't reproduce it.

From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org
Cc: 
Subject: Re: kern/1677: union FS can return bogus value for lookup of `.', causing later panic
Date: Sat, 21 May 2022 17:24:41 +0000

 onionfs is still broken, news at 11!

 Someone^TM should adapt this to an atf test at tests/fs/union/t_pr.c.


 arm64# su -m nobody -c 'ls -la /test/lower/foo'
 [ 266.7691234] Reader / writer lock error: rw_vector_enter,305: locking aga=
 inst myself

 [ 266.7766932] lock address : 0xffff0000772d0a80 type     :     sleep/adapt=
 ive
 [ 266.7766932] initialized  : 0xffffc00000639748
 [ 266.7766932] shared holds :                  0 exclusive:                =
   1
 [ 266.7766932] shares wanted:                  1 exclusive:                =
   0
 [ 266.7766932] relevant cpu :                  1 last held:                =
   1
 [ 266.7766932] relevant lwp : 0xffff00007eb9db00 last held: 0xffff00007eb9d=
 b00
 [ 266.7867213] last locked* : 0xffffc000006543a0 unlocked : 0xffffc00000654=
 3e4
 [ 266.7867213] owner/count  : 0xffff00007eb9db00 flags    : 0x0000000000000=
 004
 [ 266.7867213] Turnstile: no active turnstile for this lock.

 [ 266.7867213] panic: LOCKDEBUG: Reader / writer lock error: rw_vector_ente=
 r,305: locking against myself
 [ 266.7867213] cpu1: Begin traceback...
 [ 266.7967503] trace fp ffffc000903c73b0
 [ 266.7967503] fp ffffc000903c73e0 vpanic() at ffffc000005cdba8 netbsd:vpan=
 ic+0x178
 [ 266.7967503] fp ffffc000903c7440 panic() at ffffc000005cdcb4 netbsd:panic=
 +0x44
 [ 266.8067882] fp ffffc000903c74d0 lockdebug_abort1() at ffffc000005c0af0 n=
 etbsd:lockdebug_abort1+0x100
 [ 266.8067882] fp ffffc000903c7520 rw_enter() at ffffc0000058925c netbsd:rw=
 _enter+0x388
 [ 266.8175394] fp ffffc000903c75e0 genfs_lock() at ffffc0000065439c netbsd:=
 genfs_lock+0x8c
 [ 266.8175394] fp ffffc000903c7600 VOP_LOCK() at ffffc00000648f14 netbsd:VO=
 P_LOCK+0x90
 [ 266.8269275] fp ffffc000903c7670 vn_lock() at ffffc0000063e61c netbsd:vn_=
 lock+0x9c
 [ 266.8269275] fp ffffc000903c76a0 union_loadvnode() at ffffc0000048cb2c ne=
 tbsd:union_loadvnode+0xbc
 [ 266.8377005] fp ffffc000903c77a0 vcache_get() at ffffc0000063c88c netbsd:=
 vcache_get+0x188
 [ 266.8377005] fp ffffc000903c7840 union_allocvp() at ffffc0000048c7f4 netb=
 sd:union_allocvp+0x5a0
 [ 266.8470422] fp ffffc000903c7910 union_lookup() at ffffc0000048e9ac netbs=
 d:union_lookup+0x238
 [ 266.8470422] fp ffffc000903c7a40 VOP_LOOKUP() at ffffc0000064759c netbsd:=
 VOP_LOOKUP+0x3c
 [ 266.8572209] fp ffffc000903c7a80 lookup_once() at ffffc00000626e38 netbsd=
 :lookup_once+0x1b8
 [ 266.8572209] fp ffffc000903c7b00 namei_tryemulroot() at ffffc0000062799c =
 netbsd:namei_tryemulroot+0x4bc
 [ 266.8671509] fp ffffc000903c7c70 namei() at ffffc0000062936c netbsd:namei=
 +0x2c
 [ 266.8671509] fp ffffc000903c7cb0 do_sys_statat() at ffffc00000634fcc netb=
 sd:do_sys_statat+0xec
 [ 266.8772127] fp ffffc000903c7d60 sys___lstat50() at ffffc000006350c4 netb=
 sd:sys___lstat50+0x20
 [ 266.8772127] fp ffffc000903c7e20 syscall() at ffffc000000b255c netbsd:sys=
 call+0x19c
 [ 266.8872275] tf ffffc000903c7ed0 el0_trap() at ffffc000000b57f0 netbsd:el=
 1_trap_exit+0x68
 [ 266.8872275] ---- trapframe 0xffffc000903c7ed0 (304 bytes) ----
 [ 266.8973727]     pc=3D0000f5fbdc0a03fc,   spsr=3D0000000040000000
 [ 266.8973727]    esr=3D00000000560001b9,    far=3D0000f5fbdbf14010
 [ 266.8973727]     x0=3D0000f5fbdc3342f0,     x1=3D0000f5fbdc334300
 [ 266.8973727]     x2=3D0000000000000000,     x3=3D0000f5fbdc334280
 [ 266.8973727]     x4=3D0000000000000027,     x5=3D0000000000000011
 [ 266.8973727]     x6=3D0000f5fbdc3342f2,     x7=3D00000000000000d4
 [ 266.9073198]     x8=3D0000000000000003,     x9=3D0000f5fbdc37c308
 [ 266.9073198]    x10=3D000000000000003d,    x11=3D00000000ffffffff
 [ 266.9073198]    x12=3D0000f5fbdc374100,    x13=3D0000f5fbdba00b90
 [ 266.9073198]    x14=3D0000000000000000,    x15=3D0000000000000000
 [ 266.9073198]    x16=3D0000f5fbdc10cbe8,    x17=3D0000f5fbdc0a03f8
 [ 266.9073198]    x18=3D0000000000000064,    x19=3D0000f5fbdc334280
 [ 266.9174361]    x20=3D0000f5fbdc334300,    x21=3D0000000000000000
 [ 266.9174361]    x22=3D0000000000000000,    x23=3D0000000000000001
 [ 266.9174361]    x24=3D0000f5fbdc33b050,    x25=3D0000000000000001
 [ 266.9174361]    x26=3D0000f5fbdc333000,    x27=3D0000f5fbdc33b000
 [ 266.9174361]    x28=3D0000f5fbdc334140, fp=3Dx29=3D0000fffffffb2a20
 [ 266.9174361] lr=3Dx30=3D0000f5fbdbfdab14,     sp=3D0000fffffffb2a20
 [ 266.9273784] ------------------------------------------------
 [ 266.9273784] cpu1: End traceback...

>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.46 2020/01/03 16:35:01 leot Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2020 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.