From d24031dd0cd7426670045968bda8cc501303cd0f Mon Sep 17 00:00:00 2001 From: Konstantin Belousov Date: Tue, 4 Dec 2007 12:33:03 +0000 Subject: [PATCH] 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 --- sys/amd64/amd64/trap.c | 31 +++++++++++++++++++++++++++++-- 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 2ce8ed48d350..7e95cbc5728c 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 637dedb17b9d..ebec7ab10ca4 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;