diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2003-02-15 22:39:15 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2003-02-15 22:39:15 +0000 |
commit | 6c34c2c4c127669edb0ec50693e3493ce3c5f154 (patch) | |
tree | 9fa80d528987c0ea03eb3220d5863de82a608201 | |
parent | 6cc8ca737f0cac9a74ff9c9ad770326f1dd10663 (diff) |
Paranoia about mprotect, mprotect page aligned regions for got and plt.
-rw-r--r-- | libexec/ld.so/alpha/rtld_machine.c | 36 | ||||
-rw-r--r-- | libexec/ld.so/i386/rtld_machine.c | 36 | ||||
-rw-r--r-- | libexec/ld.so/powerpc/rtld_machine.c | 52 | ||||
-rw-r--r-- | libexec/ld.so/resolve.h | 8 | ||||
-rw-r--r-- | libexec/ld.so/sparc/rtld_machine.c | 36 | ||||
-rw-r--r-- | libexec/ld.so/sparc64/rtld_machine.c | 40 |
6 files changed, 146 insertions, 62 deletions
diff --git a/libexec/ld.so/alpha/rtld_machine.c b/libexec/ld.so/alpha/rtld_machine.c index e9c67279577..41eeb010bdb 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.20 2003/01/17 20:41:07 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.21 2003/02/15 22:39:13 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -208,7 +208,7 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) *((int *)0) = 0; /* XXX */ } /* if PLT is protected, allow the write */ - if (object->plt_addr != NULL && object->plt_size != 0) { + if (object->plt_size != 0) { sigfillset(&nmask); _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); _dl_mprotect(addr, sizeof(Elf_Addr), @@ -218,7 +218,7 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) *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) { + if (object->plt_size != 0) { _dl_mprotect(addr, sizeof(Elf_Addr), PROT_READ|PROT_EXEC); _dl_sigprocmask(SIG_SETMASK, &omask, NULL); @@ -236,11 +236,14 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) Elf_Addr *pltgot; extern void _dl_bind_start(void); /* XXX */ Elf_Addr ooff; + Elf_Addr plt_addr; const Elf_Sym *this; pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; + object->got_addr = NULL; + object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, @@ -255,19 +258,38 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; + plt_addr = NULL; + object->plt_size = 0; 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; + 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; + object->plt_size = ooff + this->st_value - plt_addr; + + if (object->got_addr == NULL) + object->got_start = NULL; + else { + object->got_start = ELF_TRUNC(object->got_addr, _dl_pagesz); + object->got_size += object->got_addr - object->got_start; + object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); + } + if (plt_addr == NULL) + object->plt_start = NULL; + else { + object->plt_start = ELF_TRUNC(plt_addr, _dl_pagesz); + object->plt_size += plt_addr - object->plt_start; + object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz); + } + + if (object->obj_type == OBJTYPE_LDR || !lazy || pltgot == NULL) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); @@ -293,8 +315,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) 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, + if (object->got_size != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_EXEC); } diff --git a/libexec/ld.so/i386/rtld_machine.c b/libexec/ld.so/i386/rtld_machine.c index 750bb2f4c1b..241e47faccc 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.7 2003/02/02 16:57:58 deraadt Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.8 2003/02/15 22:39:13 drahn Exp $ */ /* * Copyright (c) 2002 Dale Rahn @@ -380,18 +380,18 @@ _dl_bind(elf_object_t *object, int index) } /* if GOT is protected, allow the write */ - if (object->got_addr != NULL && object->got_size != 0) { + if (object->got_size != 0) { sigfillset(&nmask); _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); - _dl_mprotect((void*)object->got_addr, object->got_size, + _dl_mprotect((void*)object->got_start, 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, + if (object->got_size != 0) { + _dl_mprotect((void*)object->got_start, object->got_size, PROT_READ); _dl_sigprocmask(SIG_SETMASK, &omask, NULL); } @@ -419,6 +419,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (object->Dyn.info[DT_PLTREL] != DT_REL) return; + object->got_addr = NULL; + object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, @@ -433,19 +435,13 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) 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->got_addr == NULL) + object->got_start = NULL; + else { + object->got_start = ELF_TRUNC(object->got_addr, _dl_pagesz); + object->got_size += object->got_addr - object->got_start; + object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); + } if (!lazy) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); @@ -471,7 +467,7 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) } /* 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, + if (object->got_size != 0) + _dl_mprotect((void*)object->got_start, object->got_size, PROT_READ); } diff --git a/libexec/ld.so/powerpc/rtld_machine.c b/libexec/ld.so/powerpc/rtld_machine.c index 8c5b1e89535..2a040336a6d 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.23 2003/02/15 00:30:16 drahn Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.24 2003/02/15 22:39:13 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -448,9 +448,10 @@ _dl_printf(" found other symbol at %x size %d\n", void _dl_md_reloc_got(elf_object_t *object, int lazy) { - Elf32_Addr *pltresolve; - Elf32_Addr *first_rela; - Elf32_Rela *relas; + Elf_Addr *pltresolve; + Elf_Addr *first_rela; + Elf_RelA *relas; + Elf_Addr plt_addr; int numrela; int i; int index; @@ -461,6 +462,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (object->Dyn.info[DT_PLTREL] != DT_RELA) return; + object->got_addr = NULL; + object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, @@ -475,20 +478,38 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; + plt_addr = 0; + object->plt_size = 0; 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; + 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; - + object->plt_size = ooff + this->st_value - plt_addr; + + if (object->got_addr == NULL) + object->got_start = NULL; + else { + object->got_start = ELF_TRUNC(object->got_addr, _dl_pagesz); + object->got_size += object->got_addr - object->got_start; + object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); + } + if (plt_addr == NULL) + object->plt_start = NULL; + else { + object->plt_start = ELF_TRUNC(plt_addr, _dl_pagesz); + object->plt_size += plt_addr - object->plt_start; + object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz); + } + + if (!lazy) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); return; @@ -518,13 +539,14 @@ _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, + if (object->got_size != 0) { + + _dl_mprotect((void*)object->got_start, object->got_size, PROT_READ|PROT_EXEC); /* only PPC is PROT_EXE */ _dl_syncicache((void*)object->got_addr, 4); } - if (object->plt_addr != NULL && object->plt_size != 0) - _dl_mprotect((void*)object->plt_addr, object->plt_size, + if (object->plt_size != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_EXEC); } @@ -560,10 +582,10 @@ _dl_bind(elf_object_t *object, int reloff) } /* if PLT is protected, allow the write */ - if (object->plt_addr != NULL && object->plt_size != 0) { + if (object->plt_size != 0) { sigfillset(&nmask); _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); - _dl_mprotect((void*)object->plt_addr, object->plt_size, + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_WRITE|PROT_EXEC); } @@ -611,8 +633,8 @@ _dl_bind(elf_object_t *object, int reloff) } /* 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, + if (object->plt_size != 0) { + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_EXEC); /* only PPC is PROT_EXE */ _dl_sigprocmask(SIG_SETMASK, &omask, NULL); } diff --git a/libexec/ld.so/resolve.h b/libexec/ld.so/resolve.h index 752e721363d..f67290f00e9 100644 --- a/libexec/ld.so/resolve.h +++ b/libexec/ld.so/resolve.h @@ -1,4 +1,4 @@ -/* $OpenBSD: resolve.h,v 1.21 2003/02/02 16:57:58 deraadt Exp $ */ +/* $OpenBSD: resolve.h,v 1.22 2003/02/15 22:39:13 drahn Exp $ */ /* * Copyright (c) 1998 Per Fogelstrom, Opsycon AB @@ -62,8 +62,9 @@ typedef struct elf_object { u_int32_t load_size; Elf_Addr got_addr; + Elf_Addr got_start; size_t got_size; - Elf_Addr plt_addr; + Elf_Addr plt_start; size_t plt_size; union { @@ -198,4 +199,7 @@ extern char *_dl_debug; #define DL_INVALID_HANDLE 7 #define DL_INVALID_CTL 8 +#define ELF_ROUND(x,malign) (((x) + (malign)-1) & ~((malign)-1)) +#define ELF_TRUNC(x,malign) ((x) & ~((malign)-1)) + #endif /* _RESOLVE_H_ */ diff --git a/libexec/ld.so/sparc/rtld_machine.c b/libexec/ld.so/sparc/rtld_machine.c index 96349dba377..cc567f6218b 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.13 2003/02/02 16:57:58 deraadt Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.14 2003/02/15 22:39:13 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -356,7 +356,7 @@ _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) { + if (object->plt_size != 0) { sigfillset(&nmask); _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); /* mprotect the actual modified region, not the whole plt */ @@ -367,7 +367,7 @@ _dl_bind(elf_object_t *object, Elf_Word reloff) _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 (object->plt_size != 0) { /* mprotect the actual modified region, not the whole plt */ _dl_mprotect((void*)addr,sizeof (Elf_Addr) * 3, PROT_READ|PROT_EXEC); @@ -384,6 +384,7 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) extern void _dl_bind_start(void); /* XXX */ Elf_Addr ooff; const Elf_Sym *this; + Elf_Addr plt_addr; pltgot = (Elf_Addr *)object->Dyn.info[DT_PLTGOT]; @@ -414,6 +415,8 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) __asm __volatile("nop;nop;nop;nop;nop"); } + object->got_addr = NULL; + object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, @@ -428,30 +431,47 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; + plt_addr = 0; + object->plt_size = 0; 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; + 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; + object->plt_size = ooff + this->st_value - plt_addr; + + if (object->got_addr == NULL) + object->got_start = NULL; + else { + object->got_start = ELF_TRUNC(object->got_addr, _dl_pagesz); + object->got_size += object->got_addr - object->got_start; + object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); + } + if (plt_addr == NULL) + object->plt_start = NULL; + else { + object->plt_start = ELF_TRUNC(plt_addr, _dl_pagesz); + object->plt_size += plt_addr - object->plt_start; + object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz); + } 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) + if (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, + if (object->plt_size != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_EXEC); } diff --git a/libexec/ld.so/sparc64/rtld_machine.c b/libexec/ld.so/sparc64/rtld_machine.c index cddca12dc09..95c9c339435 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.24 2003/02/02 16:57:58 deraadt Exp $ */ +/* $OpenBSD: rtld_machine.c,v 1.25 2003/02/15 22:39:14 drahn Exp $ */ /* * Copyright (c) 1999 Dale Rahn @@ -644,18 +644,18 @@ _dl_bind(elf_object_t *object, int index) } /* if PLT is protected, allow the write */ - if (object->plt_addr != NULL && object->plt_size != 0) { + if (object->plt_size != 0) { sigfillset(&nmask); _dl_sigprocmask(SIG_BLOCK, &nmask, &omask); - _dl_mprotect((void*)object->plt_addr, object->plt_size, + _dl_mprotect((void*)object->plt_start, 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, + if (object->plt_size != 0) { + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_EXEC); _dl_sigprocmask(SIG_SETMASK, &omask, NULL); } @@ -700,11 +700,14 @@ _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; + Elf_Addr plt_addr; const Elf_Sym *this; if (object->Dyn.info[DT_PLTREL] != DT_RELA) return; + object->got_addr = NULL; + object->got_size = 0; this = NULL; ooff = _dl_find_symbol("__got_start", object, &this, SYM_SEARCH_SELF|SYM_NOWARNNOTFOUND|SYM_PLT, SYM_NOTPLT, @@ -719,19 +722,36 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) if (this != NULL) object->got_size = ooff + this->st_value - object->got_addr; + plt_addr = 0; + object->plt_size = 0; 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; + 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; + object->plt_size = ooff + this->st_value - plt_addr; + + if (object->got_addr == NULL) + object->got_start = NULL; + else { + object->got_start = ELF_TRUNC(object->got_addr, _dl_pagesz); + object->got_size += object->got_addr - object->got_start; + object->got_size = ELF_ROUND(object->got_size, _dl_pagesz); + } + if (plt_addr == NULL) + object->plt_start = NULL; + else { + object->plt_start = ELF_TRUNC(plt_addr, _dl_pagesz); + object->plt_size += plt_addr - object->plt_start; + object->plt_size = ELF_ROUND(object->plt_size, _dl_pagesz); + } if (!lazy) { _dl_md_reloc(object, DT_JMPREL, DT_PLTRELSZ); @@ -743,10 +763,10 @@ _dl_md_reloc_got(elf_object_t *object, int lazy) pltgot[8] = (Elf_Addr)object; - if (object->got_addr != NULL && object->got_size != 0) + if (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, + if (object->plt_size != 0) + _dl_mprotect((void*)object->plt_start, object->plt_size, PROT_READ|PROT_EXEC); } |