mirror of
https://github.com/netbirdio/gvisor.git
synced 2026-05-22 17:12:49 -07:00
Merge branch 'master' into tcp-matchers-submit
This commit is contained in:
@@ -23,7 +23,7 @@ bazel version
|
||||
|
||||
python3 -V
|
||||
|
||||
readonly KYTHE_VERSION='v0.0.39'
|
||||
readonly KYTHE_VERSION='v0.0.41'
|
||||
readonly WORKDIR="$(mktemp -d)"
|
||||
readonly KYTHE_DIR="${WORKDIR}/kythe-${KYTHE_VERSION}"
|
||||
if [[ -n "$KOKORO_GIT_COMMIT" ]]; then
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
build_file: "repo/scripts/packetdrill_tests.sh"
|
||||
|
||||
action {
|
||||
define_artifacts {
|
||||
regex: "**/sponge_log.xml"
|
||||
regex: "**/sponge_log.log"
|
||||
regex: "**/outputs.zip"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build_file: "github/kokoro/runtime_tests/runtime_tests.sh"
|
||||
|
||||
env_vars {
|
||||
key: "RUNTIME_TEST_NAME"
|
||||
value: "go1.12"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build_file: "github/kokoro/runtime_tests/runtime_tests.sh"
|
||||
|
||||
env_vars {
|
||||
key: "RUNTIME_TEST_NAME"
|
||||
value: "java11"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build_file: "github/kokoro/runtime_tests/runtime_tests.sh"
|
||||
|
||||
env_vars {
|
||||
key: "RUNTIME_TEST_NAME"
|
||||
value: "nodejs12.4.0"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build_file: "github/kokoro/runtime_tests/runtime_tests.sh"
|
||||
|
||||
env_vars {
|
||||
key: "RUNTIME_TEST_NAME"
|
||||
value: "php7.3.6"
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
build_file: "github/kokoro/runtime_tests/runtime_tests.sh"
|
||||
|
||||
env_vars {
|
||||
key: "RUNTIME_TEST_NAME"
|
||||
value: "python3.7.3"
|
||||
}
|
||||
@@ -138,10 +138,14 @@ func TestSwapUint32Success(t *testing.T) {
|
||||
func TestSwapUint32AlignmentError(t *testing.T) {
|
||||
// Test that SwapUint32 returns an AlignmentError when passed an unaligned
|
||||
// address.
|
||||
data := new(struct{ val uint64 })
|
||||
addr := uintptr(unsafe.Pointer(&data.val)) + 1
|
||||
want := AlignmentError{Addr: addr, Alignment: 4}
|
||||
if _, err := SwapUint32(unsafe.Pointer(addr), 1); err != want {
|
||||
data := make([]byte, 8) // 2 * sizeof(uint32).
|
||||
alignedIndex := uintptr(0)
|
||||
if offset := uintptr(unsafe.Pointer(&data[0])) % 4; offset != 0 {
|
||||
alignedIndex = 4 - offset
|
||||
}
|
||||
ptr := unsafe.Pointer(&data[alignedIndex+1])
|
||||
want := AlignmentError{Addr: uintptr(ptr), Alignment: 4}
|
||||
if _, err := SwapUint32(ptr, 1); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
@@ -171,10 +175,14 @@ func TestSwapUint64Success(t *testing.T) {
|
||||
func TestSwapUint64AlignmentError(t *testing.T) {
|
||||
// Test that SwapUint64 returns an AlignmentError when passed an unaligned
|
||||
// address.
|
||||
data := new(struct{ val1, val2 uint64 })
|
||||
addr := uintptr(unsafe.Pointer(&data.val1)) + 1
|
||||
want := AlignmentError{Addr: addr, Alignment: 8}
|
||||
if _, err := SwapUint64(unsafe.Pointer(addr), 1); err != want {
|
||||
data := make([]byte, 16) // 2 * sizeof(uint64).
|
||||
alignedIndex := uintptr(0)
|
||||
if offset := uintptr(unsafe.Pointer(&data[0])) % 8; offset != 0 {
|
||||
alignedIndex = 8 - offset
|
||||
}
|
||||
ptr := unsafe.Pointer(&data[alignedIndex+1])
|
||||
want := AlignmentError{Addr: uintptr(ptr), Alignment: 8}
|
||||
if _, err := SwapUint64(ptr, 1); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
@@ -201,10 +209,14 @@ func TestCompareAndSwapUint32Success(t *testing.T) {
|
||||
func TestCompareAndSwapUint32AlignmentError(t *testing.T) {
|
||||
// Test that CompareAndSwapUint32 returns an AlignmentError when passed an
|
||||
// unaligned address.
|
||||
data := new(struct{ val uint64 })
|
||||
addr := uintptr(unsafe.Pointer(&data.val)) + 1
|
||||
want := AlignmentError{Addr: addr, Alignment: 4}
|
||||
if _, err := CompareAndSwapUint32(unsafe.Pointer(addr), 0, 1); err != want {
|
||||
data := make([]byte, 8) // 2 * sizeof(uint32).
|
||||
alignedIndex := uintptr(0)
|
||||
if offset := uintptr(unsafe.Pointer(&data[0])) % 4; offset != 0 {
|
||||
alignedIndex = 4 - offset
|
||||
}
|
||||
ptr := unsafe.Pointer(&data[alignedIndex+1])
|
||||
want := AlignmentError{Addr: uintptr(ptr), Alignment: 4}
|
||||
if _, err := CompareAndSwapUint32(ptr, 0, 1); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
}
|
||||
}
|
||||
@@ -252,8 +264,8 @@ func TestCopyInSegvError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGSEGV", bytesBeforeFault), func(t *testing.T) {
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
src := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
src := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
dst := randBuf(pageSize)
|
||||
n, err := CopyIn(dst, src)
|
||||
if n != bytesBeforeFault {
|
||||
@@ -276,8 +288,8 @@ func TestCopyInBusError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGBUS", bytesBeforeFault), func(t *testing.T) {
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
src := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
src := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
dst := randBuf(pageSize)
|
||||
n, err := CopyIn(dst, src)
|
||||
if n != bytesBeforeFault {
|
||||
@@ -300,8 +312,8 @@ func TestCopyOutSegvError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGSEGV", bytesBeforeFault), func(t *testing.T) {
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
dst := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
dst := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
src := randBuf(pageSize)
|
||||
n, err := CopyOut(dst, src)
|
||||
if n != bytesBeforeFault {
|
||||
@@ -324,8 +336,8 @@ func TestCopyOutBusError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGSEGV", bytesBeforeFault), func(t *testing.T) {
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
dst := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
dst := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
src := randBuf(pageSize)
|
||||
n, err := CopyOut(dst, src)
|
||||
if n != bytesBeforeFault {
|
||||
@@ -348,8 +360,8 @@ func TestCopySourceSegvError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGSEGV", bytesBeforeFault), func(t *testing.T) {
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
src := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
src := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
dst := randBuf(pageSize)
|
||||
n, err := Copy(unsafe.Pointer(&dst[0]), src, pageSize)
|
||||
if n != uintptr(bytesBeforeFault) {
|
||||
@@ -372,8 +384,8 @@ func TestCopySourceBusError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGBUS", bytesBeforeFault), func(t *testing.T) {
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
src := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
src := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
dst := randBuf(pageSize)
|
||||
n, err := Copy(unsafe.Pointer(&dst[0]), src, pageSize)
|
||||
if n != uintptr(bytesBeforeFault) {
|
||||
@@ -396,8 +408,8 @@ func TestCopyDestinationSegvError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGSEGV", bytesBeforeFault), func(t *testing.T) {
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
dst := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
dst := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
src := randBuf(pageSize)
|
||||
n, err := Copy(dst, unsafe.Pointer(&src[0]), pageSize)
|
||||
if n != uintptr(bytesBeforeFault) {
|
||||
@@ -420,8 +432,8 @@ func TestCopyDestinationBusError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting copy %d bytes before SIGBUS", bytesBeforeFault), func(t *testing.T) {
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
dst := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
dst := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
src := randBuf(pageSize)
|
||||
n, err := Copy(dst, unsafe.Pointer(&src[0]), pageSize)
|
||||
if n != uintptr(bytesBeforeFault) {
|
||||
@@ -444,8 +456,8 @@ func TestZeroOutSegvError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting write %d bytes before SIGSEGV", bytesBeforeFault), func(t *testing.T) {
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
dst := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
dst := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
n, err := ZeroOut(dst, pageSize)
|
||||
if n != uintptr(bytesBeforeFault) {
|
||||
t.Errorf("Unexpected write length: got %v, want %v", n, bytesBeforeFault)
|
||||
@@ -467,8 +479,8 @@ func TestZeroOutBusError(t *testing.T) {
|
||||
for bytesBeforeFault := 0; bytesBeforeFault <= 2*maxRegisterSize; bytesBeforeFault++ {
|
||||
t.Run(fmt.Sprintf("starting write %d bytes before SIGBUS", bytesBeforeFault), func(t *testing.T) {
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
dst := unsafe.Pointer(secondPage - uintptr(bytesBeforeFault))
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
dst := unsafe.Pointer(&mapping[pageSize-bytesBeforeFault])
|
||||
n, err := ZeroOut(dst, pageSize)
|
||||
if n != uintptr(bytesBeforeFault) {
|
||||
t.Errorf("Unexpected write length: got %v, want %v", n, bytesBeforeFault)
|
||||
@@ -488,7 +500,7 @@ func TestSwapUint32SegvError(t *testing.T) {
|
||||
// Test that SwapUint32 returns a SegvError when reaching a page that
|
||||
// signals SIGSEGV.
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
_, err := SwapUint32(unsafe.Pointer(secondPage), 1)
|
||||
if want := (SegvError{secondPage}); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
@@ -500,7 +512,7 @@ func TestSwapUint32BusError(t *testing.T) {
|
||||
// Test that SwapUint32 returns a BusError when reaching a page that
|
||||
// signals SIGBUS.
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
_, err := SwapUint32(unsafe.Pointer(secondPage), 1)
|
||||
if want := (BusError{secondPage}); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
@@ -512,7 +524,7 @@ func TestSwapUint64SegvError(t *testing.T) {
|
||||
// Test that SwapUint64 returns a SegvError when reaching a page that
|
||||
// signals SIGSEGV.
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
_, err := SwapUint64(unsafe.Pointer(secondPage), 1)
|
||||
if want := (SegvError{secondPage}); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
@@ -524,7 +536,7 @@ func TestSwapUint64BusError(t *testing.T) {
|
||||
// Test that SwapUint64 returns a BusError when reaching a page that
|
||||
// signals SIGBUS.
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
_, err := SwapUint64(unsafe.Pointer(secondPage), 1)
|
||||
if want := (BusError{secondPage}); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
@@ -536,7 +548,7 @@ func TestCompareAndSwapUint32SegvError(t *testing.T) {
|
||||
// Test that CompareAndSwapUint32 returns a SegvError when reaching a page
|
||||
// that signals SIGSEGV.
|
||||
withSegvErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
_, err := CompareAndSwapUint32(unsafe.Pointer(secondPage), 0, 1)
|
||||
if want := (SegvError{secondPage}); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
@@ -548,7 +560,7 @@ func TestCompareAndSwapUint32BusError(t *testing.T) {
|
||||
// Test that CompareAndSwapUint32 returns a BusError when reaching a page
|
||||
// that signals SIGBUS.
|
||||
withBusErrorTestMapping(t, func(mapping []byte) {
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[0])) + pageSize
|
||||
secondPage := uintptr(unsafe.Pointer(&mapping[pageSize]))
|
||||
_, err := CompareAndSwapUint32(unsafe.Pointer(secondPage), 0, 1)
|
||||
if want := (BusError{secondPage}); err != want {
|
||||
t.Errorf("Unexpected error: got %v, want %v", err, want)
|
||||
|
||||
@@ -16,6 +16,7 @@ package safecopy
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
@@ -35,7 +36,7 @@ const maxRegisterSize = 16
|
||||
// successfully copied.
|
||||
//
|
||||
//go:noescape
|
||||
func memcpy(dst, src unsafe.Pointer, n uintptr) (fault unsafe.Pointer, sig int32)
|
||||
func memcpy(dst, src uintptr, n uintptr) (fault uintptr, sig int32)
|
||||
|
||||
// memclr sets the n bytes following ptr to zeroes. If a SIGSEGV or SIGBUS
|
||||
// signal is received during the write, it returns the address that caused the
|
||||
@@ -47,7 +48,7 @@ func memcpy(dst, src unsafe.Pointer, n uintptr) (fault unsafe.Pointer, sig int32
|
||||
// successfully written.
|
||||
//
|
||||
//go:noescape
|
||||
func memclr(ptr unsafe.Pointer, n uintptr) (fault unsafe.Pointer, sig int32)
|
||||
func memclr(ptr uintptr, n uintptr) (fault uintptr, sig int32)
|
||||
|
||||
// swapUint32 atomically stores new into *ptr and returns (the previous *ptr
|
||||
// value, 0). If a SIGSEGV or SIGBUS signal is received during the swap, the
|
||||
@@ -90,29 +91,35 @@ func loadUint32(ptr unsafe.Pointer) (val uint32, sig int32)
|
||||
// CopyIn copies len(dst) bytes from src to dst. It returns the number of bytes
|
||||
// copied and an error if SIGSEGV or SIGBUS is received while reading from src.
|
||||
func CopyIn(dst []byte, src unsafe.Pointer) (int, error) {
|
||||
n, err := copyIn(dst, uintptr(src))
|
||||
runtime.KeepAlive(src)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// copyIn is the underlying definition for CopyIn.
|
||||
func copyIn(dst []byte, src uintptr) (int, error) {
|
||||
toCopy := uintptr(len(dst))
|
||||
if len(dst) == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
fault, sig := memcpy(unsafe.Pointer(&dst[0]), src, toCopy)
|
||||
fault, sig := memcpy(uintptr(unsafe.Pointer(&dst[0])), src, toCopy)
|
||||
if sig == 0 {
|
||||
return len(dst), nil
|
||||
}
|
||||
|
||||
faultN, srcN := uintptr(fault), uintptr(src)
|
||||
if faultN < srcN || faultN >= srcN+toCopy {
|
||||
panic(fmt.Sprintf("CopyIn raised signal %d at %#x, which is outside source [%#x, %#x)", sig, faultN, srcN, srcN+toCopy))
|
||||
if fault < src || fault >= src+toCopy {
|
||||
panic(fmt.Sprintf("CopyIn raised signal %d at %#x, which is outside source [%#x, %#x)", sig, fault, src, src+toCopy))
|
||||
}
|
||||
|
||||
// memcpy might have ended the copy up to maxRegisterSize bytes before
|
||||
// fault, if an instruction caused a memory access that straddled two
|
||||
// pages, and the second one faulted. Try to copy up to the fault.
|
||||
var done int
|
||||
if faultN-srcN > maxRegisterSize {
|
||||
done = int(faultN - srcN - maxRegisterSize)
|
||||
if fault-src > maxRegisterSize {
|
||||
done = int(fault - src - maxRegisterSize)
|
||||
}
|
||||
n, err := CopyIn(dst[done:int(faultN-srcN)], unsafe.Pointer(srcN+uintptr(done)))
|
||||
n, err := copyIn(dst[done:int(fault-src)], src+uintptr(done))
|
||||
done += n
|
||||
if err != nil {
|
||||
return done, err
|
||||
@@ -124,29 +131,35 @@ func CopyIn(dst []byte, src unsafe.Pointer) (int, error) {
|
||||
// bytes done and an error if SIGSEGV or SIGBUS is received while writing to
|
||||
// dst.
|
||||
func CopyOut(dst unsafe.Pointer, src []byte) (int, error) {
|
||||
n, err := copyOut(uintptr(dst), src)
|
||||
runtime.KeepAlive(dst)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// copyOut is the underlying definition for CopyOut.
|
||||
func copyOut(dst uintptr, src []byte) (int, error) {
|
||||
toCopy := uintptr(len(src))
|
||||
if toCopy == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
fault, sig := memcpy(dst, unsafe.Pointer(&src[0]), toCopy)
|
||||
fault, sig := memcpy(dst, uintptr(unsafe.Pointer(&src[0])), toCopy)
|
||||
if sig == 0 {
|
||||
return len(src), nil
|
||||
}
|
||||
|
||||
faultN, dstN := uintptr(fault), uintptr(dst)
|
||||
if faultN < dstN || faultN >= dstN+toCopy {
|
||||
panic(fmt.Sprintf("CopyOut raised signal %d at %#x, which is outside destination [%#x, %#x)", sig, faultN, dstN, dstN+toCopy))
|
||||
if fault < dst || fault >= dst+toCopy {
|
||||
panic(fmt.Sprintf("CopyOut raised signal %d at %#x, which is outside destination [%#x, %#x)", sig, fault, dst, dst+toCopy))
|
||||
}
|
||||
|
||||
// memcpy might have ended the copy up to maxRegisterSize bytes before
|
||||
// fault, if an instruction caused a memory access that straddled two
|
||||
// pages, and the second one faulted. Try to copy up to the fault.
|
||||
var done int
|
||||
if faultN-dstN > maxRegisterSize {
|
||||
done = int(faultN - dstN - maxRegisterSize)
|
||||
if fault-dst > maxRegisterSize {
|
||||
done = int(fault - dst - maxRegisterSize)
|
||||
}
|
||||
n, err := CopyOut(unsafe.Pointer(dstN+uintptr(done)), src[done:int(faultN-dstN)])
|
||||
n, err := copyOut(dst+uintptr(done), src[done:int(fault-dst)])
|
||||
done += n
|
||||
if err != nil {
|
||||
return done, err
|
||||
@@ -161,6 +174,14 @@ func CopyOut(dst unsafe.Pointer, src []byte) (int, error) {
|
||||
// Data is copied in order; if [src, src+toCopy) and [dst, dst+toCopy) overlap,
|
||||
// the resulting contents of dst are unspecified.
|
||||
func Copy(dst, src unsafe.Pointer, toCopy uintptr) (uintptr, error) {
|
||||
n, err := copyN(uintptr(dst), uintptr(src), toCopy)
|
||||
runtime.KeepAlive(dst)
|
||||
runtime.KeepAlive(src)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// copyN is the underlying definition for Copy.
|
||||
func copyN(dst, src uintptr, toCopy uintptr) (uintptr, error) {
|
||||
if toCopy == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -171,17 +192,16 @@ func Copy(dst, src unsafe.Pointer, toCopy uintptr) (uintptr, error) {
|
||||
}
|
||||
|
||||
// Did the fault occur while reading from src or writing to dst?
|
||||
faultN, srcN, dstN := uintptr(fault), uintptr(src), uintptr(dst)
|
||||
faultAfterSrc := ^uintptr(0)
|
||||
if faultN >= srcN {
|
||||
faultAfterSrc = faultN - srcN
|
||||
if fault >= src {
|
||||
faultAfterSrc = fault - src
|
||||
}
|
||||
faultAfterDst := ^uintptr(0)
|
||||
if faultN >= dstN {
|
||||
faultAfterDst = faultN - dstN
|
||||
if fault >= dst {
|
||||
faultAfterDst = fault - dst
|
||||
}
|
||||
if faultAfterSrc >= toCopy && faultAfterDst >= toCopy {
|
||||
panic(fmt.Sprintf("Copy raised signal %d at %#x, which is outside source [%#x, %#x) and destination [%#x, %#x)", sig, faultN, srcN, srcN+toCopy, dstN, dstN+toCopy))
|
||||
panic(fmt.Sprintf("Copy raised signal %d at %#x, which is outside source [%#x, %#x) and destination [%#x, %#x)", sig, fault, src, src+toCopy, dst, dst+toCopy))
|
||||
}
|
||||
faultedAfter := faultAfterSrc
|
||||
if faultedAfter > faultAfterDst {
|
||||
@@ -195,7 +215,7 @@ func Copy(dst, src unsafe.Pointer, toCopy uintptr) (uintptr, error) {
|
||||
if faultedAfter > maxRegisterSize {
|
||||
done = faultedAfter - maxRegisterSize
|
||||
}
|
||||
n, err := Copy(unsafe.Pointer(dstN+done), unsafe.Pointer(srcN+done), faultedAfter-done)
|
||||
n, err := copyN(dst+done, src+done, faultedAfter-done)
|
||||
done += n
|
||||
if err != nil {
|
||||
return done, err
|
||||
@@ -206,6 +226,13 @@ func Copy(dst, src unsafe.Pointer, toCopy uintptr) (uintptr, error) {
|
||||
// ZeroOut writes toZero zero bytes to dst. It returns the number of bytes
|
||||
// written and an error if SIGSEGV or SIGBUS is received while writing to dst.
|
||||
func ZeroOut(dst unsafe.Pointer, toZero uintptr) (uintptr, error) {
|
||||
n, err := zeroOut(uintptr(dst), toZero)
|
||||
runtime.KeepAlive(dst)
|
||||
return n, err
|
||||
}
|
||||
|
||||
// zeroOut is the underlying definition for ZeroOut.
|
||||
func zeroOut(dst uintptr, toZero uintptr) (uintptr, error) {
|
||||
if toZero == 0 {
|
||||
return 0, nil
|
||||
}
|
||||
@@ -215,19 +242,18 @@ func ZeroOut(dst unsafe.Pointer, toZero uintptr) (uintptr, error) {
|
||||
return toZero, nil
|
||||
}
|
||||
|
||||
faultN, dstN := uintptr(fault), uintptr(dst)
|
||||
if faultN < dstN || faultN >= dstN+toZero {
|
||||
panic(fmt.Sprintf("ZeroOut raised signal %d at %#x, which is outside destination [%#x, %#x)", sig, faultN, dstN, dstN+toZero))
|
||||
if fault < dst || fault >= dst+toZero {
|
||||
panic(fmt.Sprintf("ZeroOut raised signal %d at %#x, which is outside destination [%#x, %#x)", sig, fault, dst, dst+toZero))
|
||||
}
|
||||
|
||||
// memclr might have ended the write up to maxRegisterSize bytes before
|
||||
// fault, if an instruction caused a memory access that straddled two
|
||||
// pages, and the second one faulted. Try to write up to the fault.
|
||||
var done uintptr
|
||||
if faultN-dstN > maxRegisterSize {
|
||||
done = faultN - dstN - maxRegisterSize
|
||||
if fault-dst > maxRegisterSize {
|
||||
done = fault - dst - maxRegisterSize
|
||||
}
|
||||
n, err := ZeroOut(unsafe.Pointer(dstN+done), faultN-dstN-done)
|
||||
n, err := zeroOut(dst+done, fault-dst-done)
|
||||
done += n
|
||||
if err != nil {
|
||||
return done, err
|
||||
@@ -243,7 +269,7 @@ func SwapUint32(ptr unsafe.Pointer, new uint32) (uint32, error) {
|
||||
return 0, AlignmentError{addr, 4}
|
||||
}
|
||||
old, sig := swapUint32(ptr, new)
|
||||
return old, errorFromFaultSignal(ptr, sig)
|
||||
return old, errorFromFaultSignal(uintptr(ptr), sig)
|
||||
}
|
||||
|
||||
// SwapUint64 is equivalent to sync/atomic.SwapUint64, except that it returns
|
||||
@@ -254,7 +280,7 @@ func SwapUint64(ptr unsafe.Pointer, new uint64) (uint64, error) {
|
||||
return 0, AlignmentError{addr, 8}
|
||||
}
|
||||
old, sig := swapUint64(ptr, new)
|
||||
return old, errorFromFaultSignal(ptr, sig)
|
||||
return old, errorFromFaultSignal(uintptr(ptr), sig)
|
||||
}
|
||||
|
||||
// CompareAndSwapUint32 is equivalent to atomicbitops.CompareAndSwapUint32,
|
||||
@@ -265,7 +291,7 @@ func CompareAndSwapUint32(ptr unsafe.Pointer, old, new uint32) (uint32, error) {
|
||||
return 0, AlignmentError{addr, 4}
|
||||
}
|
||||
prev, sig := compareAndSwapUint32(ptr, old, new)
|
||||
return prev, errorFromFaultSignal(ptr, sig)
|
||||
return prev, errorFromFaultSignal(uintptr(ptr), sig)
|
||||
}
|
||||
|
||||
// LoadUint32 is like sync/atomic.LoadUint32, but operates with user memory. It
|
||||
@@ -277,17 +303,17 @@ func LoadUint32(ptr unsafe.Pointer) (uint32, error) {
|
||||
return 0, AlignmentError{addr, 4}
|
||||
}
|
||||
val, sig := loadUint32(ptr)
|
||||
return val, errorFromFaultSignal(ptr, sig)
|
||||
return val, errorFromFaultSignal(uintptr(ptr), sig)
|
||||
}
|
||||
|
||||
func errorFromFaultSignal(addr unsafe.Pointer, sig int32) error {
|
||||
func errorFromFaultSignal(addr uintptr, sig int32) error {
|
||||
switch sig {
|
||||
case 0:
|
||||
return nil
|
||||
case int32(syscall.SIGSEGV):
|
||||
return SegvError{uintptr(addr)}
|
||||
return SegvError{addr}
|
||||
case int32(syscall.SIGBUS):
|
||||
return BusError{uintptr(addr)}
|
||||
return BusError{addr}
|
||||
default:
|
||||
panic(fmt.Sprintf("safecopy got unexpected signal %d at address %#x", sig, addr))
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
@@ -297,3 +298,19 @@ func ZeroSeq(dsts BlockSeq) (uint64, error) {
|
||||
}
|
||||
return done, nil
|
||||
}
|
||||
|
||||
// IovecsFromBlockSeq returns a []syscall.Iovec representing seq.
|
||||
func IovecsFromBlockSeq(bs BlockSeq) []syscall.Iovec {
|
||||
iovs := make([]syscall.Iovec, 0, bs.NumBlocks())
|
||||
for ; !bs.IsEmpty(); bs = bs.Tail() {
|
||||
b := bs.Head()
|
||||
iovs = append(iovs, syscall.Iovec{
|
||||
Base: &b.ToSlice()[0],
|
||||
Len: uint64(b.Len()),
|
||||
})
|
||||
// We don't need to care about b.NeedSafecopy(), because the host
|
||||
// kernel will handle such address ranges just fine (by returning
|
||||
// EFAULT).
|
||||
}
|
||||
return iovs
|
||||
}
|
||||
|
||||
+16
-4
@@ -219,24 +219,36 @@ func addSyscallArgsCheck(p *bpf.ProgramBuilder, rules []Rule, action linux.BPFAc
|
||||
switch a := arg.(type) {
|
||||
case AllowAny:
|
||||
case AllowValue:
|
||||
dataOffsetLow := seccompDataOffsetArgLow(i)
|
||||
dataOffsetHigh := seccompDataOffsetArgHigh(i)
|
||||
if i == RuleIP {
|
||||
dataOffsetLow = seccompDataOffsetIPLow
|
||||
dataOffsetHigh = seccompDataOffsetIPHigh
|
||||
}
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
// assert arg_low == low
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, seccompDataOffsetArgLow(i))
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
p.AddJumpFalseLabel(bpf.Jmp|bpf.Jeq|bpf.K, low, 0, ruleViolationLabel(ruleSetIdx, sysno, ruleidx))
|
||||
// assert arg_high == high
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, seccompDataOffsetArgHigh(i))
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
p.AddJumpFalseLabel(bpf.Jmp|bpf.Jeq|bpf.K, high, 0, ruleViolationLabel(ruleSetIdx, sysno, ruleidx))
|
||||
labelled = true
|
||||
case GreaterThan:
|
||||
dataOffsetLow := seccompDataOffsetArgLow(i)
|
||||
dataOffsetHigh := seccompDataOffsetArgHigh(i)
|
||||
if i == RuleIP {
|
||||
dataOffsetLow = seccompDataOffsetIPLow
|
||||
dataOffsetHigh = seccompDataOffsetIPHigh
|
||||
}
|
||||
labelGood := fmt.Sprintf("gt%v", i)
|
||||
high, low := uint32(a>>32), uint32(a)
|
||||
// assert arg_high < high
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, seccompDataOffsetArgHigh(i))
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetHigh)
|
||||
p.AddJumpFalseLabel(bpf.Jmp|bpf.Jge|bpf.K, high, 0, ruleViolationLabel(ruleSetIdx, sysno, ruleidx))
|
||||
// arg_high > high
|
||||
p.AddJumpFalseLabel(bpf.Jmp|bpf.Jeq|bpf.K, high, 0, ruleLabel(ruleSetIdx, sysno, ruleidx, labelGood))
|
||||
// arg_low < low
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, seccompDataOffsetArgLow(i))
|
||||
p.AddStmt(bpf.Ld|bpf.Abs|bpf.W, dataOffsetLow)
|
||||
p.AddJumpFalseLabel(bpf.Jmp|bpf.Jgt|bpf.K, low, 0, ruleViolationLabel(ruleSetIdx, sysno, ruleidx))
|
||||
p.AddLabel(ruleLabel(ruleSetIdx, sysno, ruleidx, labelGood))
|
||||
labelled = true
|
||||
|
||||
@@ -62,7 +62,11 @@ func (a AllowValue) String() (s string) {
|
||||
// rule := Rule {
|
||||
// AllowValue(linux.ARCH_GET_FS | linux.ARCH_SET_FS), // arg0
|
||||
// }
|
||||
type Rule [6]interface{}
|
||||
type Rule [7]interface{} // 6 arguments + RIP
|
||||
|
||||
// RuleIP indicates what rules in the Rule array have to be applied to
|
||||
// instruction pointer.
|
||||
const RuleIP = 6
|
||||
|
||||
func (r Rule) String() (s string) {
|
||||
if len(r) == 0 {
|
||||
|
||||
@@ -388,6 +388,33 @@ func TestBasic(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
ruleSets: []RuleSet{
|
||||
{
|
||||
Rules: SyscallRules{
|
||||
1: []Rule{
|
||||
{
|
||||
RuleIP: AllowValue(0x7aabbccdd),
|
||||
},
|
||||
},
|
||||
},
|
||||
Action: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
},
|
||||
defaultAction: linux.SECCOMP_RET_TRAP,
|
||||
specs: []spec{
|
||||
{
|
||||
desc: "IP: Syscall instruction pointer allowed",
|
||||
data: seccompData{nr: 1, arch: linux.AUDIT_ARCH_X86_64, args: [6]uint64{}, instructionPointer: 0x7aabbccdd},
|
||||
want: linux.SECCOMP_RET_ALLOW,
|
||||
},
|
||||
{
|
||||
desc: "IP: Syscall instruction pointer disallowed",
|
||||
data: seccompData{nr: 1, arch: linux.AUDIT_ARCH_X86_64, args: [6]uint64{}, instructionPointer: 0x711223344},
|
||||
want: linux.SECCOMP_RET_TRAP,
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
instrs, err := BuildProgram(test.ruleSets, test.defaultAction)
|
||||
if err != nil {
|
||||
|
||||
@@ -28,13 +28,13 @@ go_template_instance(
|
||||
"platform": "gvisor.dev/gvisor/pkg/sentry/platform",
|
||||
},
|
||||
package = "fsutil",
|
||||
prefix = "frameRef",
|
||||
prefix = "FrameRef",
|
||||
template = "//pkg/segment:generic_set",
|
||||
types = {
|
||||
"Key": "uint64",
|
||||
"Range": "platform.FileRange",
|
||||
"Value": "uint64",
|
||||
"Functions": "frameRefSetFunctions",
|
||||
"Functions": "FrameRefSetFunctions",
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@@ -20,24 +20,25 @@ import (
|
||||
"gvisor.dev/gvisor/pkg/sentry/platform"
|
||||
)
|
||||
|
||||
type frameRefSetFunctions struct{}
|
||||
// FrameRefSetFunctions implements segment.Functions for FrameRefSet.
|
||||
type FrameRefSetFunctions struct{}
|
||||
|
||||
// MinKey implements segment.Functions.MinKey.
|
||||
func (frameRefSetFunctions) MinKey() uint64 {
|
||||
func (FrameRefSetFunctions) MinKey() uint64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
// MaxKey implements segment.Functions.MaxKey.
|
||||
func (frameRefSetFunctions) MaxKey() uint64 {
|
||||
func (FrameRefSetFunctions) MaxKey() uint64 {
|
||||
return math.MaxUint64
|
||||
}
|
||||
|
||||
// ClearValue implements segment.Functions.ClearValue.
|
||||
func (frameRefSetFunctions) ClearValue(val *uint64) {
|
||||
func (FrameRefSetFunctions) ClearValue(val *uint64) {
|
||||
}
|
||||
|
||||
// Merge implements segment.Functions.Merge.
|
||||
func (frameRefSetFunctions) Merge(_ platform.FileRange, val1 uint64, _ platform.FileRange, val2 uint64) (uint64, bool) {
|
||||
func (FrameRefSetFunctions) Merge(_ platform.FileRange, val1 uint64, _ platform.FileRange, val2 uint64) (uint64, bool) {
|
||||
if val1 != val2 {
|
||||
return 0, false
|
||||
}
|
||||
@@ -45,6 +46,6 @@ func (frameRefSetFunctions) Merge(_ platform.FileRange, val1 uint64, _ platform.
|
||||
}
|
||||
|
||||
// Split implements segment.Functions.Split.
|
||||
func (frameRefSetFunctions) Split(_ platform.FileRange, val uint64, _ uint64) (uint64, uint64) {
|
||||
func (FrameRefSetFunctions) Split(_ platform.FileRange, val uint64, _ uint64) (uint64, uint64) {
|
||||
return val, val
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ type CachingInodeOperations struct {
|
||||
// refs tracks active references to data in the cache.
|
||||
//
|
||||
// refs is protected by dataMu.
|
||||
refs frameRefSet
|
||||
refs FrameRefSet
|
||||
}
|
||||
|
||||
// CachingInodeOperationsOptions configures a CachingInodeOperations.
|
||||
|
||||
@@ -112,11 +112,11 @@ attempts to queue a new event, it is already holding `fs.Watches.mu`. If we used
|
||||
`Inotify.mu` to also protect the event queue, this would violate the above lock
|
||||
ordering.
|
||||
|
||||
[dirent]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/fs/dirent.go
|
||||
[event]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/fs/inotify_event.go
|
||||
[fd_table]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/kernel/fd_table.go
|
||||
[inode]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/fs/inode.go
|
||||
[inode_watches]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/fs/inode_inotify.go
|
||||
[inotify]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/fs/inotify.go
|
||||
[syscall_dir]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/syscalls/linux/
|
||||
[watch]: https://github.com/google/gvisor/blob/master/+/master/pkg/sentry/fs/inotify_watch.go
|
||||
[dirent]: https://github.com/google/gvisor/blob/master/pkg/sentry/fs/dirent.go
|
||||
[event]: https://github.com/google/gvisor/blob/master/pkg/sentry/fs/inotify_event.go
|
||||
[fd_table]: https://github.com/google/gvisor/blob/master/pkg/sentry/kernel/fd_table.go
|
||||
[inode]: https://github.com/google/gvisor/blob/master/pkg/sentry/fs/inode.go
|
||||
[inode_watches]: https://github.com/google/gvisor/blob/master/pkg/sentry/fs/inode_inotify.go
|
||||
[inotify]: https://github.com/google/gvisor/blob/master/pkg/sentry/fs/inotify.go
|
||||
[syscall_dir]: https://github.com/google/gvisor/blob/master/pkg/sentry/syscalls/linux/
|
||||
[watch]: https://github.com/google/gvisor/blob/master/pkg/sentry/fs/inotify_watch.go
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
"cache_policy.go",
|
||||
"context_file.go",
|
||||
"device.go",
|
||||
"fifo.go",
|
||||
"file.go",
|
||||
"file_state.go",
|
||||
"fs.go",
|
||||
@@ -38,6 +39,7 @@ go_library(
|
||||
"//pkg/sentry/fs/fsutil",
|
||||
"//pkg/sentry/fs/host",
|
||||
"//pkg/sentry/kernel/auth",
|
||||
"//pkg/sentry/kernel/pipe",
|
||||
"//pkg/sentry/kernel/time",
|
||||
"//pkg/sentry/memmap",
|
||||
"//pkg/sentry/socket/unix/transport",
|
||||
|
||||
@@ -127,6 +127,9 @@ func (cp cachePolicy) revalidate(ctx context.Context, name string, parent, child
|
||||
|
||||
childIops, ok := child.InodeOperations.(*inodeOperations)
|
||||
if !ok {
|
||||
if _, ok := child.InodeOperations.(*fifo); ok {
|
||||
return false
|
||||
}
|
||||
panic(fmt.Sprintf("revalidating inode operations of unknown type %T", child.InodeOperations))
|
||||
}
|
||||
parentIops, ok := parent.InodeOperations.(*inodeOperations)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user