mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge pull request #9551 from amysaq2023:support-external-stack
PiperOrigin-RevId: 677933413
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
// Copyright 2023 The gVisor Authors.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package stack
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/abi/linux"
|
||||
"gvisor.dev/gvisor/pkg/safemem"
|
||||
"gvisor.dev/gvisor/pkg/sentry/socket/plugin/cgo"
|
||||
)
|
||||
|
||||
type pluginStackRW struct {
|
||||
handle uint32
|
||||
|
||||
// Represent both input and output flags.
|
||||
flags uint32
|
||||
|
||||
// Reused as msg_control for read.
|
||||
to []byte
|
||||
|
||||
iovs [3]syscall.Iovec
|
||||
}
|
||||
|
||||
var pluginStackRWPool = sync.Pool{
|
||||
New: func() any {
|
||||
return &pluginStackRW{}
|
||||
},
|
||||
}
|
||||
|
||||
func getReadWriter(handle uint32) *pluginStackRW {
|
||||
rw := pluginStackRWPool.Get().(*pluginStackRW)
|
||||
rw.handle = handle
|
||||
return rw
|
||||
}
|
||||
|
||||
func putReadWriter(rw *pluginStackRW) {
|
||||
*rw = pluginStackRW{}
|
||||
pluginStackRWPool.Put(rw)
|
||||
}
|
||||
|
||||
// ReadToBlocks implements safemem.Reader.ReadToBlocks.
|
||||
func (rw *pluginStackRW) ReadToBlocks(dsts safemem.BlockSeq) (uint64, error) {
|
||||
// Set MSG_DONTWAIT flag to avoid blocking in plugin stack.
|
||||
flags := int(rw.flags) & ^linux.MSG_DONTWAIT
|
||||
if len(rw.to) != 0 || flags != 0 {
|
||||
iovs := iovecsFromBlockSeq(dsts, rw)
|
||||
rc, _, lc, mflags := cgo.Recvmsg(rw.handle, iovs, nil, rw.to, int(rw.flags))
|
||||
if rc >= 0 {
|
||||
rw.to = rw.to[:lc]
|
||||
rw.flags = uint32(mflags)
|
||||
}
|
||||
return translateReturn(rc)
|
||||
}
|
||||
|
||||
var rc int64
|
||||
if dsts.IsEmpty() {
|
||||
rc = 0
|
||||
} else if dsts.NumBlocks() == 1 {
|
||||
rc = cgo.Read(rw.handle, dsts.Head().Addr(), dsts.Head().Len())
|
||||
} else {
|
||||
rc = cgo.Readv(rw.handle, iovecsFromBlockSeq(dsts, rw))
|
||||
}
|
||||
|
||||
return translateReturn(rc)
|
||||
}
|
||||
|
||||
// WriteFromBlocks implements safemem.Writer.WriteFromBlocks.
|
||||
//
|
||||
// Preconditions: rw.d.metadataMu must be locked.
|
||||
func (rw *pluginStackRW) WriteFromBlocks(srcs safemem.BlockSeq) (uint64, error) {
|
||||
var rc int64
|
||||
|
||||
if rw.to != nil {
|
||||
if srcs.IsEmpty() {
|
||||
// Invoke plugin stack checking whether there is any error to report
|
||||
// on target socket which sends 0-length data.
|
||||
rc = cgo.Sendto(rw.handle, 0, 0, 0, rw.to)
|
||||
} else if srcs.NumBlocks() == 1 {
|
||||
rc = cgo.Sendto(rw.handle, srcs.Head().Addr(), srcs.Head().Len(), 0, rw.to)
|
||||
} else {
|
||||
iovs := iovecsFromBlockSeq(srcs, rw)
|
||||
rc = cgo.Sendmsg(rw.handle, iovs, rw.to, 0)
|
||||
}
|
||||
} else {
|
||||
if srcs.IsEmpty() {
|
||||
// Invoke plugin stack checking whether there is any error to report
|
||||
// on target socket which sends 0-length data.
|
||||
rc = cgo.Write(rw.handle, 0, 0)
|
||||
} else if srcs.NumBlocks() == 1 {
|
||||
rc = cgo.Write(rw.handle, srcs.Head().Addr(), srcs.Head().Len())
|
||||
} else {
|
||||
rc = cgo.Writev(rw.handle, iovecsFromBlockSeq(srcs, rw))
|
||||
}
|
||||
}
|
||||
return translateReturn(rc)
|
||||
}
|
||||
Reference in New Issue
Block a user