summaryrefslogtreecommitdiff
path: root/libexec/ld.so
diff options
context:
space:
mode:
Diffstat (limited to 'libexec/ld.so')
-rw-r--r--libexec/ld.so/alpha/ldasm.S15
-rw-r--r--libexec/ld.so/alpha/rtld_machine.c57
-rw-r--r--libexec/ld.so/alpha/syscall.h4
-rw-r--r--libexec/ld.so/i386/ldasm.S27
-rw-r--r--libexec/ld.so/i386/rtld_machine.c56
-rw-r--r--libexec/ld.so/i386/syscall.h4
-rw-r--r--libexec/ld.so/mips/rtld_machine.c39
-rw-r--r--libexec/ld.so/powerpc/rtld_machine.c54
-rw-r--r--libexec/ld.so/powerpc/syscall.h28
-rw-r--r--libexec/ld.so/resolve.h6
-rw-r--r--libexec/ld.so/sparc/ldasm.S20
-rw-r--r--libexec/ld.so/sparc/rtld_machine.c65
-rw-r--r--libexec/ld.so/sparc/syscall.h4
-rw-r--r--libexec/ld.so/sparc64/ldasm.S20
-rw-r--r--libexec/ld.so/sparc64/rtld_machine.c56
-rw-r--r--libexec/ld.so/sparc64/syscall.h4
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)