Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F105727639
D32960.id98494.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
27 KB
Referenced Files
None
Subscribers
None
D32960.id98494.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,73 @@
return (NULL);
}
+static int
+load_kpreload(const void *addr)
+{
+ Obj_Entry *obj;
+ const Elf_Ehdr *ehdr;
+ const Elf_Phdr *phdr, *phlimit, *phdyn, *seg0, *segn;
+ Elf_Addr phdr_vaddr;
+ 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;
+ phdr_vaddr = (Elf_Addr)phdr;
+ 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 = (const Elf_Phdr *)(obj->relocbase + phdr_vaddr);
+ 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 +6177,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/sigtramp.S b/sys/amd64/amd64/sigtramp.S
--- a/sys/amd64/amd64/sigtramp.S
+++ b/sys/amd64/amd64/sigtramp.S
@@ -38,7 +38,7 @@
* Signal trampoline, copied to top of user stack
*
*/
-ENTRY(sigcode)
+ENTRY(__vdso_sigcode)
call *SIGF_HANDLER(%rsp) /* call signal handler */
lea SIGF_UC(%rsp),%rdi /* get ucontext_t */
pushq $0 /* junk to fake return addr. */
@@ -46,11 +46,6 @@
syscall /* enter kernel with args */
0: hlt /* trap priviliged instruction */
jmp 0b
+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
@@ -38,8 +38,8 @@
* XXX may need to be MD to match backend sendsig handoff protocol
*/
ALIGN_TEXT
- .globl ia32_sigcode
-ia32_sigcode:
+ .globl __vdso_ia32_sigcode
+__vdso_ia32_sigcode:
calll *IA32_SIGF_HANDLER(%esp)
leal IA32_SIGF_UC(%esp),%eax /* get ucontext */
pushl %eax
@@ -52,7 +52,8 @@
#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 +67,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,11 +92,14 @@
* vfork() and harder for other syscalls.
*/
ALIGN_TEXT
-lcall_tramp:
+ .globl __vdso_lcall_tramp
+__vdso_lcall_tramp:
int $0x80
1: jmp 1b
#endif
+#if 0
+
ALIGN_TEXT
esigcode:
@@ -115,3 +120,6 @@
sz_lcall_tramp:
.long esigcode-lcall_tramp
#endif
+
+#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_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
@@ -233,6 +233,18 @@
xo_emit("{dw:/%s}{Lw:/%-16s/%s}{:AT_PS_STRINGS/%p}\n",
prefix, "AT_PS_STRINGS", auxv[i].a_un.a_ptr);
break;
+#endif
+#ifdef AT_FXRNG
+ case AT_FXRNG:
+ 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, 6:51 PM (10 h, 3 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15534017
Default Alt Text
D32960.id98494.diff (27 KB)
Attached To
Mode
D32960: Wrap signal trampoline into vdso
Attached
Detach File
Event Timeline
Log In to Comment