summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2007-12-04 12:33:03 +0000
committerkib <kib@FreeBSD.org>2007-12-04 12:33:03 +0000
commit3e8ae081b2b44f99199487d0c40c3bf32e22fd14 (patch)
treeaea956d1d43fb99bb7f3a157f35c56a65ec5cc87
parentfeb2aba5b692eb1c9cb8275d405791736ea1067e (diff)
downloadFreeBSD-src-3e8ae081b2b44f99199487d0c40c3bf32e22fd14.zip
FreeBSD-src-3e8ae081b2b44f99199487d0c40c3bf32e22fd14.tar.gz
Fix the ABI change of the signal delivered on the access to the page
with insufficient protection mode. For the i386 and amd64, create the tunable, machdep.prot_fault_translation, with the following behaviour: 0 = autodetect the signal to be delivered on KERN_PROTECTION_FAILURE from vm_fault based on the ELF OSABI note: no note or __FreeBSD_version < 700004 - SIGBUS/BUS_PAGE_FAULT note, and __FreeBSD_version >= 700004 - SIGSEGV/SEGV_ACCERR 1 = always SIGBUS/BUS_PAGE_FAULT 2 = always SIGSEGV/SEGV_ACCERR This would do mostly automatic correction of ABI breakage, with the exception of the untaged binaries for 7-CURRENT/RELENG_7 before the note is fixed. For them, sysctl would allow to run the binary with manual settings. Discussed with: portmgr (kris) PR: kern/118304 MFC after: 3 days
-rw-r--r--sys/amd64/amd64/trap.c31
-rw-r--r--sys/i386/i386/trap.c31
2 files changed, 58 insertions, 4 deletions
diff --git a/sys/amd64/amd64/trap.c b/sys/amd64/amd64/trap.c
index 2ce8ed4..7e95cbc 100644
--- a/sys/amd64/amd64/trap.c
+++ b/sys/amd64/amd64/trap.c
@@ -144,6 +144,9 @@ SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RW,
static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
+static int prot_fault_translation = 0;
+SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
+ &prot_fault_translation, 0, "Select signal to deliver on protection fault");
extern char *syscallnames[];
@@ -312,8 +315,32 @@ trap(struct trapframe *frame)
if (i == SIGSEGV)
ucode = SEGV_MAPERR;
else {
- i = SIGSEGV; /* XXX hack */
- ucode = SEGV_ACCERR;
+ if (prot_fault_translation == 0) {
+ /*
+ * Autodetect.
+ * This check also covers the images
+ * without the ABI-tag ELF note.
+ */
+ if (p->p_osrel >= 700004) {
+ i = SIGSEGV;
+ ucode = SEGV_ACCERR;
+ } else {
+ i = SIGBUS;
+ ucode = BUS_PAGE_FAULT;
+ }
+ } else if (prot_fault_translation == 1) {
+ /*
+ * Always compat mode.
+ */
+ i = SIGBUS;
+ ucode = BUS_PAGE_FAULT;
+ } else {
+ /*
+ * Always SIGSEGV mode.
+ */
+ i = SIGSEGV;
+ ucode = SEGV_ACCERR;
+ }
}
break;
diff --git a/sys/i386/i386/trap.c b/sys/i386/i386/trap.c
index 637dedb..ebec7ab 100644
--- a/sys/i386/i386/trap.c
+++ b/sys/i386/i386/trap.c
@@ -158,6 +158,9 @@ SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RW,
static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI");
+static int prot_fault_translation = 0;
+SYSCTL_INT(_machdep, OID_AUTO, prot_fault_translation, CTLFLAG_RW,
+ &prot_fault_translation, 0, "Select signal to deliver on protection fault");
extern char *syscallnames[];
@@ -375,8 +378,32 @@ trap(struct trapframe *frame)
if (i == SIGSEGV)
ucode = SEGV_MAPERR;
else {
- i = SIGSEGV; /* XXX hack */
- ucode = SEGV_ACCERR;
+ if (prot_fault_translation == 0) {
+ /*
+ * Autodetect.
+ * This check also covers the images
+ * without the ABI-tag ELF note.
+ */
+ if (p->p_osrel >= 700004) {
+ i = SIGSEGV;
+ ucode = SEGV_ACCERR;
+ } else {
+ i = SIGBUS;
+ ucode = BUS_PAGE_FAULT;
+ }
+ } else if (prot_fault_translation == 1) {
+ /*
+ * Always compat mode.
+ */
+ i = SIGBUS;
+ ucode = BUS_PAGE_FAULT;
+ } else {
+ /*
+ * Always SIGSEGV mode.
+ */
+ i = SIGSEGV;
+ ucode = SEGV_ACCERR;
+ }
}
addr = eva;
break;
OpenPOWER on IntegriCloud