diff options
Diffstat (limited to 'libexec/ld.so/sparc')
-rw-r--r-- | libexec/ld.so/sparc/ldasm.S | 20 | ||||
-rw-r--r-- | libexec/ld.so/sparc/rtld_machine.c | 65 | ||||
-rw-r--r-- | libexec/ld.so/sparc/syscall.h | 4 |
3 files changed, 86 insertions, 3 deletions
diff --git a/libexec/ld.so/sparc/ldasm.S b/libexec/ld.so/sparc/ldasm.S index 9b3ff9fb81f..c7a3cf5f86c 100644 --- a/libexec/ld.so/sparc/ldasm.S +++ b/libexec/ld.so/sparc/ldasm.S @@ -1,4 +1,4 @@ -/* $OpenBSD: ldasm.S,v 1.9 2002/11/23 19:50:45 drahn Exp $ */ +/* $OpenBSD: ldasm.S,v 1.10 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 2001 Jason L. Wright (jason@thought.net) @@ -292,6 +292,24 @@ _dl_sysctl: retl sub %g0, %o0, %o0 ! error: result = -errno + + /* _dl_sigprocmask does not support NULL new mask */ + .section ".text" + .align 4 + .globl _dl_sigprocmask + .type _dl_sigprocmask,@function +_dl_sigprocmask: + ld [%o1], %o1 + mov SYS_sigprocmask, %g1 ! call sys___sigprocmask + t ST_SYSCALL ! off to wonderland + + cmp %o2, 0 + bne,a 1f + st %o0, [%o2] +1: + retl + clr %o0 + /* * V8 sparc .{,u}{mul,div,rem} replacements. * We try to mimic them 100%. Full 64 bit sources or outputs, and diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c index 73ccd4ffc3b..48c16f7fe98 100644 --- a/libexec/ld.so/sparc/rtld_machine.c +++ b/libexec/ld.so/sparc/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.10 2002/11/23 19:14:25 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.11 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -44,6 +44,7 @@ #include <nlist.h> #include <link.h> +#include <signal.h> #include "syscall.h" #include "archdep.h" @@ -335,6 +336,7 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) const char *symn; Elf_Addr value; Elf_RelA *rela; + sigset_t omask, nmask; rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff); @@ -353,8 +355,33 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) value = ooff + this->st_value; + /* if PLT is protected, allow the write */ + if (object->plt_addr != NULL && object->plt_size != 0) { + sigfillset(&nmask); + _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); +#if 0 + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_WRITE|PROT_EXEC); +#else + _dl_mprotect((void*)addr,sizeof (Elf_Addr) * 3, + PROT_READ|PROT_WRITE|PROT_EXEC); +#endif + } + _dl_reloc_plt(addr, value); + /* if PLT is (to be protected, change back to RO/X */ + if (object->plt_addr != NULL && object->plt_size != 0) { +#if 0 + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_EXEC); +#else + _dl_mprotect((void*)addr,sizeof (Elf_Addr) * 3, + PROT_READ|PROT_EXEC); +#endif + _dl_sigprocmask(SIG_SETMASK, &omask, NULL); + } + return (value); } @@ -363,6 +390,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) { Elf_Addr *pltgot; extern void _dl_bind_start(void); /* XXX */ + Elf_Addr ooff; + const Elf_Sym *this; pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; @@ -393,11 +422,45 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) __asm __volatile("nop;nop;nop;nop;nop"); } + this = NULL; + ooff = _dl_find_symbol("__got_start", object, &this, + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, + NULL); + if (this != NULL) + object->got_addr = ooff + this->st_value; + + this = NULL; + ooff = _dl_find_symbol("__got_end", object, &this, + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, + NULL); + if (this != NULL) + object->got_size = ooff + this->st_value - object->got_addr; + + this = NULL; + ooff = _dl_find_symbol("__plt_start", object, &this, + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, + NULL); + if (this != NULL) + object->plt_addr = ooff + this->st_value; + + this = NULL; + ooff = _dl_find_symbol("__plt_end", object, &this, + SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, + NULL); + if (this != NULL) + object->plt_size = ooff + this->st_value - object->plt_addr; + if (object->obj_type == OBJTYPE_LDR || !lazy || pltgot == NULL) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); return; } + if (object->got_addr != NULL && object->got_size != 0) + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ); + if (object->plt_addr != NULL && object->plt_size != 0) + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_EXEC); } diff --git a/libexec/ld.so/sparc/syscall.h b/libexec/ld.so/sparc/syscall.h index c11613b6120..ac19f7fb0ca 100644 --- a/libexec/ld.so/sparc/syscall.h +++ b/libexec/ld.so/sparc/syscall.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.2 2002/11/23 19:14:25 drahn Exp $ */ +/* $OpenBSD: syscall.h,v 1.3 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 2001 Niklas Hallqvist @@ -37,6 +37,7 @@ #include <sys/syscall.h> #include <sys/stat.h> +#include <sys/signal.h> #ifndef _dl_MAX_ERRNO #define _dl_MAX_ERRNO 4096 @@ -59,6 +60,7 @@ int _dl_fcntl(int, int, ...); int _dl_getdirentries(int, char*, int, long *); int _dl_sysctl(int *, u_int, void *, size_t *, void *, size_t); +int _dl_sigprocmask(int, const sigset_t *, sigset_t *); static inline off_t _dl_lseek(int fildes, off_t offset, int whence) |