jstaf/onedriver

Use after free race condition on opened file descriptor

Ciaxur opened this issue · 1 comments

Summary

Commit: 15a1c64 (v0.14.1)

While in a git directory, there's a race condition that causes a segfault when attempting to use the stats result of an open file descriptor here:

inode.DriveItem.Size = uint64(st.Size())

There's an un-handled error on the preceding line, which when logged, indicates the use of a closed file id:

st, _ := fd.Stat()

Jul 14 15:03:51 hostname onedriver[2362800]: 15:03:51 DBG Unhandled error! stat /home/user/.cache/onedriver/home-user-drives-onedrive/content/36F66C8E2C7FC2B9!109987: use of closed file id=36F66C8E2C7FC2B9!109987 nodeID=95 op=Open path=/path/to/git_dir/.git/config

The segfault error:

Jul 14 15:03:51 hostname onedriver[2362800]: panic: runtime error: invalid memory address or nil pointer dereference
Jul 14 15:03:51 hostname onedriver[2362800]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x6dd977]
Jul 14 15:03:51 hostname onedriver[2362800]: goroutine 55 [running]:
Jul 14 15:03:51 hostname onedriver[2362800]: github.com/jstaf/onedriver/fs.(*Filesystem).Open(0xc00018a340, 0x4766fd?, 0xc00012f160, 0xc000b21c98?)
Jul 14 15:03:51 hostname onedriver[2362800]:         /home/user/code/onedriver/fs/fs.go:515 +0x737
Jul 14 15:03:51 hostname onedriver[2362800]: github.com/hanwen/go-fuse/v2/fuse.doOpen(0xc00012efc8?, 0xc00012efc8)
Jul 14 15:03:51 hostname onedriver[2362800]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.1.0/fuse/opcode.go:146 +0x4a
Jul 14 15:03:51 hostname onedriver[2362800]: github.com/hanwen/go-fuse/v2/fuse.(*Server).handleRequest(0xc000728160, 0xc00012efc8)
Jul 14 15:03:51 hostname onedriver[2362800]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.1.0/fuse/server.go:483 +0x253
Jul 14 15:03:51 hostname onedriver[2362800]: github.com/hanwen/go-fuse/v2/fuse.(*Server).loop(0xc000728160, 0x1)
Jul 14 15:03:51 hostname onedriver[2362800]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.1.0/fuse/server.go:456 +0x118
Jul 14 15:03:51 hostname onedriver[2362800]: created by github.com/hanwen/go-fuse/v2/fuse.(*Server).readRequest in goroutine 51
Jul 14 15:03:51 hostname onedriver[2362800]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.1.0/fuse/server.go:323 +0x55e
Jul 14 15:03:51 hostname systemd[2682]: onedriver@home-user-drives-onedrive.service: Main process exited, code=exited, status=2/INVALIDARGUMENT

Here's a commit of the additional logs I used for debugging, if helpful: 272b1bc

How to reproduce?

  1. Create an empty git repo
  2. Wait for segfault

I created a test directory within my mounted onedriver fs. I was in that directory of course, while monitoring journalctl for onedriver:

journalctl -f | rg -i onedriver

In <1min I get a segfault:

Jul 14 15:28:37 hostname onedriver[2749545]: 15:28:37 INF Found content in cache. id=36F66C8E2C7FC2B9!114389 nodeID=187 op=Open path=/path/to/onedrive/test/.git/config
Jul 14 15:28:37 hostname onedriver[2749545]: 15:28:37 DBG  id=36F66C8E2C7FC2B9!114399 nodeID=191 op=Open path=/path/to/onedrive/test/.git/HEAD
Jul 14 15:28:37 hostname onedriver[2749545]: panic: runtime error: invalid memory address or nil pointer dereference
Jul 14 15:28:37 hostname onedriver[2749545]: [signal SIGSEGV: segmentation violation code=0x1 addr=0x38 pc=0x6df44a]
Jul 14 15:28:37 hostname onedriver[2749545]: goroutine 78 [running]:
Jul 14 15:28:37 hostname onedriver[2749545]: github.com/jstaf/onedriver/fs.(*Filesystem).Open(0xc00019c000, 0x4a8ef8?, 0xc0000fe1a0, 0xc000153e18?)
Jul 14 15:28:37 hostname onedriver[2749545]:         /home/user/code/onedriver/fs/fs.go:510 +0x66a
Jul 14 15:28:37 hostname onedriver[2749545]: github.com/hanwen/go-fuse/v2/fuse.doOpen(0xc0000fe008?, 0xc0000fe008)
Jul 14 15:28:37 hostname onedriver[2749545]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.4.2/fuse/opcode.go:179 +0x4a
Jul 14 15:28:37 hostname onedriver[2749545]: github.com/hanwen/go-fuse/v2/fuse.(*Server).handleRequest(0xc000131380, 0xc0000fe008)
Jul 14 15:28:37 hostname onedriver[2749545]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.4.2/fuse/server.go:527 +0x273
Jul 14 15:28:37 hostname onedriver[2749545]: github.com/hanwen/go-fuse/v2/fuse.(*Server).loop(0xc000131380, 0x1)
Jul 14 15:28:37 hostname onedriver[2749545]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.4.2/fuse/server.go:500 +0x118
Jul 14 15:28:37 hostname onedriver[2749545]: created by github.com/hanwen/go-fuse/v2/fuse.(*Server).readRequest in goroutine 25
Jul 14 15:28:37 hostname onedriver[2749545]:         /home/user/go/pkg/mod/github.com/hanwen/go-fuse/v2@v2.4.2/fuse/server.go:367 +0x54c
Jul 14 15:28:37 hostname systemd[2682]: onedriver@home-user-drives-onedrive.service: Main process exited, code=exited, status=2/INVALIDARGUMENT

I couldn't reproduce this in a unit test, but I do see the issue after reviewing your PR. Thank you! I've merged your fix.