diff options
author | Rahat Mahmood <rahat@google.com> | 2020-09-29 18:06:19 -0700 |
---|---|---|
committer | gVisor bot <gvisor-bot@google.com> | 2020-09-29 18:08:07 -0700 |
commit | 387501219e87701a6adeb8417542927ee39b9950 (patch) | |
tree | fdde7ebd390f3ba44067a84cc0875158469b4c25 /pkg/sentry/arch/stack_unsafe.go | |
parent | fee2c0772811d1c6de5fc9d3a754108994f4c4ab (diff) |
Replace remaining uses of reflection-based marshalling.
- Rewrite arch.Stack.{Push,Pop}. For the most part, stack now
implements marshal.CopyContext and can be used as the target of
marshal operations. Stack.Push had some extra logic for
automatically null-terminating slices. This was only used for two
specific types of slices, and is now handled explicitly.
- Delete usermem.CopyObject{In,Out}.
- Replace most remaining uses of the encoding/binary package with
go-marshal. Most of these were using the binary package to compute
the size of a struct, which go-marshal can directly replace. ~3 uses
of the binary package remain. These aren't reasonably replaceable by
go-marshal: for example one use is to construct the syscall
trampoline for systrap.
- Fill out remaining convenience wrappers in the primitive package.
PiperOrigin-RevId: 334502375
Diffstat (limited to 'pkg/sentry/arch/stack_unsafe.go')
-rw-r--r-- | pkg/sentry/arch/stack_unsafe.go | 69 |
1 files changed, 69 insertions, 0 deletions
diff --git a/pkg/sentry/arch/stack_unsafe.go b/pkg/sentry/arch/stack_unsafe.go new file mode 100644 index 000000000..a90d297ee --- /dev/null +++ b/pkg/sentry/arch/stack_unsafe.go @@ -0,0 +1,69 @@ +// Copyright 2020 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 arch + +import ( + "reflect" + "runtime" + "unsafe" + + "gvisor.dev/gvisor/pkg/marshal/primitive" + "gvisor.dev/gvisor/pkg/usermem" +) + +// pushAddrSliceAndTerminator copies a slices of addresses to the stack, and +// also pushes an extra null address element at the end of the slice. +// +// Internally, we unsafely transmute the slice type from the arch-dependent +// []usermem.Addr type, to a slice of fixed-sized ints so that we can pass it to +// go-marshal. +// +// 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) + 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) + return n + nNull, err + default: + panic("Unsupported arch width") + } +} |