diff options
author | kib <kib@FreeBSD.org> | 2007-12-04 12:33:03 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2007-12-04 12:33:03 +0000 |
commit | 3e8ae081b2b44f99199487d0c40c3bf32e22fd14 (patch) | |
tree | aea956d1d43fb99bb7f3a157f35c56a65ec5cc87 | |
parent | feb2aba5b692eb1c9cb8275d405791736ea1067e (diff) | |
download | FreeBSD-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.c | 31 | ||||
-rw-r--r-- | sys/i386/i386/trap.c | 31 |
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; |