diff options
Diffstat (limited to 'libexec/ld.so')
-rw-r--r-- | libexec/ld.so/alpha/ldasm.S | 15 | ||||
-rw-r--r-- | libexec/ld.so/alpha/rtld_machine.c | 57 | ||||
-rw-r--r-- | libexec/ld.so/alpha/syscall.h | 4 | ||||
-rw-r--r-- | libexec/ld.so/i386/ldasm.S | 27 | ||||
-rw-r--r-- | libexec/ld.so/i386/rtld_machine.c | 56 | ||||
-rw-r--r-- | libexec/ld.so/i386/syscall.h | 4 | ||||
-rw-r--r-- | libexec/ld.so/mips/rtld_machine.c | 39 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/rtld_machine.c | 54 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/syscall.h | 28 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 6 | ||||
-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 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/ldasm.S | 20 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/rtld_machine.c | 56 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/syscall.h | 4 |
16 files changed, 443 insertions, 16 deletions
diff --git a/libexec/ld.so/alpha/ldasm.S b/libexec/ld.so/alpha/ldasm.S index 68659b6e05e..c6917ff2e26 100644 --- a/libexec/ld.so/alpha/ldasm.S +++ b/libexec/ld.so/alpha/ldasm.S @@ -1,4 +1,4 @@ -/* $OpenBSD: ldasm.S,v 1.10 2002/10/21 16:01:55 drahn Exp $ */ +/* $OpenBSD: ldasm.S,v 1.11 2002/12/18 19:20:01 drahn Exp $ */ /* * Copyright (c) 2001 Niklas Hallqvist @@ -290,3 +290,16 @@ LEAF_NOPROFILE(_dl_getdirentries, 4) call_pal PAL_OSF1_callsys RET END(_dl_getdirentries) + +/* _dl_sigprocmask does not support NULL new mask */ +LEAF_NOPROFILE(_dl_sigprocmask, 4) + mov a2, a5 + ldl a1, 0(a1) /* load the set from *set */ + ldiq v0, SYS_sigprocmask + call_pal PAL_OSF1_callsys + /* What about syscalls failing? */ + beq a5, 1f + stl v0, 0(a5) +1: mov zero, v0 + RET +END(_dl_sigprocmask) diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c index 0c10637104d..cde1b9e0b5a 100644 --- a/libexec/ld.so/alpha/rtld_machine.c +++ b/libexec/ld.so/alpha/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.17 2002/11/14 15:15:54 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.18 2002/12/18 19:20:01 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" @@ -189,6 +190,7 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) Elf_Addr *addr, ooff; const Elf_Sym *sym, *this; const char *symn; + sigset_t omask, nmask; rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL] + reloff); @@ -205,7 +207,23 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) _dl_printf("lazy binding failed!\n"); *((int *)0) = 0; /* XXX */ } + /* if PLT is protected, allow the write */ + if (object->plt_addr != NULL && object->plt_size != 0) { + sigfillset(&nmask); + _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); + _dl_mprotect(addr, sizeof(Elf_Addr), + PROT_READ|PROT_WRITE|PROT_EXEC); + } + *addr = ooff + this->st_value + rela->r_addend; + + /* if PLT is (to be protected, change back to RO/X */ + if (object->plt_addr != NULL && object->plt_size != 0) { + _dl_mprotect(addr, sizeof(Elf_Addr), + PROT_READ|PROT_EXEC); + _dl_sigprocmask(SIG_SETMASK, &omask, NULL); + } + return (void *)*addr; } @@ -217,9 +235,40 @@ _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]; + 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; @@ -241,4 +290,10 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) pltgot[2] = (Elf_Addr)_dl_bind_start; pltgot[3] = (Elf_Addr)object; + if (object->got_addr != NULL && object->got_size != 0) + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ|PROT_EXEC); + if (object->plt_addr != NULL && object->got_size != 0) + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_EXEC); } diff --git a/libexec/ld.so/alpha/syscall.h b/libexec/ld.so/alpha/syscall.h index 6c65a0b9f81..11d2c9692f3 100644 --- a/libexec/ld.so/alpha/syscall.h +++ b/libexec/ld.so/alpha/syscall.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.9 2002/07/24 04:11:10 deraadt Exp $ */ +/* $OpenBSD: syscall.h,v 1.10 2002/12/18 19:20:01 drahn Exp $ */ /* * Copyright (c) 2001 Niklas Hallqvist @@ -36,6 +36,7 @@ #include <sys/stat.h> #include <sys/syscall.h> +#include <sys/signal.h> #ifndef _dl_MAX_ERRNO #define _dl_MAX_ERRNO 4096 @@ -57,6 +58,7 @@ int _dl_fstat(int, struct stat *); int _dl_fcntl(int, int, ...); int _dl_getdirentries(int, char*, int, long *); long _dl__syscall(quad_t, ...); +int _dl_sigprocmask(int, const sigset_t *, sigset_t *); static inline off_t _dl_lseek(int fildes, off_t offset, int whence) diff --git a/libexec/ld.so/i386/ldasm.S b/libexec/ld.so/i386/ldasm.S index b7af2be3792..c3ff47b5234 100644 --- a/libexec/ld.so/i386/ldasm.S +++ b/libexec/ld.so/i386/ldasm.S @@ -1,4 +1,4 @@ -/* $OpenBSD: ldasm.S,v 1.2 2002/10/21 16:01:55 drahn Exp $ */ +/* $OpenBSD: ldasm.S,v 1.3 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -227,6 +227,31 @@ _dl_getdirentries: ret + /* _dl_sigprocmask: does not handle NULL new set */ + + .section ".text" + .align 4 + .global _dl_sigprocmask + .type _dl_sigprocmask,@function +_dl_sigprocmask: + movl 8(%esp), %ecx + movl (%ecx),%ecx + movl %ecx,8(%esp) # to new mask arg + mov $SYS_sigprocmask, %eax + int $0x80 + jb 1f /* error: result = -errno */ + movl 12(%esp),%ecx # fetch old mask requested + testl %ecx,%ecx # test if old mask requested + jz 2f + movl %eax,(%ecx) # store old mask + xorl %eax,%eax +2: ret + +1: /* error: result = -errno; - handled here. */ + neg %eax + ret + + .align 4 .global _dl_bind_start .type _dl_bind_start,@function diff --git a/libexec/ld.so/i386/rtld_machine.c b/libexec/ld.so/i386/rtld_machine.c index 5495e42749b..e8ce94c1927 100644 --- a/libexec/ld.so/i386/rtld_machine.c +++ b/libexec/ld.so/i386/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.5 2002/11/23 06:04:13 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.6 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -77,6 +77,7 @@ #include <nlist.h> #include <link.h> +#include <signal.h> #include "syscall.h" #include "archdep.h" @@ -332,6 +333,7 @@ resolve_failed: return (fails); } +#if 0 struct jmpslot { u_short opcode; u_short addr[2]; @@ -339,6 +341,7 @@ struct jmpslot { #define JMPSLOT_RELOC_MASK 0xffff }; #define JUMP 0xe990 /* NOP + JMP opcode */ +#endif void _dl_reloc_plt(Elf_Addr *where, Elf_Addr value) @@ -357,6 +360,7 @@ _dl_bind(elf_object_t *object, int index) const Elf_Sym *sym, *this; const char *symn; Elf_Addr ooff; + sigset_t omask, nmask; rel = (Elf_Rel *)(object->Dyn.info[DT_JMPREL]); @@ -375,8 +379,23 @@ _dl_bind(elf_object_t *object, int index) *((int *)0) = 0; /* XXX */ } + /* if GOT is protected, allow the write */ + if (object->got_addr != NULL && object->got_size != 0) { + sigfillset(&nmask); + _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ|PROT_WRITE); + } + _dl_reloc_plt(addr, ooff + this->st_value); + /* put the GOT back to RO */ + if (object->got_addr != NULL && object->got_size != 0) { + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ); + _dl_sigprocmask(SIG_SETMASK, &omask, NULL); + } + return((Elf_Addr)ooff + this->st_value); } @@ -388,6 +407,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) int i, num; Elf_Rel *rel; struct load_list *llist; + Elf_Addr ooff; + const Elf_Sym *this; if (pltgot == NULL) return; /* it is possible to have no PLT/GOT relocations */ @@ -398,6 +419,34 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (object->Dyn.info[DT_PLTREL] != DT_REL) return; + 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 (!lazy) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); return; @@ -420,4 +469,9 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) _dl_mprotect(llist->start, llist->size, llist->prot); } + + /* PLT is already RO on i386, no point in mprotecting it, just GOT */ + if (object->got_addr != NULL && object->got_size != 0) + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ); } diff --git a/libexec/ld.so/i386/syscall.h b/libexec/ld.so/i386/syscall.h index c9719118dd1..f853ad4cb6c 100644 --- a/libexec/ld.so/i386/syscall.h +++ b/libexec/ld.so/i386/syscall.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.1 2002/08/23 23:02:48 drahn Exp $ */ +/* $OpenBSD: syscall.h,v 1.2 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 @@ -57,6 +58,7 @@ int _dl_write(int, const char*, int); int _dl_fstat(int, struct stat *); int _dl_fcntl(int, int, ...); int _dl_getdirentries(int, char*, int, long *); +int _dl_sigprocmask(int, const sigset_t *, sigset_t *); static inline off_t _dl_lseek(int fildes, off_t offset, int whence) diff --git a/libexec/ld.so/mips/rtld_machine.c b/libexec/ld.so/mips/rtld_machine.c index b58e689e7fa..45467e3b9cf 100644 --- a/libexec/ld.so/mips/rtld_machine.c +++ b/libexec/ld.so/mips/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.9 2002/11/14 15:15:54 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.10 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 1998-2002 Opsycon AB, Sweden. @@ -129,6 +129,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) const Elf32_Sym *symp; const Elf32_Sym *this; const char *strt; + Elf_Addr ooff; + const Elf_Sym *this; if (object->status & STAT_GOT_DONE) return; @@ -159,6 +161,34 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) n = object->Dyn.info[DT_MIPS_SYMTABNO - DT_LOPROC + DT_NUM] - object->Dyn.info[DT_MIPS_GOTSYM - DT_LOPROC + DT_NUM]; + 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; + /* * Then do all global references according to the ABI. * Quickstart is not yet implemented. @@ -195,4 +225,11 @@ DL_DEB(("got: '%s' = %x\n", strt + symp->st_name, symp->st_value)); symp++; } object->status |= STAT_GOT_DONE; + + 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/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c index ac6cb26fa93..5e44c314f04 100644 --- a/libexec/ld.so/powerpc/rtld_machine.c +++ b/libexec/ld.so/powerpc/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.18 2002/11/22 22:21:23 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.19 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -39,6 +39,7 @@ #include <nlist.h> #include <link.h> +#include <signal.h> #include "syscall.h" #include "archdep.h" @@ -450,10 +451,40 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) int i; int index; Elf32_Addr *r_addr; + Elf_Addr ooff; + const Elf_Sym *this; if (object->Dyn.info[DT_PLTREL] != DT_RELA) return; + 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 (!lazy) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); return; @@ -483,6 +514,12 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) _dl_dcbf(&r_addr[0]); _dl_dcbf(&r_addr[2]); } + if (object->got_addr != NULL && object->got_size != 0) + _dl_mprotect((void*)object->got_addr, object->got_size, + PROT_READ|PROT_EXEC); /* only PPC is PROT_EXE */ + if (object->plt_addr != NULL && object->plt_size != 0) + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_EXEC); } Elf_Addr @@ -498,6 +535,7 @@ _dl_bind(elf_object_t *object, int reloff) Elf32_Addr *pltcall; Elf32_Addr *pltinfo; Elf32_Addr *plttable; + sigset_t omask, nmask; relas = ((Elf_RelA *)object->Dyn.info[DT_JMPREL]) + (reloff>>2); @@ -515,6 +553,14 @@ _dl_bind(elf_object_t *object, int reloff) *((int *)0) = 0; /* XXX */ } + /* if PLT is protected, allow the write */ + if (object->plt_addr != NULL && object->plt_size != 0) { + sigfillset(&nmask); + _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_WRITE|PROT_EXEC); + } + value = ooff + this->st_value; val = value - (Elf32_Addr)r_addr; @@ -558,6 +604,12 @@ _dl_bind(elf_object_t *object, int reloff) _dl_dcbf(&r_addr[0]); } + /* if PLT is (to be protected, change back to RO/X */ + if (object->plt_addr != NULL && object->plt_size != 0) { + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_EXEC); /* only PPC is PROT_EXE */ + _dl_sigprocmask(SIG_SETMASK, &omask, NULL); + } return (value); } diff --git a/libexec/ld.so/powerpc/syscall.h b/libexec/ld.so/powerpc/syscall.h index 55bcb55b36f..92de932f7f5 100644 --- a/libexec/ld.so/powerpc/syscall.h +++ b/libexec/ld.so/powerpc/syscall.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.13 2002/07/24 04:11:10 deraadt Exp $ */ +/* $OpenBSD: syscall.h,v 1.14 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -37,6 +37,7 @@ #include <sys/stat.h> #include <sys/syscall.h> +#include <sys/signal.h> static off_t _dl_lseek(int, off_t, int); @@ -306,4 +307,29 @@ _dl_lseek(int fildes, off_t offset, int whence) { return _dl__syscall((quad_t)SYS_lseek, fildes, 0, offset, whence); } + +static inline int +_dl_sigprocmask (int how, const sigset_t *set, sigset_t *oset) +{ + sigset_t sig_store; + sigset_t sig_store1; + if (set != NULL) { + sig_store1 = *set; + } else { + sig_store1 = 0; + } + + __asm__ volatile ("li 0,%1\n\t" + "mr 3,%2\n\t" + "mr 4,%3\n\t" + "sc\n\t" + "mr %0, 3" + : "=r" (sig_store) + : "I" (SYS_sigprocmask), "r" (how), "r" (sig_store1) + : "0", "3", "4"); + if (oset != NULL) + *oset = sig_store; + + return 0; +} #endif /*__DL_SYSCALL_H__*/ diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 8e0060698d3..52a99e303c9 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.18 2002/11/14 15:15:54 drahn Exp $ */ +/* $OpenBSD: resolve.h,v 1.19 2002/12/18 19:20:01 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -61,6 +61,10 @@ typedef struct elf_object { struct load_list *load_list; u_int32_t load_size; + Elf_Addr got_addr; + size_t got_size; + Elf_Addr plt_addr; + size_t plt_size; union { u_long info[DT_NUM + DT_PROCNUM]; 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) diff --git a/libexec/ld.so/sparc64/ldasm.S b/libexec/ld.so/sparc64/ldasm.S index 574f065c1ea..2391fbe1b40 100644 --- a/libexec/ld.so/sparc64/ldasm.S +++ b/libexec/ld.so/sparc64/ldasm.S @@ -1,4 +1,4 @@ -/* $OpenBSD: ldasm.S,v 1.15 2002/11/23 06:19:26 drahn Exp $ */ +/* $OpenBSD: ldasm.S,v 1.16 2002/12/18 19:20:02 drahn Exp $ */ /* $NetBSD: rtld_start.S,v 1.5 2001/08/14 22:17:48 eeh Exp $ */ /* @@ -366,3 +366,21 @@ _dl_getdirentries: t ST_SYSCALL ! off to wonderland 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 ! indirect for new mask + mov SYS_sigprocmask, %g1 ! call sys_sigprocmask + t ST_SYSCALL ! off to wonderland + ! what about errors? + cmp %o2, 0 + bne,a 1f ! if oset != NULL + st %o0, [%o2] ! *oset = oldmask +1: + retl + clr %o0 diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c index d44c20888a2..a46e471b300 100644 --- a/libexec/ld.so/sparc64/rtld_machine.c +++ b/libexec/ld.so/sparc64/rtld_machine.c @@ -1,4 +1,4 @@ -/* $OpenBSD: rtld_machine.c,v 1.22 2002/11/14 15:15:54 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.23 2002/12/18 19:20:02 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -77,6 +77,7 @@ #include <nlist.h> #include <link.h> +#include <signal.h> #include "syscall.h" #include "archdep.h" @@ -602,6 +603,7 @@ _dl_bind(elf_object_t *object, int index) Elf_Addr ooff; const Elf_Sym *sym, *this; const char *symn; + sigset_t omask, nmask; rela = (Elf_RelA *)(object->Dyn.info[DT_JMPREL]); if (ELF_R_TYPE(rela->r_info) == R_TYPE(JMP_SLOT)) { @@ -641,8 +643,23 @@ _dl_bind(elf_object_t *object, int index) *((int *)0) = 0; /* XXX */ } + /* if PLT is protected, allow the write */ + if (object->plt_addr != NULL && object->plt_size != 0) { + sigfillset(&nmask); + _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_WRITE|PROT_EXEC); + } + _dl_reloc_plt(addr, ooff + this->st_value, rela); + /* if PLT is (to be protected), change back to RO/X */ + if (object->plt_addr != NULL && object->plt_size != 0) { + _dl_mprotect((void*)object->plt_addr, object->plt_size, + PROT_READ|PROT_EXEC); + _dl_sigprocmask(SIG_SETMASK, &omask, NULL); + } + return (void *)ooff + this->st_value; } @@ -682,10 +699,40 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) { Elf_Addr *pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; Elf_Word *entry = (Elf_Word *)pltgot; + Elf_Addr ooff; + const Elf_Sym *this; if (object->Dyn.info[DT_PLTREL] != DT_RELA) return; + 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 (!lazy) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); return; @@ -695,4 +742,11 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) _dl_install_plt(&entry[8], (Elf_Addr)&_dl_bind_start_1); pltgot[8] = (Elf_Addr)object; + + 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/sparc64/syscall.h b/libexec/ld.so/sparc64/syscall.h index 2370348b169..cd39a0550c7 100644 --- a/libexec/ld.so/sparc64/syscall.h +++ b/libexec/ld.so/sparc64/syscall.h @@ -1,4 +1,4 @@ -/* $OpenBSD: syscall.h,v 1.10 2002/07/24 04:11:10 deraadt Exp $ */ +/* $OpenBSD: syscall.h,v 1.11 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 @@ -57,6 +58,7 @@ ssize_t _dl_write(int, const char*, size_t); int _dl_fstat(int, struct stat *); int _dl_fcntl(int, int, ...); int _dl_getdirentries(int, char*, int, long *); +int _dl_sigprocmask(int, const sigset_t *, sigset_t *); static inline off_t _dl_lseek(int fildes, off_t offset, int whence) |