Merge pull request #4874 from zhlhahaha:2022
PiperOrigin-RevId: 346134026
This commit is contained in:
commit
7527371f0f
|
@ -72,7 +72,6 @@ go_library(
|
|||
"lib_amd64.s",
|
||||
"lib_arm64.go",
|
||||
"lib_arm64.s",
|
||||
"lib_arm64_unsafe.go",
|
||||
"ring0.go",
|
||||
],
|
||||
visibility = ["//pkg/sentry:internal"],
|
||||
|
|
|
@ -132,40 +132,6 @@
|
|||
MOVD offset+PTRACE_R29(reg), R29; \
|
||||
MOVD offset+PTRACE_R30(reg), R30;
|
||||
|
||||
// NOP-s
|
||||
#define nop31Instructions() \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f; \
|
||||
WORD $0xd503201f;
|
||||
|
||||
#define ESR_ELx_EC_UNKNOWN (0x00)
|
||||
#define ESR_ELx_EC_WFx (0x01)
|
||||
/* Unallocated EC: 0x02 */
|
||||
|
@ -764,79 +730,43 @@ TEXT ·El0_error_invalid(SB),NOSPLIT,$0
|
|||
B ·Shutdown(SB)
|
||||
|
||||
// Vectors implements exception vector table.
|
||||
// The start address of exception vector table should be 11-bits aligned.
|
||||
// For detail, please refer to arm developer document:
|
||||
// https://developer.arm.com/documentation/100933/0100/AArch64-exception-vector-table
|
||||
// Also can refer to the code in linux kernel: arch/arm64/kernel/entry.S
|
||||
TEXT ·Vectors(SB),NOSPLIT,$0
|
||||
PCALIGN $2048
|
||||
B ·El1_sync_invalid(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El1_irq_invalid(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El1_fiq_invalid(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El1_error_invalid(SB)
|
||||
nop31Instructions()
|
||||
|
||||
PCALIGN $128
|
||||
B ·El1_sync(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El1_irq(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El1_fiq(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El1_error(SB)
|
||||
nop31Instructions()
|
||||
|
||||
PCALIGN $128
|
||||
B ·El0_sync(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El0_irq(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El0_fiq(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El0_error(SB)
|
||||
nop31Instructions()
|
||||
|
||||
PCALIGN $128
|
||||
B ·El0_sync_invalid(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El0_irq_invalid(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El0_fiq_invalid(SB)
|
||||
nop31Instructions()
|
||||
PCALIGN $128
|
||||
B ·El0_error_invalid(SB)
|
||||
nop31Instructions()
|
||||
|
||||
// The exception-vector-table is required to be 11-bits aligned.
|
||||
// Please see Linux source code as reference: arch/arm64/kernel/entry.s.
|
||||
// For gvisor, I defined it as 4K in length, filled the 2nd 2K part with NOPs.
|
||||
// So that, I can safely move the 1st 2K part into the address with 11-bits alignment.
|
||||
WORD $0xd503201f //nop
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
WORD $0xd503201f
|
||||
nop31Instructions()
|
||||
|
|
|
@ -62,6 +62,4 @@ func DisableVFP()
|
|||
// Init sets function pointers based on architectural features.
|
||||
//
|
||||
// This must be called prior to using ring0.
|
||||
func Init() {
|
||||
rewriteVectors()
|
||||
}
|
||||
func Init() {}
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
// Copyright 2019 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.
|
||||
|
||||
// +build arm64
|
||||
|
||||
package ring0
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"gvisor.dev/gvisor/pkg/safecopy"
|
||||
"gvisor.dev/gvisor/pkg/usermem"
|
||||
)
|
||||
|
||||
const (
|
||||
nopInstruction = 0xd503201f
|
||||
instSize = unsafe.Sizeof(uint32(0))
|
||||
vectorsRawLen = 0x800
|
||||
)
|
||||
|
||||
func unsafeSlice(addr uintptr, length int) (slice []uint32) {
|
||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&slice))
|
||||
hdr.Data = addr
|
||||
hdr.Len = length / int(instSize)
|
||||
hdr.Cap = length / int(instSize)
|
||||
return slice
|
||||
}
|
||||
|
||||
// Work around: move ring0.Vectors() into a specific address with 11-bits alignment.
|
||||
//
|
||||
// According to the design documentation of Arm64,
|
||||
// the start address of exception vector table should be 11-bits aligned.
|
||||
// Please see the code in linux kernel as reference: arch/arm64/kernel/entry.S
|
||||
// But, we can't align a function's start address to a specific address by using golang.
|
||||
// We have raised this question in golang community:
|
||||
// https://groups.google.com/forum/m/#!topic/golang-dev/RPj90l5x86I
|
||||
// This function will be removed when golang supports this feature.
|
||||
//
|
||||
// There are 2 jobs were implemented in this function:
|
||||
// 1, move the start address of exception vector table into the specific address.
|
||||
// 2, modify the offset of each instruction.
|
||||
func rewriteVectors() {
|
||||
vectorsBegin := reflect.ValueOf(Vectors).Pointer()
|
||||
|
||||
// The exception-vector-table is required to be 11-bits aligned.
|
||||
// And the size is 0x800.
|
||||
// Please see the documentation as reference:
|
||||
// https://developer.arm.com/docs/100933/0100/aarch64-exception-vector-table
|
||||
//
|
||||
// But, golang does not allow to set a function's address to a specific value.
|
||||
// So, for gvisor, I defined the size of exception-vector-table as 4K,
|
||||
// filled the 2nd 2K part with NOP-s.
|
||||
// So that, I can safely move the 1st 2K part into the address with 11-bits alignment.
|
||||
//
|
||||
// So, the prerequisite for this function to work correctly is:
|
||||
// vectorsSafeLen >= 0x1000
|
||||
// vectorsRawLen = 0x800
|
||||
vectorsSafeLen := int(safecopy.FindEndAddress(vectorsBegin) - vectorsBegin)
|
||||
if vectorsSafeLen < 2*vectorsRawLen {
|
||||
panic("Can't update vectors")
|
||||
}
|
||||
|
||||
vectorsSafeTable := unsafeSlice(vectorsBegin, vectorsSafeLen) // Now a []uint32
|
||||
vectorsRawLen32 := vectorsRawLen / int(instSize)
|
||||
|
||||
offset := vectorsBegin & (1<<11 - 1)
|
||||
if offset != 0 {
|
||||
offset = 1<<11 - offset
|
||||
}
|
||||
|
||||
pageBegin := (vectorsBegin + offset) & ^uintptr(usermem.PageSize-1)
|
||||
|
||||
_, _, errno := syscall.Syscall(syscall.SYS_MPROTECT, uintptr(pageBegin), uintptr(usermem.PageSize), uintptr(syscall.PROT_READ|syscall.PROT_WRITE|syscall.PROT_EXEC))
|
||||
if errno != 0 {
|
||||
panic(errno.Error())
|
||||
}
|
||||
|
||||
offset = offset / instSize // By index, not bytes.
|
||||
// Move exception-vector-table into the specific address, should uses memmove here.
|
||||
for i := 1; i <= vectorsRawLen32; i++ {
|
||||
vectorsSafeTable[int(offset)+vectorsRawLen32-i] = vectorsSafeTable[vectorsRawLen32-i]
|
||||
}
|
||||
|
||||
// Adjust branch since instruction was moved forward.
|
||||
for i := 0; i < vectorsRawLen32; i++ {
|
||||
if vectorsSafeTable[int(offset)+i] != nopInstruction {
|
||||
vectorsSafeTable[int(offset)+i] -= uint32(offset)
|
||||
}
|
||||
}
|
||||
|
||||
_, _, errno = syscall.Syscall(syscall.SYS_MPROTECT, uintptr(pageBegin), uintptr(usermem.PageSize), uintptr(syscall.PROT_READ|syscall.PROT_EXEC))
|
||||
if errno != 0 {
|
||||
panic(errno.Error())
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue