diff --git a/pkg/abi/linux/BUILD b/pkg/abi/linux/BUILD index e29655591..2f54d0158 100644 --- a/pkg/abi/linux/BUILD +++ b/pkg/abi/linux/BUILD @@ -56,6 +56,8 @@ go_library( "linux.go", "membarrier.go", "mm.go", + "mm_amd64.go", + "mm_arm64.go", "mqueue.go", "msgqueue.go", "netdevice.go", @@ -99,6 +101,7 @@ go_library( "//pkg/hostarch", "//pkg/marshal", "//pkg/marshal/primitive", + "@org_golang_x_sys//unix:go_default_library", ], ) diff --git a/pkg/abi/linux/mm.go b/pkg/abi/linux/mm.go index 07cc1895e..40a0814a8 100644 --- a/pkg/abi/linux/mm.go +++ b/pkg/abi/linux/mm.go @@ -14,6 +14,12 @@ package linux +import ( + "fmt" + + "golang.org/x/sys/unix" +) + // Protections for mmap(2). const ( PROT_NONE = 0 @@ -128,3 +134,26 @@ const ( MPOL_MF_VALID = MPOL_MF_STRICT | MPOL_MF_MOVE | MPOL_MF_MOVE_ALL ) + +// TaskSize is the address space size. +var TaskSize = func() uintptr { + pageSize := uintptr(unix.Getpagesize()) + for _, s := range feasibleTaskSizes { + // mmap returns ENOMEM if addr is greater than TASK_SIZE, + // otherwise it returns EINVAL, because addr isn't aligned to + // the page size. + _, _, errno := unix.RawSyscall6( + unix.SYS_MMAP, + s-pageSize-1, + 512, + uintptr(unix.PROT_NONE), + uintptr(unix.MAP_ANONYMOUS|unix.MAP_PRIVATE|unix.MAP_FIXED), 0, 0) + if errno == unix.EINVAL { + return s + } + if errno != unix.ENOMEM { + panic(fmt.Sprintf("mmap returned unexpected error: %d", errno)) + } + } + panic("None of the address space sizes could be successfully mmaped") +}() diff --git a/pkg/abi/linux/mm_amd64.go b/pkg/abi/linux/mm_amd64.go new file mode 100644 index 000000000..e302c7514 --- /dev/null +++ b/pkg/abi/linux/mm_amd64.go @@ -0,0 +1,24 @@ +// 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. + +//go:build amd64 +// +build amd64 + +package linux + +// TASK_SIZE can be one of two values, corresponding to 4-level and 5-level +// paging. +// +// The array has to be sorted in decreasing order. +var feasibleTaskSizes = []uintptr{0xffffffffff000, 0x7ffffffff000} diff --git a/pkg/abi/linux/mm_arm64.go b/pkg/abi/linux/mm_arm64.go new file mode 100644 index 000000000..2d36f860d --- /dev/null +++ b/pkg/abi/linux/mm_arm64.go @@ -0,0 +1,25 @@ +// 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. + +//go:build arm64 +// +build arm64 + +package linux + +// Only 4K page size is supported on arm64. In this case, TASK_SIZE can +// be one of three values, corresponding to 3-level, 4-level and +// 5-level paging. +// +// The array has to be sorted in decreasing order. +var feasibleTaskSizes = []uintptr{1 << 52, 1 << 48, 1 << 39} diff --git a/pkg/sentry/platform/ptrace/subprocess.go b/pkg/sentry/platform/ptrace/subprocess.go index ec590d25a..45405d651 100644 --- a/pkg/sentry/platform/ptrace/subprocess.go +++ b/pkg/sentry/platform/ptrace/subprocess.go @@ -30,6 +30,14 @@ import ( "gvisor.dev/gvisor/pkg/sync" ) +var ( + // maximumUserAddress is the largest possible user address. + maximumUserAddress = linux.TaskSize + + // stubInitAddress is the initial attempt link address for the stub. + stubInitAddress = linux.TaskSize +) + // Linux kernel errnos which "should never be seen by user programs", but will // be revealed to ptrace syscall exit tracing. // diff --git a/pkg/sentry/platform/ptrace/subprocess_amd64.go b/pkg/sentry/platform/ptrace/subprocess_amd64.go index 13a55b784..d1ae9c1b2 100644 --- a/pkg/sentry/platform/ptrace/subprocess_amd64.go +++ b/pkg/sentry/platform/ptrace/subprocess_amd64.go @@ -28,12 +28,6 @@ import ( ) const ( - // maximumUserAddress is the largest possible user address. - maximumUserAddress = 0x7ffffffff000 - - // stubInitAddress is the initial attempt link address for the stub. - stubInitAddress = 0x7fffffff0000 - // initRegsRipAdjustment is the size of the syscall instruction. initRegsRipAdjustment = 2 ) diff --git a/pkg/sentry/platform/ptrace/subprocess_arm64.go b/pkg/sentry/platform/ptrace/subprocess_arm64.go index 8181db659..b61a79aca 100644 --- a/pkg/sentry/platform/ptrace/subprocess_arm64.go +++ b/pkg/sentry/platform/ptrace/subprocess_arm64.go @@ -28,13 +28,6 @@ import ( ) const ( - // maximumUserAddress is the largest possible user address. - maximumUserAddress = 0xfffffffff000 - - // stubInitAddress is the initial attempt link address for the stub. - // Only support 48bits VA currently. - stubInitAddress = 0xffffffff0000 - // initRegsRipAdjustment is the size of the svc instruction. initRegsRipAdjustment = 4 )