From 0479a63023e04ba8452cc94bd51bc5a9a747de45 Mon Sep 17 00:00:00 2001 From: Ayush Ranjan Date: Fri, 23 Sep 2022 15:01:39 -0700 Subject: [PATCH] Use a different host FD to back lisafs.ControlFD for a bound socket. Earlier we were using the socket(2) FD as the socket file's lisafs.ControlFD. However, the same socket(2) FD is used to back the lisafs.BoundSocketFD. These are two separate FDIDs on the lisafs connection. Closing one, should not make the other unusable. PiperOrigin-RevId: 476470242 --- pkg/lisafs/client_file.go | 2 ++ runsc/fsgofer/lisafs.go | 32 ++++++++++++++++++++++---------- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/pkg/lisafs/client_file.go b/pkg/lisafs/client_file.go index 226a22390..73f8a5684 100644 --- a/pkg/lisafs/client_file.go +++ b/pkg/lisafs/client_file.go @@ -591,6 +591,8 @@ type ClientBoundSocketFD struct { // Close implements transport.BoundSocketFD.Close. func (f *ClientBoundSocketFD) Close(ctx context.Context) { _ = unix.Close(int(f.notificationFD)) + // flush is true because the socket FD must be closed immediately on the + // server. close(2) on socket FD impacts application behavior. f.client.CloseFD(ctx, f.fd, true /* flush */) } diff --git a/runsc/fsgofer/lisafs.go b/runsc/fsgofer/lisafs.go index 42c749836..f52c1c4f6 100644 --- a/runsc/fsgofer/lisafs.go +++ b/runsc/fsgofer/lisafs.go @@ -689,32 +689,44 @@ func (fd *controlFDLisa) BindAt(name string, sockType uint32) (*lisafs.ControlFD if err != nil { return nil, linux.Statx{}, nil, -1, err } - if err := unix.Bind(sockFD, &unix.SockaddrUnix{Name: socketPath}); err != nil { + cu := cleanup.Make(func() { _ = unix.Close(sockFD) + }) + defer cu.Clean() + + if err := unix.Bind(sockFD, &unix.SockaddrUnix{Name: socketPath}); err != nil { return nil, linux.Statx{}, nil, -1, err } + cu.Add(func() { + _ = unix.Unlink(socketPath) + }) + + sockFileFD, err := tryOpen(func(flags int) (int, error) { + return unix.Openat(fd.hostFD, name, flags, 0) + }) + if err != nil { + return nil, linux.Statx{}, nil, -1, err + } + cu.Add(func() { + _ = unix.Close(sockFileFD) + }) // Stat the socket. - sockStat, err := fstatTo(sockFD) + sockStat, err := fstatTo(sockFileFD) if err != nil { - _ = unix.Close(sockFD) - _ = unix.Unlink(socketPath) return nil, linux.Statx{}, nil, -1, err } - // Get an os.File that will back future socket calls. - sockFile := os.NewFile(uintptr(sockFD), socketPath) - // Create an FD that will be donated to the sandbox. - sockFDToDonate, err := unix.Dup(int(sockFile.Fd())) + sockFDToDonate, err := unix.Dup(sockFD) if err != nil { - _ = unix.Unlink(socketPath) return nil, linux.Statx{}, nil, -1, err } + cu.Release() socketControlFD := newControlFDLisa(sockFD, fd, socketPath, linux.ModeSocket) boundSocketFD := &boundSocketFDLisa{ - sock: sockFile, + sock: os.NewFile(uintptr(sockFD), socketPath), } boundSocketFD.Init(socketControlFD.FD(), boundSocketFD)