Skip to content

Commit

Permalink
Arm64: VDSO support for signal
Browse files Browse the repository at this point in the history
The vdso is enabled, so we can use the sigreturn trampolines
the vdso provides in arch module.

Signed-off-by: Bin Lu <[email protected]>
  • Loading branch information
Bin Lu committed Apr 17, 2020
1 parent 0dd9ee0 commit fe001ed
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 18 deletions.
9 changes: 9 additions & 0 deletions pkg/sentry/loader/loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,15 @@ func Load(ctx context.Context, args LoadArgs, extraAuxv []arch.AuxEntry, vdso *V
m.SetAuxv(auxv)
m.SetExecutable(d)

symbolValue, err := getSymbolValueFromVDSO("rt_sigreturn")
if err != nil {
return 0, nil, "", syserr.NewDynamic(fmt.Sprintf("Failed to find rt_sigreturn in vdso: %v", err), syserr.FromError(err).ToLinux())
}

// Found rt_sigretrun.
addr := uint64(vdsoAddr) + symbolValue - vdsoPrelink
m.SetVDSOSigReturn(addr)

ac.SetIP(uintptr(loaded.entry))
ac.SetStack(uintptr(stack.Bottom))

Expand Down
25 changes: 25 additions & 0 deletions pkg/sentry/loader/vdso.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
package loader

import (
"bytes"
"debug/elf"
"fmt"
"io"
"strings"

"gvisor.dev/gvisor/pkg/abi"
"gvisor.dev/gvisor/pkg/context"
Expand All @@ -37,6 +39,8 @@ import (
"gvisor.dev/gvisor/pkg/waiter"
)

const vdsoPrelink = 0xffffffffff700000

type fileContext struct {
context.Context
}
Expand Down Expand Up @@ -218,6 +222,27 @@ type VDSO struct {
phdrs []elf.ProgHeader `state:".([]elfProgHeader)"`
}

// getSymbolValueFromVDSO returns the specific symbol value in vdso.so.
func getSymbolValueFromVDSO(symbol string) (uint64, error) {
f, err := elf.NewFile(bytes.NewReader(vdsoBin))
if err != nil {
return 0, err
}
syms, err := f.Symbols()
if err != nil {
return 0, err
}

for _, sym := range syms {
if elf.ST_BIND(sym.Info) != elf.STB_LOCAL && sym.Section != elf.SHN_UNDEF {
if strings.Contains(sym.Name, symbol) {
return sym.Value, nil
}
}
}
return 0, fmt.Errorf("no %v in vdso.so", symbol)
}

// PrepareVDSO validates the system VDSO and returns a VDSO, containing the
// param page for updating by the kernel.
func PrepareVDSO(ctx context.Context, mfp pgalloc.MemoryFileProvider) (*VDSO, error) {
Expand Down
25 changes: 13 additions & 12 deletions vdso/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@
#include <stddef.h>
#include <sys/types.h>

#define __stringify_1(x...) #x
#define __stringify(x...) __stringify_1(x)

namespace vdso {

#if __x86_64__
Expand All @@ -51,20 +54,13 @@ static inline int sys_getcpu(unsigned* cpu, unsigned* node,
return num;
}

#elif __aarch64__

static inline int sys_rt_sigreturn(void) {
int num = __NR_rt_sigreturn;

asm volatile(
"mov x8, %0\n"
"svc #0 \n"
: "+r"(num)
:
:);
return num;
static inline void sys_rt_sigreturn(void) {
asm volatile("movl $" __stringify(__NR_rt_sigreturn)", %eax \n"
"syscall \n");
}

#elif __aarch64__

static inline int sys_clock_gettime(clockid_t _clkid, struct timespec* _ts) {
register struct timespec* ts asm("x1") = _ts;
register clockid_t clkid asm("x0") = _clkid;
Expand All @@ -91,6 +87,11 @@ static inline int sys_clock_getres(clockid_t _clkid, struct timespec* _ts) {
return ret;
}

static inline void sys_rt_sigreturn(void) {
asm volatile("mov x8, #" __stringify(__NR_rt_sigreturn)" \n"
"svc #0 \n");
}

#else
#error "unsupported architecture"
#endif
Expand Down
12 changes: 6 additions & 6 deletions vdso/vdso.cc
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ int __common_gettimeofday(struct timeval* tv, struct timezone* tz) {
}
} // namespace

// __kernel_rt_sigreturn() implements rt_sigreturn()
extern "C" void __kernel_rt_sigreturn(unsigned long unused) {
// No optimizations yet, just make the real system call.
sys_rt_sigreturn();
}

#if __x86_64__

// __vdso_clock_gettime() implements clock_gettime()
Expand Down Expand Up @@ -139,12 +145,6 @@ extern "C" int __kernel_clock_getres(clockid_t clock, struct timespec* res) {
return ret;
}

// __kernel_rt_sigreturn() implements gettimeofday()
extern "C" int __kernel_rt_sigreturn(unsigned long unused) {
// No optimizations yet, just make the real system call.
return sys_rt_sigreturn();
}

#else
#error "unsupported architecture"
#endif
Expand Down
1 change: 1 addition & 0 deletions vdso/vdso_amd64.lds
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ VERSION {
__vdso_getcpu;
time;
__vdso_time;
__kernel_rt_sigreturn;

local: *;
};
Expand Down

0 comments on commit fe001ed

Please sign in to comment.