Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105739817
D32960.id98552.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
32 KB
Referenced Files
None
Subscribers
None
D32960.id98552.diff
View Options
diff --git a/libexec/rtld-elf/map_object.c b/libexec/rtld-elf/map_object.c
--- a/libexec/rtld-elf/map_object.c
+++ b/libexec/rtld-elf/map_object.c
@@ -345,6 +345,39 @@
return (NULL);
}
+bool
+check_elf_headers(const Elf_Ehdr *hdr, const char *path)
+{
+ if (!IS_ELF(*hdr)) {
+ _rtld_error("%s: invalid file format", path);
+ return (false);
+ }
+ if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
+ hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
+ _rtld_error("%s: unsupported file layout", path);
+ return (false);
+ }
+ if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
+ hdr->e_version != EV_CURRENT) {
+ _rtld_error("%s: unsupported file version", path);
+ return (false);
+ }
+ if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
+ _rtld_error("%s: unsupported file type", path);
+ return (false);
+ }
+ if (hdr->e_machine != ELF_TARG_MACH) {
+ _rtld_error("%s: unsupported machine", path);
+ return (false);
+ }
+ if (hdr->e_phentsize != sizeof(Elf_Phdr)) {
+ _rtld_error(
+ "%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path);
+ return (false);
+ }
+ return (true);
+}
+
static Elf_Ehdr *
get_elf_header(int fd, const char *path, const struct stat *sbp,
Elf_Phdr **phdr_p)
@@ -366,39 +399,14 @@
}
/* Make sure the file is valid */
- if (!IS_ELF(*hdr)) {
- _rtld_error("%s: invalid file format", path);
+ if (!check_elf_headers(hdr, path))
goto error;
- }
- if (hdr->e_ident[EI_CLASS] != ELF_TARG_CLASS ||
- hdr->e_ident[EI_DATA] != ELF_TARG_DATA) {
- _rtld_error("%s: unsupported file layout", path);
- goto error;
- }
- if (hdr->e_ident[EI_VERSION] != EV_CURRENT ||
- hdr->e_version != EV_CURRENT) {
- _rtld_error("%s: unsupported file version", path);
- goto error;
- }
- if (hdr->e_type != ET_EXEC && hdr->e_type != ET_DYN) {
- _rtld_error("%s: unsupported file type", path);
- goto error;
- }
- if (hdr->e_machine != ELF_TARG_MACH) {
- _rtld_error("%s: unsupported machine", path);
- goto error;
- }
/*
* We rely on the program header being in the first page. This is
* not strictly required by the ABI specification, but it seems to
* always true in practice. And, it simplifies things considerably.
*/
- if (hdr->e_phentsize != sizeof(Elf_Phdr)) {
- _rtld_error(
- "%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path);
- goto error;
- }
if (phdr_in_zero_page(hdr)) {
phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff);
} else {
diff --git a/libexec/rtld-elf/rtld.h b/libexec/rtld-elf/rtld.h
--- a/libexec/rtld-elf/rtld.h
+++ b/libexec/rtld-elf/rtld.h
@@ -405,6 +405,7 @@
const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long);
int convert_prot(int elfflags);
void *_get_tp(void); /* libc implementation */
+bool check_elf_headers(const Elf_Ehdr *hdr, const char *path);
/*
* MD function declarations.
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -125,6 +125,7 @@
static void unload_filtees(Obj_Entry *, RtldLockState *);
static int load_needed_objects(Obj_Entry *, int);
static int load_preload_objects(const char *, bool);
+static int load_kpreload(const void *addr);
static Obj_Entry *load_object(const char *, int fd, const Obj_Entry *, int);
static void map_stacks_exec(RtldLockState *);
static int obj_disable_relro(Obj_Entry *);
@@ -828,6 +829,12 @@
if (!libmap_disable)
libmap_disable = (bool)lm_init(libmap_override);
+ if (aux_info[AT_KPRELOAD]->a_un.a_ptr != NULL) {
+ dbg("loading kernel vdso");
+ if (load_kpreload(aux_info[AT_KPRELOAD]->a_un.a_ptr) == -1)
+ rtld_die();
+ }
+
dbg("loading LD_PRELOAD_FDS libraries");
if (load_preload_objects(ld_preload_fds, true) == -1)
rtld_die();
@@ -2842,6 +2849,71 @@
return (NULL);
}
+static int
+load_kpreload(const void *addr)
+{
+ Obj_Entry *obj;
+ const Elf_Ehdr *ehdr;
+ const Elf_Phdr *phdr, *phlimit, *phdyn, *seg0, *segn;
+ size_t phsize;
+ static const char kname[] = "[vdso]";
+
+ ehdr = addr;
+ if (!check_elf_headers(ehdr, "kpreload"))
+ return (false);
+ phdr = (const Elf_Phdr *)((const char *)addr + ehdr->e_phoff);
+ phlimit = phdr + ehdr->e_phnum;
+ phsize = ehdr->e_phnum * sizeof(*phdr);
+ seg0 = segn = NULL;
+ obj = obj_new();
+
+ for (; phdr < phlimit; phdr++) {
+ switch (phdr->p_type) {
+ case PT_DYNAMIC:
+ phdyn = phdr;
+ break;
+ case PT_GNU_STACK:
+ obj->stack_flags = phdr->p_flags;
+ break;
+ case PT_LOAD:
+ if (seg0 == NULL || seg0->p_vaddr > phdr->p_vaddr)
+ seg0 = phdr;
+ if (segn == NULL || segn->p_vaddr + segn->p_memsz <
+ phdr->p_vaddr + phdr->p_memsz)
+ segn = phdr;
+ break;
+ }
+ }
+
+ obj->mapbase = __DECONST(caddr_t, addr);
+ obj->mapsize = segn->p_vaddr + segn->p_memsz - (Elf_Addr)addr;
+ obj->vaddrbase = 0;
+ obj->relocbase = obj->mapbase;
+
+ object_add_name(obj, kname);
+ obj->path = xstrdup(kname);
+ obj->dynamic = (const Elf_Dyn *)(obj->relocbase + phdyn->p_vaddr);
+ obj->phdr = phdr;
+ obj->phsize = phsize;
+
+ if (!digest_dynamic(obj, 0)) {
+ obj_free(obj);
+ return (-1);
+ }
+
+ dbg("%s valid_hash_sysv %d valid_hash_gnu %d dynsymcount %d", obj->path,
+ obj->valid_hash_sysv, obj->valid_hash_gnu, obj->dynsymcount);
+
+ TAILQ_INSERT_TAIL(&obj_list, obj, next);
+ obj_count++;
+ obj_loads++;
+ linkmap_add(obj); /* for GDB & dlinfo() */
+ max_stack_flags |= obj->stack_flags;
+
+ LD_UTRACE(UTRACE_LOAD_OBJECT, obj, obj->mapbase, 0, 0, obj->path);
+ return (0);
+}
+
Obj_Entry *
obj_from_addr(const void *addr)
{
@@ -6103,6 +6175,7 @@
AUXFMT(AT_ENVV, "%p"),
AUXFMT(AT_PS_STRINGS, "%p"),
AUXFMT(AT_FXRNG, "%p"),
+ AUXFMT(AT_KPRELOAD, "%p"),
};
static bool
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -49,14 +49,21 @@
#include <machine/fpu.h>
#include <machine/md_var.h>
+#include "vdso_offsets.h"
+
+extern const char _binary_elf_vdso_so_1_start[];
+extern const char _binary_elf_vdso_so_1_end[];
+extern char _binary_elf_vdso_so_1_size;
+
struct sysentvec elf64_freebsd_sysvec_la48 = {
.sv_size = SYS_MAXSYSCALL,
.sv_table = sysent,
.sv_transtrap = NULL,
.sv_fixup = __elfN(freebsd_fixup),
.sv_sendsig = sendsig,
- .sv_sigcode = sigcode,
- .sv_szsigcode = &szsigcode,
+ .sv_sigcode = _binary_elf_vdso_so_1_start,
+ .sv_szsigcode = (int *)&_binary_elf_vdso_so_1_size,
+ .sv_sigcodeoff = VDSO_SIGCODE_OFFSET,
.sv_name = "FreeBSD ELF64",
.sv_coredump = __elfN(coredump),
.sv_elf_core_osabi = ELFOSABI_FREEBSD,
@@ -75,7 +82,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
- SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
@@ -96,8 +103,9 @@
.sv_transtrap = NULL,
.sv_fixup = __elfN(freebsd_fixup),
.sv_sendsig = sendsig,
- .sv_sigcode = sigcode,
- .sv_szsigcode = &szsigcode,
+ .sv_sigcode = _binary_elf_vdso_so_1_start,
+ .sv_szsigcode = (int *)&_binary_elf_vdso_so_1_size,
+ .sv_sigcodeoff = VDSO_SIGCODE_OFFSET,
.sv_name = "FreeBSD ELF64",
.sv_coredump = __elfN(coredump),
.sv_elf_core_osabi = ELFOSABI_FREEBSD,
@@ -116,7 +124,7 @@
.sv_fixlimit = NULL,
.sv_maxssiz = NULL,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_LP64 | SV_SHP |
- SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
.sv_set_syscall_retval = cpu_set_syscall_retval,
.sv_fetch_syscall_args = cpu_fetch_syscall_args,
.sv_syscallnames = syscallnames,
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c
--- a/sys/amd64/amd64/genassym.c
+++ b/sys/amd64/amd64/genassym.c
@@ -205,6 +205,24 @@
ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler));
ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc));
ASSYM(UC_EFLAGS, offsetof(ucontext_t, uc_mcontext.mc_rflags));
+ASSYM(UC_RDI, offsetof(ucontext_t, uc_mcontext.mc_rdi));
+ASSYM(UC_RSI, offsetof(ucontext_t, uc_mcontext.mc_rsi));
+ASSYM(UC_RDX, offsetof(ucontext_t, uc_mcontext.mc_rdx));
+ASSYM(UC_RCX, offsetof(ucontext_t, uc_mcontext.mc_rcx));
+ASSYM(UC_R8, offsetof(ucontext_t, uc_mcontext.mc_r8));
+ASSYM(UC_R9, offsetof(ucontext_t, uc_mcontext.mc_r9));
+ASSYM(UC_RAX, offsetof(ucontext_t, uc_mcontext.mc_rax));
+ASSYM(UC_RBX, offsetof(ucontext_t, uc_mcontext.mc_rbx));
+ASSYM(UC_RBP, offsetof(ucontext_t, uc_mcontext.mc_rbp));
+ASSYM(UC_R10, offsetof(ucontext_t, uc_mcontext.mc_r10));
+ASSYM(UC_R11, offsetof(ucontext_t, uc_mcontext.mc_r11));
+ASSYM(UC_R12, offsetof(ucontext_t, uc_mcontext.mc_r12));
+ASSYM(UC_R13, offsetof(ucontext_t, uc_mcontext.mc_r13));
+ASSYM(UC_R14, offsetof(ucontext_t, uc_mcontext.mc_r14));
+ASSYM(UC_R15, offsetof(ucontext_t, uc_mcontext.mc_r15));
+ASSYM(UC_RIP, offsetof(ucontext_t, uc_mcontext.mc_rip));
+ASSYM(UC_RSP, offsetof(ucontext_t, uc_mcontext.mc_rsp));
+
ASSYM(ENOENT, ENOENT);
ASSYM(EFAULT, EFAULT);
ASSYM(ENAMETOOLONG, ENAMETOOLONG);
diff --git a/sys/amd64/amd64/sigtramp.S b/sys/amd64/amd64/sigtramp.S
--- a/sys/amd64/amd64/sigtramp.S
+++ b/sys/amd64/amd64/sigtramp.S
@@ -2,6 +2,11 @@
* Copyright (c) 2003 Peter Wemm <peter@freeBSD.org>
* All rights reserved.
*
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -27,30 +32,44 @@
*/
#include <sys/syscall.h>
-
#include <machine/asmacros.h>
#include "assym.inc"
.text
-/**********************************************************************
- *
- * Signal trampoline, copied to top of user stack
- *
+/*
+ * Signal trampoline, mapped as vdso into shared page.
*/
-ENTRY(sigcode)
+ENTRY(__vdso_sigcode)
+ .cfi_startproc
+ .cfi_signal_frame
+ .cfi_def_cfa %rsp, 0
+ .cfi_offset %rdi, SIGF_UC + UC_RDI
+ .cfi_offset %rsi, SIGF_UC + UC_RSI
+ .cfi_offset %rdx, SIGF_UC + UC_RDX
+ .cfi_offset %rcx, SIGF_UC + UC_RCX
+ .cfi_offset %r8, SIGF_UC + UC_R8
+ .cfi_offset %r9, SIGF_UC + UC_R9
+ .cfi_offset %rax, SIGF_UC + UC_RAX
+ .cfi_offset %rbx, SIGF_UC + UC_RBX
+ .cfi_offset %rbp, SIGF_UC + UC_RBP
+ .cfi_offset %r10, SIGF_UC + UC_R10
+ .cfi_offset %r11, SIGF_UC + UC_R11
+ .cfi_offset %r12, SIGF_UC + UC_R12
+ .cfi_offset %r13, SIGF_UC + UC_R13
+ .cfi_offset %r14, SIGF_UC + UC_R14
+ .cfi_offset %r15, SIGF_UC + UC_R15
+ .cfi_offset %rip, SIGF_UC + UC_RIP
+ .cfi_offset %rsp, SIGF_UC + UC_RSP
call *SIGF_HANDLER(%rsp) /* call signal handler */
lea SIGF_UC(%rsp),%rdi /* get ucontext_t */
pushq $0 /* junk to fake return addr. */
+ .cfi_def_cfa %rsp, 8
movq $SYS_sigreturn,%rax
syscall /* enter kernel with args */
0: hlt /* trap priviliged instruction */
jmp 0b
+ .cfi_endproc
+END(__vdso_sigcode)
- ALIGN_TEXT
-esigcode:
-
- .data
- .globl szsigcode
-szsigcode:
- .long esigcode-sigcode
+ .section .note.GNU-stack,"",%progbits
diff --git a/sys/amd64/ia32/ia32_signal.c b/sys/amd64/ia32/ia32_signal.c
--- a/sys/amd64/ia32/ia32_signal.c
+++ b/sys/amd64/ia32/ia32_signal.c
@@ -81,6 +81,12 @@
#include <machine/cpufunc.h>
#include <machine/trap.h>
+#include "vdso_ia32_offsets.h"
+
+extern const char _binary_elf_vdso32_so_1_start[];
+extern const char _binary_elf_vdso32_so_1_end[];
+extern char _binary_elf_vdso32_so_1_size;
+
#ifdef COMPAT_FREEBSD4
static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
#endif
@@ -416,7 +422,9 @@
}
regs->tf_rsp = (uintptr_t)fp;
- regs->tf_rip = p->p_sysent->sv_psstrings - sz_ia32_osigcode;
+ regs->tf_rip = p->p_sysent->sv_psstrings -
+ (_binary_elf_vdso32_so_1_end - _binary_elf_vdso32_so_1_start) +
+ VDSO_IA32_OSIGCODE_OFFSET;
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ds = _udatasel;
@@ -527,8 +535,8 @@
}
regs->tf_rsp = (uintptr_t)sfp;
- regs->tf_rip = p->p_sysent->sv_sigcode_base + sz_ia32_sigcode -
- sz_freebsd4_ia32_sigcode;
+ regs->tf_rip = p->p_sysent->sv_sigcode_base +
+ VDSO_FREEBSD4_IA32_SIGCODE_OFFSET;
regs->tf_rflags &= ~(PSL_T | PSL_D);
regs->tf_cs = _ucode32sel;
regs->tf_ss = _udatasel;
diff --git a/sys/amd64/ia32/ia32_sigtramp.S b/sys/amd64/ia32/ia32_sigtramp.S
--- a/sys/amd64/ia32/ia32_sigtramp.S
+++ b/sys/amd64/ia32/ia32_sigtramp.S
@@ -2,6 +2,11 @@
* Copyright (c) 2003 Peter Wemm
* All rights reserved.
*
+ * Copyright (c) 2021 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Konstantin Belousov
+ * under sponsorship from the FreeBSD Foundation.
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -32,27 +37,42 @@
#include "ia32_assym.h"
.text
- .code32
/*
- * Signal trampoline, copied to top of user stack
- * XXX may need to be MD to match backend sendsig handoff protocol
+ * Signal trampoline, mapped as vdso into shared page, or copied to
+ * top of user stack for old binaries.
*/
ALIGN_TEXT
- .globl ia32_sigcode
-ia32_sigcode:
+ .globl __vdso_ia32_sigcode
+__vdso_ia32_sigcode:
+ .cfi_startproc
+ .cfi_signal_frame
+ .cfi_def_cfa %esp, 0
+ .cfi_offset %edi, IA32_SIGF_UC + IA32_UC_EDI
+ .cfi_offset %esi, IA32_SIGF_UC + IA32_UC_ESI
+ .cfi_offset %ebp, IA32_SIGF_UC + IA32_UC_EBP
+ .cfi_offset %ebx, IA32_SIGF_UC + IA32_UC_EBX
+ .cfi_offset %edx, IA32_SIGF_UC + IA32_UC_EDX
+ .cfi_offset %ecx, IA32_SIGF_UC + IA32_UC_ECX
+ .cfi_offset %eax, IA32_SIGF_UC + IA32_UC_EAX
+ .cfi_offset %eip, IA32_SIGF_UC + IA32_UC_EIP
+ .cfi_offset %esp, IA32_SIGF_UC + IA32_UC_ESP
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC(%esp),%eax /* get ucontext */
pushl %eax
+ .cfi_def_cfa %esp, 4
movl $SYS_sigreturn,%eax
pushl %eax /* junk to fake return addr. */
+ .cfi_def_cfa %esp, 8
int $0x80 /* enter kernel with args */
/* on stack */
1:
jmp 1b
+ .cfi_endproc
#ifdef COMPAT_FREEBSD4
ALIGN_TEXT
-freebsd4_ia32_sigcode:
+ .globl __vdso_freebsd4_ia32_sigcode
+__vdso_freebsd4_ia32_sigcode:
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC4(%esp),%eax/* get ucontext */
pushl %eax
@@ -66,7 +86,8 @@
#ifdef COMPAT_43
ALIGN_TEXT
-ia32_osigcode:
+ .globl __vdso_ia32_osigcode
+__vdso_ia32_osigcode:
calll *IA32_SIGF_HANDLER(%esp)/* call signal handler */
leal IA32_SIGF_SC(%esp),%eax /* get sigcontext */
pushl %eax
@@ -90,28 +111,8 @@
* vfork() and harder for other syscalls.
*/
ALIGN_TEXT
-lcall_tramp:
+ .globl __vdso_lcall_tramp
+__vdso_lcall_tramp:
int $0x80
1: jmp 1b
-#endif
-
- ALIGN_TEXT
-esigcode:
-
- .data
- .globl sz_ia32_sigcode
-sz_ia32_sigcode:
- .long esigcode-ia32_sigcode
-#ifdef COMPAT_FREEBSD4
- .globl sz_freebsd4_ia32_sigcode
-sz_freebsd4_ia32_sigcode:
- .long esigcode-freebsd4_ia32_sigcode
-#endif
-#ifdef COMPAT_43
- .globl sz_ia32_osigcode
-sz_ia32_osigcode:
- .long esigcode-ia32_osigcode
- .globl sz_lcall_tramp
-sz_lcall_tramp:
- .long esigcode-lcall_tramp
#endif
diff --git a/sys/amd64/ia32/ia32_syscall.c b/sys/amd64/ia32/ia32_syscall.c
--- a/sys/amd64/ia32/ia32_syscall.c
+++ b/sys/amd64/ia32/ia32_syscall.c
@@ -92,6 +92,12 @@
#include <machine/pcb.h>
#include <machine/cpufunc.h>
+#include "vdso_ia32_offsets.h"
+
+extern const char _binary_elf_vdso32_so_1_start[];
+extern const char _binary_elf_vdso32_so_1_end[];
+extern char _binary_elf_vdso32_so_1_size;
+
#define IDTVEC(name) __CONCAT(X,name)
extern inthand_t IDTVEC(int0x80_syscall), IDTVEC(int0x80_syscall_pti),
@@ -264,7 +270,9 @@
bzero(&uap, sizeof(uap));
uap.start = 0;
uap.num = 1;
- lcall_addr = curproc->p_sysent->sv_psstrings - sz_lcall_tramp;
+ lcall_addr = curproc->p_sysent->sv_psstrings -
+ (_binary_elf_vdso32_so_1_end - _binary_elf_vdso32_so_1_start) +
+ VDSO_LCALL_TRAMP_OFFSET;
bzero(&desc, sizeof(desc));
desc.sd_type = SDT_MEMERA;
desc.sd_dpl = SEL_UPL;
diff --git a/sys/compat/ia32/ia32_genassym.c b/sys/compat/ia32/ia32_genassym.c
--- a/sys/compat/ia32/ia32_genassym.c
+++ b/sys/compat/ia32/ia32_genassym.c
@@ -11,6 +11,15 @@
ASSYM(IA32_SIGF_HANDLER, offsetof(struct ia32_sigframe, sf_ah));
ASSYM(IA32_SIGF_UC, offsetof(struct ia32_sigframe, sf_uc));
+ASSYM(IA32_UC_EDI, offsetof(struct ia32_ucontext, uc_mcontext.mc_edi));
+ASSYM(IA32_UC_ESI, offsetof(struct ia32_ucontext, uc_mcontext.mc_esi));
+ASSYM(IA32_UC_EBP, offsetof(struct ia32_ucontext, uc_mcontext.mc_ebp));
+ASSYM(IA32_UC_EBX, offsetof(struct ia32_ucontext, uc_mcontext.mc_ebx));
+ASSYM(IA32_UC_EDX, offsetof(struct ia32_ucontext, uc_mcontext.mc_edx));
+ASSYM(IA32_UC_ECX, offsetof(struct ia32_ucontext, uc_mcontext.mc_ecx));
+ASSYM(IA32_UC_EAX, offsetof(struct ia32_ucontext, uc_mcontext.mc_eax));
+ASSYM(IA32_UC_EIP, offsetof(struct ia32_ucontext, uc_mcontext.mc_eip));
+ASSYM(IA32_UC_ESP, offsetof(struct ia32_ucontext, uc_mcontext.mc_esp));
#ifdef COMPAT_43
ASSYM(IA32_SIGF_SC, offsetof(struct ia32_sigframe3, sf_siginfo.si_sc));
#endif
diff --git a/sys/compat/ia32/ia32_signal.h b/sys/compat/ia32/ia32_signal.h
--- a/sys/compat/ia32/ia32_signal.h
+++ b/sys/compat/ia32/ia32_signal.h
@@ -195,14 +195,6 @@
struct ksiginfo;
struct image_params;
-extern char ia32_sigcode[];
-extern char freebsd4_ia32_sigcode[];
-extern char ia32_osigcode[];
-extern char lcall_tramp;
-extern int sz_ia32_sigcode;
-extern int sz_freebsd4_ia32_sigcode;
-extern int sz_ia32_osigcode;
-extern int sz_lcall_tramp;
void ia32_sendsig(sig_t, struct ksiginfo *, sigset_t *);
void ia32_setregs(struct thread *td, struct image_params *imgp,
uintptr_t stack);
diff --git a/sys/compat/ia32/ia32_sysvec.c b/sys/compat/ia32/ia32_sysvec.c
--- a/sys/compat/ia32/ia32_sysvec.c
+++ b/sys/compat/ia32/ia32_sysvec.c
@@ -83,6 +83,12 @@
CTASSERT(sizeof(struct ia32_sigframe4) == 408);
#endif
+#include "vdso_ia32_offsets.h"
+
+extern const char _binary_elf_vdso32_so_1_start[];
+extern const char _binary_elf_vdso32_so_1_end[];
+extern char _binary_elf_vdso32_so_1_size;
+
extern const char *freebsd32_syscallnames[];
static SYSCTL_NODE(_compat, OID_AUTO, ia32, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
@@ -101,8 +107,9 @@
.sv_transtrap = NULL,
.sv_fixup = elf32_freebsd_fixup,
.sv_sendsig = ia32_sendsig,
- .sv_sigcode = ia32_sigcode,
- .sv_szsigcode = &sz_ia32_sigcode,
+ .sv_sigcode = _binary_elf_vdso32_so_1_start,
+ .sv_szsigcode = (int *)&_binary_elf_vdso32_so_1_size,
+ .sv_sigcodeoff = VDSO_IA32_SIGCODE_OFFSET,
.sv_name = "FreeBSD ELF32",
.sv_coredump = elf32_coredump,
.sv_elf_core_osabi = ELFOSABI_FREEBSD,
@@ -121,7 +128,7 @@
.sv_fixlimit = ia32_fixlimit,
.sv_maxssiz = &ia32_maxssiz,
.sv_flags = SV_ABI_FREEBSD | SV_ASLR | SV_IA32 | SV_ILP32 |
- SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER,
+ SV_SHP | SV_TIMEKEEP | SV_RNG_SEED_VER | SV_DSO_SIG,
.sv_set_syscall_retval = ia32_set_syscall_retval,
.sv_fetch_syscall_args = ia32_fetch_syscall_args,
.sv_syscallnames = freebsd32_syscallnames,
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -12,6 +12,18 @@
# dependency lines other than the first are silently ignored.
#
#
+elf-vdso.so.o standard \
+ dependency "$S/amd64/amd64/sigtramp.S assym.inc $S/tools/amd64_vdso.sh" \
+ compile-with "env NM='${NM}' LD='${LD}' CC='${CC}' OBJCOPY='${OBJCOPY}' S='${S}' sh $S/tools/amd64_vdso.sh" \
+ no-implicit-rule before-depend \
+ clean "elf-vdso.so.o elf-vdso.so.1 vdso_offsets.h sigtramp.pico"
+#
+elf-vdso32.so.o optional compat_freebsd32 \
+ dependency "$S/amd64/ia32/ia32_sigtramp.S ia32_assym.h $S/tools/amd64_ia32_vdso.sh" \
+ compile-with "env NM='${NM}' LD='${LD}' CC='${CC}' OBJCOPY='${OBJCOPY}' S='${S}' sh $S/tools/amd64_ia32_vdso.sh" \
+ no-implicit-rule before-depend \
+ clean "elf-vdso32.so.o elf-vdso32.so.1 vdso_ia32_offsets.h ia32_sigtramp.pico"
+#
ia32_genassym.o standard \
dependency "$S/compat/ia32/ia32_genassym.c offset.inc" \
compile-with "${CC} ${CFLAGS:N-flto:N-fno-common} -fcommon -c ${.IMPSRC}" \
@@ -76,7 +88,6 @@
amd64/amd64/mpboot.S optional smp
amd64/amd64/pmap.c standard
amd64/amd64/ptrace_machdep.c standard
-amd64/amd64/sigtramp.S standard
amd64/amd64/support.S standard
amd64/amd64/sys_machdep.c standard
amd64/amd64/trap.c standard
@@ -352,7 +363,6 @@
#amd64/ia32/ia32_exception.S optional compat_freebsd32
amd64/ia32/ia32_reg.c optional compat_freebsd32
amd64/ia32/ia32_signal.c optional compat_freebsd32
-amd64/ia32/ia32_sigtramp.S optional compat_freebsd32
amd64/ia32/ia32_syscall.c optional compat_freebsd32
amd64/ia32/ia32_misc.c optional compat_freebsd32
compat/ia32/ia32_sysvec.c optional compat_freebsd32
diff --git a/sys/conf/vdso_amd64.ldscript b/sys/conf/vdso_amd64.ldscript
new file mode 100644
--- /dev/null
+++ b/sys/conf/vdso_amd64.ldscript
@@ -0,0 +1,59 @@
+/*
+ * Linker script for amd64 vdso.
+ */
+
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(5);
+ eh_frame_hdr PT_GNU_EH_FRAME FLAGS(5);
+}
+
+SECTIONS
+{
+ . = . + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) } :text
+ .dynsym : { *(.dynsym) } :text
+ .dynstr : { *(.dynstr) } :text
+ .gnu.version : { *(.gnu.version) } :text
+ .gnu.version_d : { *(.gnu.version_d) } :text
+ .gnu.version_r : { *(.gnu.version_r) } :text
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .rodata : { *(.rodata*) } :text
+ .data : {
+ *(.got.plt) *(.got)
+ } :text
+ /DISCARD/ /* .data */: {
+ *(.data*)
+ *(.sdata*)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ *(.ctors)
+ *(.dtors)
+ *(.jcr)
+ *(.init_array)
+ *(.init)
+ *(.fini)
+ *(.debug*)
+ *(.comment)
+ }
+
+ . = ALIGN(0x10);
+ .text : { *(.test .text*) } :text =0x90909090
+}
+
+VERSION
+{
+ FBSD_1.7 {
+ global:
+ __vdso_sigcode;
+ local:
+ *;
+ };
+}
diff --git a/sys/conf/vdso_amd64_ia32.ldscript b/sys/conf/vdso_amd64_ia32.ldscript
new file mode 100644
--- /dev/null
+++ b/sys/conf/vdso_amd64_ia32.ldscript
@@ -0,0 +1,64 @@
+/*
+ * Linker script for ia32 (32bit) vdso on amd64.
+ */
+
+OUTPUT_ARCH(i386)
+
+PHDRS
+{
+ text PT_LOAD FILEHDR PHDRS FLAGS(5); /* PF_R|PF_X */
+ dynamic PT_DYNAMIC FLAGS(5);
+ eh_frame_hdr PT_GNU_EH_FRAME FLAGS(5);
+}
+
+SECTIONS
+{
+ . = . + SIZEOF_HEADERS;
+
+ .hash : { *(.hash) } :text
+ .gnu.hash : { *(.gnu.hash) } :text
+ .dynsym : { *(.dynsym) } :text
+ .dynstr : { *(.dynstr) } :text
+ .gnu.version : { *(.gnu.version) } :text
+ .gnu.version_d : { *(.gnu.version_d) } :text
+ .gnu.version_r : { *(.gnu.version_r) } :text
+ .eh_frame_hdr : { *(.eh_frame_hdr) } :text :eh_frame_hdr
+ .eh_frame : { KEEP (*(.eh_frame)) } :text
+ .dynamic : { *(.dynamic) } :text :dynamic
+ .rodata : { *(.rodata*) } :text
+ .data : {
+ *(.got.plt) *(.got)
+ } :text
+ /DISCARD/ /* .data */: {
+ *(.data*)
+ *(.sdata*)
+ *(.gnu.linkonce.d.*)
+ *(.bss*)
+ *(.dynbss*)
+ *(.gnu.linkonce.b.*)
+ *(.ctors)
+ *(.dtors)
+ *(.jcr)
+ *(.init_array)
+ *(.init)
+ *(.fini)
+ *(.debug*)
+ *(.comment)
+ }
+
+ . = ALIGN(0x10);
+ .text : { *(.test .text*) } :text =0x90909090
+}
+
+VERSION
+{
+ FBSD_1.7 {
+ global:
+ __vdso_ia32_sigcode;
+ __vdso_freebsd4_ia32_sigcode;
+ __vdso_ia32_osigcode;
+ __vdso_lcall_tramp;
+ local:
+ *;
+ };
+}
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -108,6 +108,12 @@
#elif defined(__amd64__)
+#include "vdso_ia32_offsets.h"
+
+extern const char _binary_elf_vdso32_so_1_start[];
+extern const char _binary_elf_vdso32_so_1_end[];
+extern char _binary_elf_vdso32_so_1_size;
+
#define AOUT32_PS_STRINGS \
(AOUT32_USRSTACK - sizeof(struct freebsd32_ps_strings))
#define AOUT32_MINUSER FREEBSD32_MINUSER
@@ -115,14 +121,15 @@
extern const char *freebsd32_syscallnames[];
extern u_long ia32_maxssiz;
+static int aout_szsigcode;
+
struct sysentvec aout_sysvec = {
.sv_size = FREEBSD32_SYS_MAXSYSCALL,
.sv_table = freebsd32_sysent,
.sv_transtrap = NULL,
.sv_fixup = aout_fixup,
.sv_sendsig = ia32_sendsig,
- .sv_sigcode = ia32_sigcode,
- .sv_szsigcode = &sz_ia32_sigcode,
+ .sv_szsigcode = &aout_szsigcode,
.sv_name = "FreeBSD a.out",
.sv_coredump = NULL,
.sv_imgact_try = NULL,
@@ -144,6 +151,17 @@
.sv_onexit = exit_onexit,
.sv_set_fork_retval = x86_set_fork_retval,
};
+
+static void
+aout_sysvec_init(void *arg)
+{
+ aout_sysvec.sv_sigcode = _binary_elf_vdso32_so_1_start +
+ VDSO_IA32_OSIGCODE_OFFSET;
+ aout_szsigcode = _binary_elf_vdso32_so_1_end -
+ _binary_elf_vdso32_so_1_start + VDSO_IA32_OSIGCODE_OFFSET;
+}
+SYSINIT(aout, SI_SUB_EXEC, SI_ORDER_MIDDLE, (sysinit_cfunc_t)aout_sysvec_init,
+ NULL);
#else
#error "Port me"
#endif
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -1400,6 +1400,8 @@
AUXARGS_ENTRY_PTR(pos, AT_PS_STRINGS, imgp->ps_strings);
if (imgp->sysent->sv_fxrng_gen_base != 0)
AUXARGS_ENTRY(pos, AT_FXRNG, imgp->sysent->sv_fxrng_gen_base);
+ if (imgp->sysent->sv_vdso_base != 0)
+ AUXARGS_ENTRY(pos, AT_KPRELOAD, imgp->sysent->sv_vdso_base);
AUXARGS_ENTRY(pos, AT_NULL, 0);
free(imgp->auxargs, M_TEMP);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -3100,7 +3100,9 @@
if (sv->sv_sigcode_base != 0) {
kst32.ksigtramp_start = sv->sv_sigcode_base;
kst32.ksigtramp_end = sv->sv_sigcode_base +
- *sv->sv_szsigcode;
+ ((sv->sv_flags & SV_DSO_SIG) == 0 ?
+ *sv->sv_szsigcode :
+ (uintptr_t)sv->sv_szsigcode);
} else {
kst32.ksigtramp_start = sv->sv_psstrings -
*sv->sv_szsigcode;
@@ -3116,7 +3118,8 @@
if (sv->sv_sigcode_base != 0) {
kst.ksigtramp_start = (char *)sv->sv_sigcode_base;
kst.ksigtramp_end = (char *)sv->sv_sigcode_base +
- *sv->sv_szsigcode;
+ ((sv->sv_flags & SV_DSO_SIG) == 0 ? *sv->sv_szsigcode :
+ (uintptr_t)sv->sv_szsigcode);
} else {
kst.ksigtramp_start = (char *)sv->sv_psstrings -
*sv->sv_szsigcode;
diff --git a/sys/kern/kern_sharedpage.c b/sys/kern/kern_sharedpage.c
--- a/sys/kern/kern_sharedpage.c
+++ b/sys/kern/kern_sharedpage.c
@@ -305,10 +305,12 @@
exec_sysvec_init(void *param)
{
struct sysentvec *sv;
+ vm_offset_t sb;
#ifdef RANDOM_FENESTRASX
ptrdiff_t base;
#endif
u_int flags;
+ int res;
sv = param;
flags = sv->sv_flags;
@@ -319,8 +321,21 @@
sv->sv_shared_page_obj = shared_page_obj;
if ((flags & SV_ABI_MASK) == SV_ABI_FREEBSD) {
- sv->sv_sigcode_base = sv->sv_shared_page_base +
- shared_page_fill(*(sv->sv_szsigcode), 16, sv->sv_sigcode);
+ if ((flags & SV_DSO_SIG) != 0) {
+ sb = sv->sv_shared_page_base;
+ res = shared_page_fill((uintptr_t)sv->sv_szsigcode,
+ 16, sv->sv_sigcode);
+ if (res == -1)
+ panic("copying sigtramp to shared page");
+ sb += res;
+ sv->sv_vdso_base = sb;
+ sb += sv->sv_sigcodeoff;
+ sv->sv_sigcode_base = sb;
+ } else {
+ sv->sv_sigcode_base = sv->sv_shared_page_base +
+ shared_page_fill(*(sv->sv_szsigcode), 16,
+ sv->sv_sigcode);
+ }
}
if ((flags & SV_TIMEKEEP) != 0) {
#ifdef COMPAT_FREEBSD32
@@ -372,12 +387,18 @@
MPASS((sv2->sv_flags & SV_ABI_MASK) == (sv->sv_flags & SV_ABI_MASK));
MPASS((sv2->sv_flags & SV_TIMEKEEP) == (sv->sv_flags & SV_TIMEKEEP));
MPASS((sv2->sv_flags & SV_SHP) != 0 && (sv->sv_flags & SV_SHP) != 0);
+ MPASS((sv2->sv_flags & SV_DSO_SIG) != 0 &&
+ (sv->sv_flags & SV_DSO_SIG) != 0);
MPASS((sv2->sv_flags & SV_RNG_SEED_VER) ==
(sv->sv_flags & SV_RNG_SEED_VER));
sv2->sv_shared_page_obj = sv->sv_shared_page_obj;
sv2->sv_sigcode_base = sv2->sv_shared_page_base +
(sv->sv_sigcode_base - sv->sv_shared_page_base);
+ if ((sv2->sv_flags & SV_DSO_SIG) != 0) {
+ sv2->sv_vdso_base = sv2->sv_shared_page_base +
+ (sv->sv_vdso_base - sv->sv_shared_page_base);
+ }
if ((sv2->sv_flags & SV_ABI_MASK) != SV_ABI_FREEBSD)
return;
if ((sv2->sv_flags & SV_TIMEKEEP) != 0) {
diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h
--- a/sys/sys/elf_common.h
+++ b/sys/sys/elf_common.h
@@ -981,8 +981,9 @@
#define AT_ENVV 31 /* Environment vector */
#define AT_PS_STRINGS 32 /* struct ps_strings */
#define AT_FXRNG 33 /* Pointer to root RNG seed version. */
+#define AT_KPRELOAD 34
-#define AT_COUNT 34 /* Count of defined aux entry types. */
+#define AT_COUNT 35 /* Count of defined aux entry types. */
/*
* Relocation types.
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -109,8 +109,9 @@
/* stack fixup function */
void (*sv_sendsig)(void (*)(int), struct ksiginfo *, struct __sigset *);
/* send signal */
- char *sv_sigcode; /* start of sigtramp code */
+ const char *sv_sigcode; /* start of sigtramp code */
int *sv_szsigcode; /* size of sigtramp code */
+ int sv_sigcodeoff;
char *sv_name; /* name of binary type */
int (*sv_coredump)(struct thread *, struct vnode *, off_t, int);
/* function to dump core, or NULL */
@@ -143,6 +144,7 @@
vm_offset_t sv_shared_page_len;
vm_offset_t sv_sigcode_base;
void *sv_shared_page_obj;
+ vm_offset_t sv_vdso_base;
void (*sv_schedtail)(struct thread *);
void (*sv_thread_detach)(struct thread *);
int (*sv_trap)(struct thread *);
@@ -171,6 +173,7 @@
#define SV_RNG_SEED_VER 0x100000 /* random(4) reseed generation. */
#define SV_SIG_DISCIGN 0x200000 /* Do not discard ignored signals */
#define SV_SIG_WAITNDQ 0x400000 /* Wait does not dequeue SIGCHLD */
+#define SV_DSO_SIG 0x800000 /* Signal trampoline packed in dso */
#define SV_ABI_MASK 0xff
#define SV_PROC_FLAG(p, x) ((p)->p_sysent->sv_flags & (x))
diff --git a/sys/tools/amd64_ia32_vdso.sh b/sys/tools/amd64_ia32_vdso.sh
new file mode 100644
--- /dev/null
+++ b/sys/tools/amd64_ia32_vdso.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+set -e
+
+${CC} -x assembler-with-cpp -DLOCORE -fPIC -nostdinc -c -m32 \
+ -o ia32_sigtramp.pico -I. -I${S} -include opt_global.h \
+ ${S}/amd64/ia32/ia32_sigtramp.S
+
+${LD} --shared -Bsymbolic -soname="elf-vdso32.so.1" \
+ -T ${S}/conf/vdso_amd64_ia32.ldscript \
+ --eh-frame-hdr --no-undefined -z rodynamic -z norelro -nmagic \
+ --hash-style=sysv --fatal-warnings --strip-all \
+ -o elf-vdso32.so.1 ia32_sigtramp.pico
+
+${OBJCOPY} --input-target binary \
+ --output-target elf64-x86-64 --binary-architecture i386:x86-64 \
+ elf-vdso32.so.1 elf-vdso32.so.o
+
+${NM} -D elf-vdso32.so.1 | awk \
+ '/__vdso_ia32_sigcode/{printf "#define VDSO_IA32_SIGCODE_OFFSET 0x%s\n",$1}
+ /__vdso_freebsd4_ia32_sigcode/{printf "#define VDSO_FREEBSD4_IA32_SIGCODE_OFFSET 0x%s\n",$1}
+ /__vdso_ia32_osigcode/{printf "#define VDSO_IA32_OSIGCODE_OFFSET 0x%s\n",$1}
+ /__vdso_lcall_tramp/{printf "#define VDSO_LCALL_TRAMP_OFFSET 0x%s\n",$1}' \
+ >vdso_ia32_offsets.h
diff --git a/sys/tools/amd64_vdso.sh b/sys/tools/amd64_vdso.sh
new file mode 100644
--- /dev/null
+++ b/sys/tools/amd64_vdso.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -e
+
+${CC} -x assembler-with-cpp -DLOCORE -fPIC -nostdinc -c \
+ -o sigtramp.pico -I. -I${S} -include opt_global.h \
+ ${S}/amd64/amd64/sigtramp.S
+
+# We need to make vdso as compact as possible, for it to leave space
+# for other things in the shared page. For this, we pack everything
+# into single loadable segment.
+#
+# -z rodynamic is undocumented lld-specific option, seemingly required
+# for lld to avoid putting dynamic into dedicated writeable segment,
+# despite ldscript placement. It is ignored by ld.bfd but ldscript
+# alone is enough there.
+${LD} --shared -Bsymbolic -soname="elf-vdso.so.1" \
+ -T ${S}/conf/vdso_amd64.ldscript \
+ --eh-frame-hdr --no-undefined -z rodynamic -z norelro -nmagic \
+ --hash-style=sysv --fatal-warnings --strip-all \
+ -o elf-vdso.so.1 sigtramp.pico
+
+${OBJCOPY} --input-target binary \
+ --output-target elf64-x86-64 --binary-architecture i386:x86-64 \
+ elf-vdso.so.1 elf-vdso.so.o
+
+${NM} -D elf-vdso.so.1 | \
+ awk '/__vdso_sigcode/{printf "#define VDSO_SIGCODE_OFFSET 0x%s\n",$1}' \
+ >vdso_offsets.h
diff --git a/usr.bin/procstat/procstat_auxv.c b/usr.bin/procstat/procstat_auxv.c
--- a/usr.bin/procstat/procstat_auxv.c
+++ b/usr.bin/procstat/procstat_auxv.c
@@ -239,6 +239,12 @@
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_FXRNG/%p}\n",
prefix, "AT_FXRNG", auxv[i].a_un.a_ptr);
break;
+#endif
+#ifdef AT_KPRELOAD
+ case AT_KPRELOAD:
+ xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_KPRELOAD/%p}\n",
+ prefix, "AT_KPRELOAD", auxv[i].a_un.a_ptr);
+ break;
#endif
default:
xo_emit("{dw:/%s}{Lw:/%16ld/%ld}{:UNKNOWN/%#lx}\n",
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Dec 20, 11:18 PM (14 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15536333
Default Alt Text
D32960.id98552.diff (32 KB)
Attached To
Mode
D32960: Wrap signal trampoline into vdso
Attached
Detach File
Event Timeline
Log In to Comment