Update BindAt RPC to include other creation options.

BindAt should also be setting the socket file mode and owners.
All file creation RPCs do this. This is required for correct behavior.

PiperOrigin-RevId: 477023055
This commit is contained in:
Ayush Ranjan
2022-09-26 16:49:27 -07:00
committed by gVisor bot
parent f841b2511e
commit 68fd6aba43
6 changed files with 27 additions and 15 deletions
+8 -6
View File
@@ -421,16 +421,18 @@ func (f *ClientFD) Flush(ctx context.Context) error {
}
// BindAt makes the BindAt RPC.
func (f *ClientFD) BindAt(ctx context.Context, sockType linux.SockType, name string) (Inode, *ClientBoundSocketFD, error) {
req := BindAtReq{
DirFD: f.fd,
SockType: primitive.Uint32(sockType),
Name: SizedString(name),
}
func (f *ClientFD) BindAt(ctx context.Context, sockType linux.SockType, name string, mode linux.FileMode, uid UID, gid GID) (Inode, *ClientBoundSocketFD, error) {
var (
req BindAtReq
resp BindAtResp
hostSocketFD [1]int
)
req.DirFD = f.fd
req.SockType = primitive.Uint32(sockType)
req.Name = SizedString(name)
req.Mode = mode
req.UID = uid
req.GID = gid
ctx.UninterruptibleSleepStart(false)
err := f.client.SndRcvMessage(BindAt, uint32(req.SizeBytes()), req.MarshalBytes, resp.CheckedUnmarshal, hostSocketFD[:], req.String, resp.String)
ctx.UninterruptibleSleepFinish(false)
+1 -1
View File
@@ -492,7 +492,7 @@ type ControlFDImpl interface {
// connections).
//
// On the server, BindAt has a write concurrency guarantee.
BindAt(name string, sockType uint32) (*ControlFD, linux.Statx, *BoundSocketFD, int, error)
BindAt(name string, sockType uint32, mode linux.FileMode, uid UID, gid GID) (*ControlFD, linux.Statx, *BoundSocketFD, int, error)
// UnlinkAt the file identified by name in this directory.
//
+1 -1
View File
@@ -1103,7 +1103,7 @@ func BindAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32,
if dir.node.isDeleted() {
return unix.EINVAL
}
childFD, childStat, boundSocketFD, hostSocketFD, err = dir.impl.BindAt(name, uint32(req.SockType))
childFD, childStat, boundSocketFD, hostSocketFD, err = dir.impl.BindAt(name, uint32(req.SockType), req.Mode, req.UID, req.GID)
return err
}); err != nil {
return 0, err
+5 -5
View File
@@ -1290,19 +1290,19 @@ func (*ConnectResp) String() string {
// BindAtReq is used to make BindAt requests.
type BindAtReq struct {
DirFD FDID
createCommon
SockType primitive.Uint32
Name SizedString
}
// SizeBytes implements marshal.Marshallable.SizeBytes.
func (b *BindAtReq) SizeBytes() int {
return b.DirFD.SizeBytes() + b.SockType.SizeBytes() + b.Name.SizeBytes()
return b.createCommon.SizeBytes() + b.SockType.SizeBytes() + b.Name.SizeBytes()
}
// MarshalBytes implements marshal.Marshallable.MarshalBytes.
func (b *BindAtReq) MarshalBytes(dst []byte) []byte {
dst = b.DirFD.MarshalUnsafe(dst)
dst = b.createCommon.MarshalUnsafe(dst)
dst = b.SockType.MarshalUnsafe(dst)
return b.Name.MarshalBytes(dst)
}
@@ -1313,7 +1313,7 @@ func (b *BindAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) {
if b.SizeBytes() > len(src) {
return src, false
}
srcRemain := b.DirFD.UnmarshalUnsafe(src)
srcRemain := b.createCommon.UnmarshalUnsafe(src)
srcRemain = b.SockType.UnmarshalUnsafe(srcRemain)
if srcRemain, ok := b.Name.CheckedUnmarshal(srcRemain); ok {
return srcRemain, ok
@@ -1323,7 +1323,7 @@ func (b *BindAtReq) CheckedUnmarshal(src []byte) ([]byte, bool) {
// String implements fmt.Stringer.String.
func (b *BindAtReq) String() string {
return fmt.Sprintf("BindAtReq{DirFD: %d, SockType: %d, Name: %q}", b.DirFD, b.SockType, b.Name)
return fmt.Sprintf("BindAtReq{DirFD: %d, Mode: %s, UID: %d, GID: %d, SockType: %d, Name: %q}", b.DirFD, b.Mode, b.UID, b.GID, b.SockType, b.Name)
}
// BindAtResp is used to communicate BindAt response.
+1 -1
View File
@@ -1638,7 +1638,7 @@ func (d *dentry) mknodLisaLocked(ctx context.Context, name string, creds *auth.C
// This mknod(2) is coming from unix bind(2), as opts.Endpoint is set.
sockType := opts.Endpoint.(transport.Endpoint).Type()
childInode, boundSocketFD, err := d.controlFDLisa.BindAt(ctx, sockType, name)
childInode, boundSocketFD, err := d.controlFDLisa.BindAt(ctx, sockType, name, opts.Mode, lisafs.UID(creds.EffectiveKUID), lisafs.GID(creds.EffectiveKGID))
if err != nil {
return err
}
+11 -1
View File
@@ -682,7 +682,7 @@ func (fd *controlFDLisa) Connect(sockType uint32) (int, error) {
}
// BindAt implements lisafs.ControlFDImpl.BindAt.
func (fd *controlFDLisa) BindAt(name string, sockType uint32) (*lisafs.ControlFD, linux.Statx, *lisafs.BoundSocketFD, int, error) {
func (fd *controlFDLisa) BindAt(name string, sockType uint32, mode linux.FileMode, uid lisafs.UID, gid lisafs.GID) (*lisafs.ControlFD, linux.Statx, *lisafs.BoundSocketFD, int, error) {
if !fd.Conn().ServerImpl().(*LisafsServer).config.HostUDS {
return nil, linux.Statx{}, nil, -1, unix.EPERM
}
@@ -716,6 +716,12 @@ func (fd *controlFDLisa) BindAt(name string, sockType uint32) (*lisafs.ControlFD
})
defer cu.Clean()
// fchmod(2) has to happen *before* the bind(2). sockFD's file mode will
// be used in creating the filesystem-object in bind(2).
if err := unix.Fchmod(sockFD, uint32(mode&^linux.FileTypeMask)); err != nil {
return nil, linux.Statx{}, nil, -1, err
}
if err := unix.Bind(sockFD, &unix.SockaddrUnix{Name: socketPath}); err != nil {
return nil, linux.Statx{}, nil, -1, err
}
@@ -733,6 +739,10 @@ func (fd *controlFDLisa) BindAt(name string, sockType uint32) (*lisafs.ControlFD
_ = unix.Close(sockFileFD)
})
if err := unix.Fchownat(sockFileFD, "", int(uid), int(gid), unix.AT_EMPTY_PATH|unix.AT_SYMLINK_NOFOLLOW); err != nil {
return nil, linux.Statx{}, nil, -1, err
}
// Stat the socket.
sockStat, err := fstatTo(sockFileFD)
if err != nil {