summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorgVisor bot <gvisor-bot@google.com>2021-02-18 01:45:49 +0000
committergVisor bot <gvisor-bot@google.com>2021-02-18 01:45:49 +0000
commit2d9dc3c1b7be34442f224a10013dd5f3823c962a (patch)
treee25228b2da4ae13353eb247d3771352a182fb41e
parent45be62df210badd412752214925e0de28887ed54 (diff)
parentf051ec64639b83faabcfe766ff078072def3c2aa (diff)
Merge release-20210208.0-64-gf051ec646 (automated)
-rw-r--r--pkg/fdchannel/fdchannel_unsafe.go9
-rw-r--r--pkg/flipcall/flipcall_unsafe.go13
-rw-r--r--pkg/gohacks/gohacks_unsafe.go38
-rw-r--r--pkg/safemem/block_unsafe.go13
-rw-r--r--pkg/safemem/seq_unsafe.go7
-rw-r--r--pkg/sentry/arch/stack_unsafe.go23
-rw-r--r--pkg/sentry/vfs/mount_unsafe.go5
-rw-r--r--pkg/usermem/addr_range_seq_unsafe.go7
8 files changed, 60 insertions, 55 deletions
diff --git a/pkg/fdchannel/fdchannel_unsafe.go b/pkg/fdchannel/fdchannel_unsafe.go
index b253a8fdd..0ebdedf26 100644
--- a/pkg/fdchannel/fdchannel_unsafe.go
+++ b/pkg/fdchannel/fdchannel_unsafe.go
@@ -20,9 +20,10 @@ package fdchannel
import (
"fmt"
- "reflect"
"syscall"
"unsafe"
+
+ "gvisor.dev/gvisor/pkg/gohacks"
)
// int32 is the real type of a file descriptor.
@@ -53,10 +54,10 @@ func (ep *Endpoint) Init(sockfd int) {
// sendmsg+recvmsg for a zero-length datagram is slightly faster than
// sendmsg+recvmsg for a single byte over a stream socket.
cmsgSlice := make([]byte, syscall.CmsgSpace(sizeofInt32))
- cmsgReflect := (*reflect.SliceHeader)(unsafe.Pointer(&cmsgSlice))
+ cmsgSliceHdr := (*gohacks.SliceHeader)(unsafe.Pointer(&cmsgSlice))
ep.sockfd = int32(sockfd)
- ep.msghdr.Control = (*byte)(unsafe.Pointer(cmsgReflect.Data))
- ep.cmsg = (*syscall.Cmsghdr)(unsafe.Pointer(cmsgReflect.Data))
+ ep.msghdr.Control = (*byte)(cmsgSliceHdr.Data)
+ ep.cmsg = (*syscall.Cmsghdr)(cmsgSliceHdr.Data)
// ep.msghdr.Controllen and ep.cmsg.* are mutated by recvmsg(2), so they're
// set before calling sendmsg/recvmsg.
}
diff --git a/pkg/flipcall/flipcall_unsafe.go b/pkg/flipcall/flipcall_unsafe.go
index 580bf23a4..613ed8943 100644
--- a/pkg/flipcall/flipcall_unsafe.go
+++ b/pkg/flipcall/flipcall_unsafe.go
@@ -61,13 +61,12 @@ func (ep *Endpoint) dataLen() *uint32 {
// - Writers must not assume that they will read back the same data that they
// have written. In other words, writers should avoid reading from Data() at
// all.
-func (ep *Endpoint) Data() []byte {
- var bs []byte
- bsReflect := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
- bsReflect.Data = ep.packet + PacketHeaderBytes
- bsReflect.Len = int(ep.dataCap)
- bsReflect.Cap = int(ep.dataCap)
- return bs
+func (ep *Endpoint) Data() (bs []byte) {
+ bshdr := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
+ bshdr.Data = ep.packet + PacketHeaderBytes
+ bshdr.Len = int(ep.dataCap)
+ bshdr.Cap = int(ep.dataCap)
+ return
}
// ioSync is a dummy variable used to indicate synchronization to the Go race
diff --git a/pkg/gohacks/gohacks_unsafe.go b/pkg/gohacks/gohacks_unsafe.go
index aad675172..d26c1ac05 100644
--- a/pkg/gohacks/gohacks_unsafe.go
+++ b/pkg/gohacks/gohacks_unsafe.go
@@ -12,14 +12,35 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+// +build go1.13
+// +build !go1.17
+
+// Check type signatures when updating Go version.
+
// Package gohacks contains utilities for subverting the Go compiler.
package gohacks
import (
- "reflect"
"unsafe"
)
+// SliceHeader is equivalent to reflect.SliceHeader, but represents the pointer
+// to the underlying array as unsafe.Pointer rather than uintptr, allowing
+// SliceHeaders to be directly converted to slice objects.
+type SliceHeader struct {
+ Data unsafe.Pointer
+ Len int
+ Cap int
+}
+
+// StringHeader is equivalent to reflect.StringHeader, but represents the
+// pointer to the underlying array as unsafe.Pointer rather than uintptr,
+// allowing StringHeaders to be directly converted to strings.
+type StringHeader struct {
+ Data unsafe.Pointer
+ Len int
+}
+
// Noescape hides a pointer from escape analysis. Noescape is the identity
// function but escape analysis doesn't think the output depends on the input.
// Noescape is inlined and currently compiles down to zero instructions.
@@ -36,22 +57,21 @@ func Noescape(p unsafe.Pointer) unsafe.Pointer {
// ImmutableBytesFromString is equivalent to []byte(s), except that it uses the
// same memory backing s instead of making a heap-allocated copy. This is only
// valid if the returned slice is never mutated.
-func ImmutableBytesFromString(s string) []byte {
- shdr := (*reflect.StringHeader)(unsafe.Pointer(&s))
- var bs []byte
- bshdr := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
+func ImmutableBytesFromString(s string) (bs []byte) {
+ shdr := (*StringHeader)(unsafe.Pointer(&s))
+ bshdr := (*SliceHeader)(unsafe.Pointer(&bs))
bshdr.Data = shdr.Data
bshdr.Len = shdr.Len
bshdr.Cap = shdr.Len
- return bs
+ return
}
// StringFromImmutableBytes is equivalent to string(bs), except that it uses
// the same memory backing bs instead of making a heap-allocated copy. This is
// only valid if bs is never mutated after StringFromImmutableBytes returns.
func StringFromImmutableBytes(bs []byte) string {
- // This is cheaper than messing with reflect.StringHeader and
- // reflect.SliceHeader, which as of this writing produces many dead stores
- // of zeroes. Compare strings.Builder.String().
+ // This is cheaper than messing with StringHeader and SliceHeader, which as
+ // of this writing produces many dead stores of zeroes. Compare
+ // strings.Builder.String().
return *(*string)(unsafe.Pointer(&bs))
}
diff --git a/pkg/safemem/block_unsafe.go b/pkg/safemem/block_unsafe.go
index 7857f5853..93879bb4f 100644
--- a/pkg/safemem/block_unsafe.go
+++ b/pkg/safemem/block_unsafe.go
@@ -16,9 +16,9 @@ package safemem
import (
"fmt"
- "reflect"
"unsafe"
+ "gvisor.dev/gvisor/pkg/gohacks"
"gvisor.dev/gvisor/pkg/safecopy"
)
@@ -148,12 +148,11 @@ func (b Block) TakeFirst64(n uint64) Block {
// ToSlice returns a []byte equivalent to b.
func (b Block) ToSlice() []byte {
- var bs []byte
- hdr := (*reflect.SliceHeader)(unsafe.Pointer(&bs))
- hdr.Data = uintptr(b.start)
- hdr.Len = b.length
- hdr.Cap = b.length
- return bs
+ return *(*[]byte)(unsafe.Pointer(&gohacks.SliceHeader{
+ Data: b.start,
+ Len: b.length,
+ Cap: b.length,
+ }))
}
// Addr returns b's start address as a uintptr. It returns uintptr instead of
diff --git a/pkg/safemem/seq_unsafe.go b/pkg/safemem/seq_unsafe.go
index fc4049eeb..b315b0e5a 100644
--- a/pkg/safemem/seq_unsafe.go
+++ b/pkg/safemem/seq_unsafe.go
@@ -17,9 +17,10 @@ package safemem
import (
"bytes"
"fmt"
- "reflect"
"syscall"
"unsafe"
+
+ "gvisor.dev/gvisor/pkg/gohacks"
)
// A BlockSeq represents a sequence of Blocks, each of which has non-zero
@@ -184,8 +185,8 @@ func (bs BlockSeq) Tail() BlockSeq {
return BlockSeq{}
}
var extSlice []Block
- extSliceHdr := (*reflect.SliceHeader)(unsafe.Pointer(&extSlice))
- extSliceHdr.Data = uintptr(bs.data)
+ extSliceHdr := (*gohacks.SliceHeader)(unsafe.Pointer(&extSlice))
+ extSliceHdr.Data = bs.data
extSliceHdr.Len = bs.length
extSliceHdr.Cap = bs.length
tailSlice := skipEmpty(extSlice[1:])
diff --git a/pkg/sentry/arch/stack_unsafe.go b/pkg/sentry/arch/stack_unsafe.go
index a90d297ee..0e478e434 100644
--- a/pkg/sentry/arch/stack_unsafe.go
+++ b/pkg/sentry/arch/stack_unsafe.go
@@ -15,8 +15,6 @@
package arch
import (
- "reflect"
- "runtime"
"unsafe"
"gvisor.dev/gvisor/pkg/marshal/primitive"
@@ -33,35 +31,22 @@ import (
// On error, the contents of the stack and the bottom cursor are undefined.
func (s *Stack) pushAddrSliceAndTerminator(src []usermem.Addr) (int, error) {
// Note: Stack grows upwards, so push the terminator first.
- srcHdr := (*reflect.SliceHeader)(unsafe.Pointer(&src))
switch s.Arch.Width() {
case 8:
nNull, err := primitive.CopyUint64Out(s, StackBottomMagic, 0)
if err != nil {
return 0, err
}
- var dst []uint64
- dstHdr := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
- dstHdr.Data = srcHdr.Data
- dstHdr.Len = srcHdr.Len
- dstHdr.Cap = srcHdr.Cap
- n, err := primitive.CopyUint64SliceOut(s, StackBottomMagic, dst)
- // Ensures src doesn't get GCed until we're done using it through dst.
- runtime.KeepAlive(src)
+ srcAsUint64 := *(*[]uint64)(unsafe.Pointer(&src))
+ n, err := primitive.CopyUint64SliceOut(s, StackBottomMagic, srcAsUint64)
return n + nNull, err
case 4:
nNull, err := primitive.CopyUint32Out(s, StackBottomMagic, 0)
if err != nil {
return 0, err
}
- var dst []uint32
- dstHdr := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
- dstHdr.Data = srcHdr.Data
- dstHdr.Len = srcHdr.Len
- dstHdr.Cap = srcHdr.Cap
- n, err := primitive.CopyUint32SliceOut(s, StackBottomMagic, dst)
- // Ensure src doesn't get GCed until we're done using it through dst.
- runtime.KeepAlive(src)
+ srcAsUint32 := *(*[]uint32)(unsafe.Pointer(&src))
+ n, err := primitive.CopyUint32SliceOut(s, StackBottomMagic, srcAsUint32)
return n + nNull, err
default:
panic("Unsupported arch width")
diff --git a/pkg/sentry/vfs/mount_unsafe.go b/pkg/sentry/vfs/mount_unsafe.go
index 0df023713..c7a78d8f8 100644
--- a/pkg/sentry/vfs/mount_unsafe.go
+++ b/pkg/sentry/vfs/mount_unsafe.go
@@ -17,7 +17,6 @@ package vfs
import (
"fmt"
"math/bits"
- "reflect"
"sync/atomic"
"unsafe"
@@ -153,8 +152,8 @@ func (mt *mountTable) Init() {
func newMountTableSlots(cap uintptr) unsafe.Pointer {
slice := make([]mountSlot, cap, cap)
- hdr := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
- return unsafe.Pointer(hdr.Data)
+ hdr := (*gohacks.SliceHeader)(unsafe.Pointer(&slice))
+ return hdr.Data
}
// Lookup returns the Mount with the given parent, mounted at the given point.
diff --git a/pkg/usermem/addr_range_seq_unsafe.go b/pkg/usermem/addr_range_seq_unsafe.go
index 495896ded..c9a1415a0 100644
--- a/pkg/usermem/addr_range_seq_unsafe.go
+++ b/pkg/usermem/addr_range_seq_unsafe.go
@@ -17,8 +17,9 @@ package usermem
import (
"bytes"
"fmt"
- "reflect"
"unsafe"
+
+ "gvisor.dev/gvisor/pkg/gohacks"
)
// An AddrRangeSeq represents a sequence of AddrRanges.
@@ -163,8 +164,8 @@ func (ars AddrRangeSeq) externalTail() AddrRangeSeq {
tailLimit = int64(ars.limit - headLen)
}
var extSlice []AddrRange
- extSliceHdr := (*reflect.SliceHeader)(unsafe.Pointer(&extSlice))
- extSliceHdr.Data = uintptr(ars.data)
+ extSliceHdr := (*gohacks.SliceHeader)(unsafe.Pointer(&extSlice))
+ extSliceHdr.Data = ars.data
extSliceHdr.Len = ars.length
extSliceHdr.Cap = ars.length
return addrRangeSeqFromSliceLimited(extSlice[1:], tailLimit)