Bug 239830 - [FUSEFS]: fusefs doesn't send the entire fuse_getattr_in structure
Summary: [FUSEFS]: fusefs doesn't send the entire fuse_getattr_in structure
Status: In Progress
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Some People
Assignee: Alan Somers
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-08-13 21:04 UTC by Alan Somers
Modified: 2019-08-14 20:45 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Alan Somers freebsd_committer 2019-08-13 21:04:03 UTC
On FreeBSD CURRENT, trying to access the mountpoint of a fusefs-lkl mount returns EBADF.  I don't know yet whether this is due to a bug in fusefs-lkl, or a bug in the new fusefs(5) driver.

> uname -a
FreeBSD arginine-fbsd-head 13.0-CURRENT FreeBSD 13.0-CURRENT #7 r350943M: Mon Aug 12 22:46:56 UTC 2019     somers@arginine-fbsd-head:/usr/obj/usr/home/somers/freebsd/base/head/amd64.amd64/sys/GENERIC  amd64
> truncate -s 1g /tmp/ext2.img
> mkfs.ext2 /tmp/ext2.img 
mke2fs 1.45.3 (14-Jul-2019)
Creating filesystem with 262144 4k blocks and 65536 inodes
Filesystem UUID: b6ea7c26-79c2-445c-a128-3c7a2fc4c2c2
Superblock backups stored on blocks: 
	32768, 98304, 163840, 229376

Allocating group tables: done                            
Writing inode tables: done                            
Writing superblocks and filesystem accounting information: done
> lklfuse -o type=ext2,debug /tmp/ext2.img /tmp/mnt
FUSE library version: 2.9.9
nullpath_ok: 1
nopath: 1
utime_omit_ok: 1
[    0.000000] Linux version 4.16.0 (root@head-amd64-default-job-13) (gcc version 9.1.0 (FreeBSD Ports Collection)) #1 Sat Aug 3 20:01:57 UTC 2019
[    0.000000] bootmem address range: 0x802601000 - 0x806600000
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16159
[    0.000000] Kernel command line: mem=64M virtio_mmio.device=292@0x1000000:1
[    0.000000] Dentry cache hash table entries: 8192 (order: 4, 65536 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 3, 32768 bytes)
[    0.000000] Memory available: 64440k/65532k RAM
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] NR_IRQS: 4096
[    0.000000] lkl: irqs initialized
[    0.000000] clocksource: lkl: mask: 0xffffffffffffffff max_cycles: 0x1cd42e4dffb, max_idle_ns: 881590591483 ns
[    0.000008] lkl: time and timers initialized (irq2)
[    0.000038] pid_max: default: 4096 minimum: 301
[    0.000077] Mount-cache hash table entries: 512 (order: 0, 4096 bytes)
[    0.000085] Mountpoint-cache hash table entries: 512 (order: 0, 4096 bytes)
[    0.006054] console [lkl_console0] enabled
[    0.006083] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.006100] xor: automatically using best checksumming function   8regs     
[    0.006181] random: get_random_u32 called from bucket_table_alloc+0x8b/0x240 with crng_init=0
[    0.006233] NET: Registered protocol family 16
[    0.341124] raid6: int64x1  gen()  9406 MB/s
[    0.681041] raid6: int64x1  xor()  5210 MB/s
[    1.021097] raid6: int64x2  gen() 11317 MB/s
[    1.361247] raid6: int64x2  xor()  6949 MB/s
[    1.701154] raid6: int64x4  gen()  8793 MB/s
[    2.041063] raid6: int64x4  xor()  5944 MB/s
[    2.381000] raid6: int64x8  gen()  8385 MB/s
[    2.561119] random: fast init done
[    2.721020] raid6: int64x8  xor()  5898 MB/s
[    2.721045] raid6: using algorithm int64x2 gen() 11317 MB/s
[    2.721055] raid6: .... xor() 6949 MB/s, rmw enabled
[    2.721065] raid6: using intx1 recovery algorithm
[    2.721212] clocksource: Switched to clocksource lkl
[    2.721343] NET: Registered protocol family 2
[    2.721565] tcp_listen_portaddr_hash hash table entries: 256 (order: 0, 4096 bytes)
[    2.721586] TCP established hash table entries: 512 (order: 0, 4096 bytes)
[    2.721597] TCP bind hash table entries: 512 (order: 0, 4096 bytes)
[    2.721608] TCP: Hash tables configured (established 512 bind 512)
[    2.721649] UDP hash table entries: 128 (order: 0, 4096 bytes)
[    2.721660] UDP-Lite hash table entries: 128 (order: 0, 4096 bytes)
[    2.721816] virtio-mmio: Registering device virtio-mmio.0 at 0x1000000-0x1000123, IRQ 1.
[    2.722891] workingset: timestamp_bits=62 max_order=14 bucket_order=0
[    2.723841] SGI XFS with ACLs, security attributes, no debug enabled
[    2.744209] io scheduler noop registered
[    2.744235] io scheduler deadline registered
[    2.744298] io scheduler cfq registered (default)
[    2.744309] io scheduler mq-deadline registered
[    2.744318] io scheduler kyber registered
[    2.744338] virtio-mmio virtio-mmio.0: Failed to enable 64-bit or 32-bit DMA.  Trying to continue, but this might not work.
[    2.746783] virtio_blk virtio0: [vda] 2097152 512-byte logical blocks (1.07 GB/1.00 GiB)
[    2.747978] NET: Registered protocol family 10
[    2.749093] Segment Routing with IPv6
[    2.749144] sit: IPv6, IPv4 and MPLS over IPv4 tunneling driver
[    2.749526] Btrfs loaded, crc32c=crc32c-generic
[    2.749651] Warning: unable to open an initial console.
[    2.749695] This architecture does not have kernel memory protection.
[    2.751010] EXT4-fs (vda): mounting ext2 file system using the ext4 subsystem
[    2.753282] EXT4-fs (vda): mounted filesystem without journal. Opts: 
warning: multithreaded mode not supported
unique: 1, opcode: INIT (26), nodeid: 0, insize: 56, pid: 1832
INIT: 7.23
flags=0x00010033
max_readahead=0x00010000
   INIT: 7.19
   flags=0x00000011
   max_readahead=0x00010000
   max_write=0x00020000
   max_background=0
   congestion_threshold=0
   unique: 1, success, outsize: 40
