Hi,
If an unlink fails due to unveil, the reference count of the inode
is not decremented. You cannot unmount the file system anymore.
I have added unveilleak.c that triggers the breakage.
dd if=/dev/zero of=diskimage bs=512 count=4k
vnconfig vnd0 diskimage
newfs vnd0c
mount /dev/vnd0c /mnt
unveilleak /mnt foo
umount /mnt
umount: /mnt: Device busy
Kenrel debug print shows that use count is not 0.
vflush: busy vnode: 0xd50bf2e8, type VDIR, use 1, write 0, hold 1, flags (VROOT)
tag VT_UFS, ino 2, on dev 14, 2 flags 0x100, effnlink 2, nlink 2
mode 040755, owner 0, group 0, size 512
This unveilleak.c program increases use by 1.
#include <sys/stat.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
int
main(int argc, char *argv[])
{
char *dir, *file, *path;
int fd;
if (argc != 3)
errx(2, "missing dir file");
dir = argv[1];
file = argv[2];
if (asprintf(&path, "%s/%s", dir, file) == -1)
err(1, "asprintf");
fd = open(path, O_WRONLY|O_CREAT, 0755);
if (fd == -1)
err(1, "open %s", dir);
close(fd);
if (unveil(dir, "r") == -1)
err(1, "unveil %s", dir);
if (unveil(NULL, NULL) == -1)
err(1, "unveil NULL");
if (unlink(path) == 0)
errx(1, "unlink %s succeeded", path);
return 0;
}
And this vput(9) in namei(9) fixes the bug.
ok?
bluhm
Index: kern/vfs_lookup.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/vfs_lookup.c,v
retrieving revision 1.77
diff -u -p -r1.77 vfs_lookup.c
--- kern/vfs_lookup.c 13 May 2019 22:55:27 -0000 1.77
+++ kern/vfs_lookup.c 4 Jul 2019 20:16:24 -0000
@@ -262,7 +262,7 @@ fail:
if ((cnp->cn_flags & LOCKPARENT) &&
(cnp->cn_flags & ISLASTCN) &&
(ndp->ni_vp != ndp->ni_dvp))
- VOP_UNLOCK(ndp->ni_dvp);
+ vput(ndp->ni_dvp);
if (ndp->ni_vp) {
if ((cnp->cn_flags & LOCKLEAF))
vput(ndp->ni_vp);