Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F162208287
D32960.id98410.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D32960.id98410.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
@@ -124,6 +124,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 *);
@@ -825,6 +826,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();
@@ -2836,6 +2843,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)
{
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/amd64/vdso.ldscript b/sys/amd64/amd64/vdso.ldscript
new file mode 100644
--- /dev/null
+++ b/sys/amd64/amd64/vdso.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/files.amd64 b/sys/conf/files.amd64
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -12,6 +12,12 @@
# 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_offset.h 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 +82,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
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_vdso.sh b/sys/tools/amd64_vdso.sh
new file mode 100644
--- /dev/null
+++ b/sys/tools/amd64_vdso.sh
@@ -0,0 +1,15 @@
+#!/bin/sh
+set -e
+${CC} -x assembler-with-cpp -DLOCORE -fPIC -nostdinc -c \
+ -o sigtramp.pico -I. -I${S} \
+ ${S}/amd64/amd64/sigtramp.S
+${LD} --shared -Bsymbolic -soname="elf-vdso.so.1" \
+ --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
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jul 11, 10:12 PM (20 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34975917
Default Alt Text
D32960.id98410.diff (16 KB)
Attached To
Mode
D32960: Wrap signal trampoline into vdso
Attached
Detach File
Event Timeline
Log In to Comment