Skip to content

Commit

Permalink
Merge pull request #6 from kinvolk/rata/fix-double-close
Browse files Browse the repository at this point in the history
Fix double close(2) when using EventMetadata.Close() and EventMetadata.File()
  • Loading branch information
s3rj1k authored Sep 17, 2021
2 parents 500f21f + 3d5480a commit 9c00a30
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 3 deletions.
12 changes: 11 additions & 1 deletion cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,18 @@ func main() {
return "", err
}

dataFile := data.File()
defer dataFile.Close()

fInfo, err := dataFile.Stat()
if err != nil {
return "", err
}

mTime := fInfo.ModTime()

if data.MatchMask(unix.FAN_CLOSE_WRITE) || data.MatchMask(unix.FAN_MODIFY) {
return fmt.Sprintf("PID:%d %s", data.GetPID(), path), nil
return fmt.Sprintf("PID:%d %s - %v", data.GetPID(), path, mTime), nil
}

return "", fmt.Errorf("fanotify: unknown event")
Expand Down
22 changes: 20 additions & 2 deletions fanotify/fanotify.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,27 @@ func (metadata *EventMetadata) MatchMask(mask int) bool {
}

// File returns pointer to os.File created from event metadata supplied Fd.
// File needs to be Closed after usage, to prevent an Fd leak.
// File needs to be Closed after usage.
func (metadata *EventMetadata) File() *os.File {
return os.NewFile(uintptr(metadata.Fd), "")
// The fd used in os.NewFile() can be garbage collected, making the fd
// used to create it invalid. This can be problematic, as now the fd can
// be closed when the os.File created here is GC/Close() or when our
// function Close() is used too.
//
// To avoid having so many references to the same fd and have one close
// silently invalidate other users, we dup() the fd. This way, a new fd
// is created every time File() is used and this even works if File() is
// used multiple times (they never point to the same fd).
//
// For more details on when this can happen, see:
// https://pkg.go.dev/os#File.Fd, that is referenced from:
// https://pkg.go.dev/os#NewFile
fd, err := unix.Dup(int(metadata.Fd))
if err != nil {
return nil
}

return os.NewFile(uintptr(fd), "")
}

// NotifyFD is a notify file handle, used by all fanotify functions.
Expand Down

0 comments on commit 9c00a30

Please sign in to comment.