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
This commit is contained in:
Konstantin Belousov 2007-12-04 12:33:03 +00:00
parent f231de478e
commit d24031dd0c
2 changed files with 58 additions and 4 deletions

View File

@ -144,6 +144,9 @@ SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RW,
static int panic_on_nmi = 1; static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW, SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI"); &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[]; extern char *syscallnames[];
@ -312,8 +315,32 @@ trap(struct trapframe *frame)
if (i == SIGSEGV) if (i == SIGSEGV)
ucode = SEGV_MAPERR; ucode = SEGV_MAPERR;
else { else {
i = SIGSEGV; /* XXX hack */ if (prot_fault_translation == 0) {
ucode = SEGV_ACCERR; /*
* 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; break;

View File

@ -158,6 +158,9 @@ SYSCTL_INT(_machdep, OID_AUTO, kdb_on_nmi, CTLFLAG_RW,
static int panic_on_nmi = 1; static int panic_on_nmi = 1;
SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW, SYSCTL_INT(_machdep, OID_AUTO, panic_on_nmi, CTLFLAG_RW,
&panic_on_nmi, 0, "Panic on NMI"); &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[]; extern char *syscallnames[];
@ -375,8 +378,32 @@ trap(struct trapframe *frame)
if (i == SIGSEGV) if (i == SIGSEGV)
ucode = SEGV_MAPERR; ucode = SEGV_MAPERR;
else { else {
i = SIGSEGV; /* XXX hack */ if (prot_fault_translation == 0) {
ucode = SEGV_ACCERR; /*
* 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; addr = eva;
break; break;