unique: 2, opcode: GETATTR (3), nodeid: 1, insize: 40, pid: 1836
fgetattr[281694020108288] (null)
   unique: 2, error: -9 (Bad file descriptor), outsize: 16

The GETATTR operation was triggered by doing "stat /tmp/mnt" in another window.  Notice that nodeid is 1.  In the FUSE protocol, nodeid 1 always refers to the mountpoint.  Obviously, EBADF is not a valid error for that operation.

This bug cannot be reproduced in 11.3-RELEASE-p1.
Comment 1 Alan Somers freebsd_committer 2019-08-14 20:40:24 UTC
Turns out to be a kernel bug. In FUSE protocol 7.9 and above, FUSE_GETATTR has a larger payload.  We aren't sending the entire payload.  I never noticed until now, because the extra fields are all always 0.  But fusefs-lkl checks the overall size and complains.  Most fuse daemons don't.
Comment 2 commit-hook freebsd_committer 2019-08-14 20:45:58 UTC
A commit references this bug:

Author: asomers
Date: Wed Aug 14 20:45:01 UTC 2019
New revision: 351042
URL: https://svnweb.freebsd.org/changeset/base/351042

Log:
  fusefs: Fix the size of fuse_getattr_in

  In FUSE protocol 7.9, the size of the FUSE_GETATTR request has increased.
  However, the fusefs driver is currently not sending the additional fields.
  In our implementation, the additional fields are always zero, so I there
  haven't been any test failures until now.  But fusefs-lkl requires the
  request's length to be correct.

  Fix this bug, and also enhance the test suite to catch similar bugs.

  PR:		239830
  MFC after:	2 weeks
  MFC-With:	350665
  Sponsored by:	The FreeBSD Foundation

Changes:
  head/sys/fs/fuse/fuse_internal.c
  head/tests/sys/fs/fusefs/getattr.cc
  head/tests/sys/fs/fusefs/mockfs.cc
  head/tests/sys/fs/fusefs/mockfs.hh