Leaking vnode with chroot to mounted file system due to unveil()

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Leaking vnode with chroot to mounted file system due to unveil()

Silamael
Hi,

We found a problem with programs using unveil() executed by chroot in a
mounted file system.
After the program run, umount of the file system will return with EBUSY.

Simple test program to reproduce the problem:

---------------------------------------------
#include <unistd.h>
#include <err.h>

int main() {
        if (unveil("/", "") == -1)
                err(1, "Error calling unveil()");

        return 0
}
----------------------------------------------

Steps to reproduce:
1. Mount a MFS to /mnt
2. Compile the example program with -static and copy to /mnt
3. Do a chroot /mnt unveil
4. Try to unmount: umount /mnt

The umount command will fail at least with OpenBSD 6.5 and -current with
EBUSY. I haven't tested if the error also exists in 6.4.
As far as we found out, the use counter of the vnode for the directory
seems leaking.

-- Matthias

Reply | Threaded
Open this post in threaded view
|

Re: Leaking vnode with chroot to mounted file system due to unveil()

Alexander Bluhm
On Tue, Jul 16, 2019 at 02:04:12PM +0200, Silamael wrote:
> We found a problem with programs using unveil() executed by chroot in a
> mounted file system.
> After the program run, umount of the file system will return with EBUSY.

If I understand the code in ufs_lookup() correctly, *vpp = tdp is
refcounted in the ISDOTDOT case.  This happens also if *vpp == vdp.

So it is wrong to skip dereferencing if parent != vp.  I have written
a test and this diff survived a full make regress run.

ok?

bluhm

Index: kern/kern_unveil.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/kern_unveil.c,v
retrieving revision 1.29
diff -u -p -r1.29 kern_unveil.c
--- kern/kern_unveil.c 29 Jul 2019 23:14:06 -0000 1.29
+++ kern/kern_unveil.c 30 Jul 2019 12:18:52 -0000
@@ -309,8 +309,7 @@ unveil_find_cover(struct vnode *dp, stru
  break;
  }

- if (parent != vp)
- vrele(vp);
+ vrele(vp);
  (void) unveil_lookup(parent, p, &ret);
  vput(parent);