Skip to content

libtailscale: do not close the caller's fd in tailscale_set_logfd - #68

Open
RaphaelFakhri wants to merge 1 commit into
tailscale:mainfrom
RaphaelFakhri:fix-logfd-finalizer
Open

RaphaelFakhri wants to merge 1 commit into
tailscale:mainfrom
RaphaelFakhri:fix-logfd-finalizer

Conversation

@RaphaelFakhri

Copy link
Copy Markdown

TsnetSetLogFD wraps the caller's fd in os.NewFile. An *os.File closes its fd when it is garbage collected, so after the logger is replaced (a second tailscale_set_logfd call, for example with -1) or the server is closed, the next GC cycle closes an fd that belongs to the C caller. With tailscale_set_logfd(sd, 2) this closes the process's stderr; if the fd number has been reused in the meantime, it closes an unrelated file or socket.

Change

  • TsnetSetLogFD writes to the fd with write(2) through a small fdWriter type, which never closes it. Log output is unchanged.
  • TestSetLogFD (in tsnetctest) passes one end of a pipe to tailscale_set_logfd, resets the logger with -1, closes the server, runs GC, and checks that the fd is still open.

Testing

go test -run TestSetLogFD -count=3 .   # without the fix: 3 of 3 fail, "log fd 7 was closed by libtailscale: bad file descriptor"
go test -run TestSetLogFD -count=3 .   # with the fix: 3 of 3 pass
go test -count=1 -v .                  # TestConn, TestGetRemoteAddr, TestSetLogFD, TestExtractIP pass
gofmt -l . && go vet . ./tsnetctest/   # clean

TsnetSetLogFD wrapped the caller's fd in os.NewFile. An *os.File
closes its fd when it is garbage collected, so once the logger was
replaced (another tailscale_set_logfd call) or the server was closed,
the next GC cycle closed an fd that belongs to the C caller. With
tailscale_set_logfd(sd, 2) that closes the process's stderr, and if the
number has since been reused, an unrelated file or socket.

Write to the fd with write(2) through a small io.Writer instead, which
never closes it.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant