mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Add a new RPC ConnectWithCreds to allow gofer to connect to a unix domain socket with application's credentials
This commit is contained in:
@@ -467,13 +467,30 @@ func (f *ClientFD) BindAt(ctx context.Context, sockType linux.SockType, name str
|
||||
}
|
||||
|
||||
// Connect makes the Connect RPC.
|
||||
func (f *ClientFD) Connect(ctx context.Context, sockType linux.SockType) (int, error) {
|
||||
req := ConnectReq{FD: f.fd, SockType: uint32(sockType)}
|
||||
var resp ConnectResp
|
||||
func (f *ClientFD) Connect(ctx context.Context, sockType linux.SockType, euid UID, egid GID) (int, error) {
|
||||
credsAvailable := euid != NoUID && egid != NoGID
|
||||
var err error
|
||||
var sockFD [1]int
|
||||
ctx.UninterruptibleSleepStart(false)
|
||||
err := f.client.SndRcvMessage(Connect, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.CheckedUnmarshal, sockFD[:], req.String, resp.String)
|
||||
ctx.UninterruptibleSleepFinish(false)
|
||||
var resp ConnectResp
|
||||
if credsAvailable && f.client.IsSupported(ConnectWithCreds) {
|
||||
req := ConnectWithCredsReq{
|
||||
ConnectReq: ConnectReq{
|
||||
FD: f.fd,
|
||||
SockType: uint32(sockType),
|
||||
},
|
||||
UID: euid,
|
||||
GID: egid,
|
||||
}
|
||||
ctx.UninterruptibleSleepStart(false)
|
||||
err = f.client.SndRcvMessage(ConnectWithCreds, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.CheckedUnmarshal, sockFD[:], req.String, resp.String)
|
||||
ctx.UninterruptibleSleepFinish(false)
|
||||
} else {
|
||||
req := ConnectReq{FD: f.fd, SockType: uint32(sockType)}
|
||||
ctx.UninterruptibleSleepStart(false)
|
||||
err = f.client.SndRcvMessage(Connect, uint32(req.SizeBytes()), req.MarshalUnsafe, resp.CheckedUnmarshal, sockFD[:], req.String, resp.String)
|
||||
ctx.UninterruptibleSleepFinish(false)
|
||||
}
|
||||
|
||||
if err == nil && sockFD[0] < 0 {
|
||||
err = unix.EBADF
|
||||
}
|
||||
|
||||
@@ -484,6 +484,13 @@ type ControlFDImpl interface {
|
||||
// On the server, Connect has a read concurrency guarantee.
|
||||
Connect(sockType uint32) (int, error)
|
||||
|
||||
// ConnectWithCreds is a wrapper around Connect but first changes the gofer's
|
||||
// euid and egid to the given uid and gid before calling Connect. It restores
|
||||
// the euid and egid after Connect.
|
||||
//
|
||||
// On the server, ConnectWithCreds has a read concurrency guarantee.
|
||||
ConnectWithCreds(sockType uint32, uid UID, gid GID) (int, error)
|
||||
|
||||
// BindAt creates a host unix domain socket of type sockType, bound to
|
||||
// the given namt of type sockType, bound to the given name. It returns
|
||||
// a ControlFD that can be used for path operations on the socket, a
|
||||
|
||||
+63
-32
@@ -46,38 +46,39 @@ const (
|
||||
type RPCHandler func(c *Connection, comm Communicator, payloadLen uint32) (uint32, error)
|
||||
|
||||
var handlers = [...]RPCHandler{
|
||||
Error: ErrorHandler,
|
||||
Mount: MountHandler,
|
||||
Channel: ChannelHandler,
|
||||
FStat: FStatHandler,
|
||||
SetStat: SetStatHandler,
|
||||
Walk: WalkHandler,
|
||||
WalkStat: WalkStatHandler,
|
||||
OpenAt: OpenAtHandler,
|
||||
OpenCreateAt: OpenCreateAtHandler,
|
||||
Close: CloseHandler,
|
||||
FSync: FSyncHandler,
|
||||
PWrite: PWriteHandler,
|
||||
PRead: PReadHandler,
|
||||
MkdirAt: MkdirAtHandler,
|
||||
MknodAt: MknodAtHandler,
|
||||
SymlinkAt: SymlinkAtHandler,
|
||||
LinkAt: LinkAtHandler,
|
||||
FStatFS: FStatFSHandler,
|
||||
FAllocate: FAllocateHandler,
|
||||
ReadLinkAt: ReadLinkAtHandler,
|
||||
Flush: FlushHandler,
|
||||
UnlinkAt: UnlinkAtHandler,
|
||||
RenameAt: RenameAtHandler,
|
||||
Getdents64: Getdents64Handler,
|
||||
FGetXattr: FGetXattrHandler,
|
||||
FSetXattr: FSetXattrHandler,
|
||||
FListXattr: FListXattrHandler,
|
||||
FRemoveXattr: FRemoveXattrHandler,
|
||||
Connect: ConnectHandler,
|
||||
BindAt: BindAtHandler,
|
||||
Listen: ListenHandler,
|
||||
Accept: AcceptHandler,
|
||||
Error: ErrorHandler,
|
||||
Mount: MountHandler,
|
||||
Channel: ChannelHandler,
|
||||
FStat: FStatHandler,
|
||||
SetStat: SetStatHandler,
|
||||
Walk: WalkHandler,
|
||||
WalkStat: WalkStatHandler,
|
||||
OpenAt: OpenAtHandler,
|
||||
OpenCreateAt: OpenCreateAtHandler,
|
||||
Close: CloseHandler,
|
||||
FSync: FSyncHandler,
|
||||
PWrite: PWriteHandler,
|
||||
PRead: PReadHandler,
|
||||
MkdirAt: MkdirAtHandler,
|
||||
MknodAt: MknodAtHandler,
|
||||
SymlinkAt: SymlinkAtHandler,
|
||||
LinkAt: LinkAtHandler,
|
||||
FStatFS: FStatFSHandler,
|
||||
FAllocate: FAllocateHandler,
|
||||
ReadLinkAt: ReadLinkAtHandler,
|
||||
Flush: FlushHandler,
|
||||
UnlinkAt: UnlinkAtHandler,
|
||||
RenameAt: RenameAtHandler,
|
||||
Getdents64: Getdents64Handler,
|
||||
FGetXattr: FGetXattrHandler,
|
||||
FSetXattr: FSetXattrHandler,
|
||||
FListXattr: FListXattrHandler,
|
||||
FRemoveXattr: FRemoveXattrHandler,
|
||||
Connect: ConnectHandler,
|
||||
BindAt: BindAtHandler,
|
||||
Listen: ListenHandler,
|
||||
Accept: AcceptHandler,
|
||||
ConnectWithCreds: ConnectWithCredsHandler,
|
||||
}
|
||||
|
||||
// ErrorHandler handles Error message.
|
||||
@@ -1069,6 +1070,36 @@ func ConnectHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// ConnectWithCredsHandler handles the ConnectWithCreds RPC.
|
||||
func ConnectWithCredsHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
|
||||
var req ConnectWithCredsReq
|
||||
if _, ok := req.CheckedUnmarshal(comm.PayloadBuf(payloadLen)); !ok {
|
||||
return 0, unix.EIO
|
||||
}
|
||||
|
||||
fd, err := c.lookupControlFD(req.FD)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
defer fd.DecRef(nil)
|
||||
if !fd.IsSocket() {
|
||||
return 0, unix.ENOTSOCK
|
||||
}
|
||||
var sock int
|
||||
if err := fd.safelyRead(func() error {
|
||||
if fd.node.isDeleted() {
|
||||
return unix.EINVAL
|
||||
}
|
||||
sock, err = fd.impl.ConnectWithCreds(req.SockType, req.UID, req.GID)
|
||||
return err
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
comm.DonateFD(sock)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// BindAtHandler handles the BindAt RPC.
|
||||
func BindAtHandler(c *Connection, comm Communicator, payloadLen uint32) (uint32, error) {
|
||||
var req BindAtReq
|
||||
|
||||
@@ -172,6 +172,10 @@ const (
|
||||
|
||||
// Accept is analogous to accept4(2).
|
||||
Accept MID = 31
|
||||
|
||||
// ConnectWithCreds is analogous to connect(2) but it asks the server
|
||||
// to connect with the provided effective uid/gid.
|
||||
ConnectWithCreds MID = 32
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -1318,6 +1322,21 @@ func (*ConnectResp) String() string {
|
||||
return "ConnectResp{}"
|
||||
}
|
||||
|
||||
// ConnectWithCredsReq is used to make a ConnectWithCreds request. The response is also ConnectResp.
|
||||
//
|
||||
// +marshal boundCheck
|
||||
type ConnectWithCredsReq struct {
|
||||
ConnectReq
|
||||
// UID and GID are used to specify the credentials to connect with.
|
||||
UID UID
|
||||
GID GID
|
||||
}
|
||||
|
||||
// String implements fmt.Stringer.String.
|
||||
func (c *ConnectWithCredsReq) String() string {
|
||||
return fmt.Sprintf("ConnectWithCredsReq{FD: %d, SockType: %d, UID: %d, GID: %d}", c.FD, c.SockType, c.UID, c.GID)
|
||||
}
|
||||
|
||||
// BindAtReq is used to make BindAt requests.
|
||||
type BindAtReq struct {
|
||||
createCommon
|
||||
|
||||
Reference in New Issue
Block a user