Fatal trap 12 in fuse_vnop_create and patch

From: Henry Hu <henry.hu.sh_at_gmail.com>
Date: Sun, 9 Nov 2014 16:15:17 -0500
Hi,

I've hit a crash in the fuse module when doing a rsync to an ntfs volume
mounted with ntfs-3g.
The crash is the same as ones reported before, in

https://lists.freebsd.org/pipermail/freebsd-current/2013-October/045993.html

and there are other similar reports:

http://www.bsdforen.de/threads/probleme-mit-rsync-und-sshfs.29323/

After digging it a bit, I found that the problem is in fuse_vnop_create().
Check
https://github.com/freebsd/freebsd/blame/master/sys/fs/fuse/fuse_vnops.c#L337
.
At line 337, it checks if vap->va_type is VREG, and if it is not, it goes
to label bringup.
Then, feo is assigned with fdip->answ and used. But fdip which points to
fdi is initialized after the goto. As a result, when vap->va_type != VREG,
fdi is not initialized and feo is invalid.

I made the following patch and it works for me. In my case, the problematic
file is a socket.

Index: fuse_vnops.c
===================================================================
--- fuse_vnops.c        (版本 274059)
+++ fuse_vnops.c        (工作副本)
_at__at_ -336,7 +336,8 _at__at_
        /* XXX: Will we ever want devices ? */
        if ((vap->va_type != VREG)) {
                MPASS(vap->va_type != VFIFO);
-               goto bringup;
+               printf("unsupported vatype: %d\n", vap->va_type);
+               return EINVAL;
        }
        debug_printf("parent nid = %ju, mode = %x\n", (uintmax_t)parentnid,
            mode);
_at__at_ -364,7 +365,7 _at__at_
                debug_printf("create: got err=%d from daemon\n", err);
                goto out;
        }
-bringup:
+
        feo = fdip->answ;

        if ((err = fuse_internal_checkentry(feo, VREG))) {

But I think that fuse filesystems may support file types other than VREG,
so maybe we should remove that check completely?

-- 
Cheers,
Henry
Received on Sun Nov 09 2014 - 20:15:59 UTC

This archive was generated by hypermail 2.4.0 : Wed May 19 2021 - 11:40:53 UTC