Re: mprotect with PROT_NONE throws SIGBUS, not SIGSEGV
Re: mprotect with PROT_NONE throws SIGBUS, not SIGSEGV
- Subject: Re: mprotect with PROT_NONE throws SIGBUS, not SIGSEGV
- From: Steven Bytnar <email@hidden>
- Date: Tue, 1 Apr 2003 09:59:33 -0600
- Mail-followup-to: Andre Pang <email@hidden>, email@hidden
On Tue, Apr 01, 2003 at 11:05:19PM +1000, Andre Pang wrote:
>
I have feeling that the following diff to xnu-10 is a start to solving
>
the problem, and may even be sufficient:
>
>
--- ./bsd/uxkern/ux_exception.c.old Tue Apr 1 22:52:52 2003
>
+++ ./bsd/uxkern/ux_exception.c Tue Apr 1 22:53:39 2003
>
@@ -277,7 +277,8 @@
>
switch(exception) {
>
>
case EXC_BAD_ACCESS:
>
- if (code == KERN_INVALID_ADDRESS)
>
+ if (code == KERN_INVALID_ADDRESS ||
>
+ code == KERN_PROTECTION_FAILURE)
>
*ux_signal = SIGSEGV;
>
else
>
*ux_signal = SIGBUS;
>
>
However, I can't actually test this because I'm running Mac OS X
>
10.2.4, and the 10.2.4 kernel (xnu-344.26) isn't up on the Apple CVS
>
servers yet :(.
You could always do a binary patch to your kernel! B)
Let's convert some constants to their values:
./osfmk/mach/kern_return.h:#define KERN_INVALID_ADDRESS 1
./osfmk/mach/kern_return.h:#define KERN_PROTECTION_FAILURE 2
./osfmk/mach/exception_types.h:#define EXC_BAD_ACCESS 1
./bsd/sys/signal.h:#define SIGSEGV 11 /* segmentation violation */
./bsd/sys/signal.h:#define SIGBUS 10 /* bus error */
otool -vVt /mach_kernel | less
# search for "ux_exception"
You'll find this code segment in the MacOS X 10.2.4 /mach_kernel.
_ux_exception:
0020ca0c mfspr r0,lr
0020ca10 stmw r29,0xfff4(r1)
0020ca14 stw r0,0x8(r1)
0020ca18 or r30,r4,r4
0020ca1c stwu r1,0xffb0(r1)
0020ca20 or r31,r3,r3
0020ca24 or r29,r6,r6
0020ca28 bl _machine_exception
0020ca2c cmpwi r3,__framesize
0020ca30 bne 0x20cb10
0020ca34 cmplwi r31,0x6
0020ca38 bgt 0x20cb10
0020ca3c lis r9,0x21
// get offset in jump table.
0020ca40 rlwinm r11,r31,2,0,29
0020ca44 addi r9,r9,0xca58
0020ca48 lwzx r0,r11,r9
0020ca4c add r0,r0,r9
0020ca50 mtspr ctr,r0
0020ca54 bctr
// jump table
0020ca58 .long 0x000000b8 //28CA58+B8=28CB10 (case EXC_BAD_ACCESS)
0020ca5c .long 0x0000001c //28CA58+1C=28CB74 (case EXC_BAD_INST...)
0020ca60 .long 0x00000030
0020ca64 .long 0x00000038
0020ca68 .long 0x00000040
0020ca6c .long 0x00000048
0020ca70 .long 0x000000b0
// compare r30 to KERN_INVALID_ADDRESS
0020ca74 cmpwi r30,0x1
// if (r30 == KERN_INVALID_ADDRESS) return SIGBUS
0020ca78 li r0,0xb
0020ca7c beq 0x20cb0c
// if (r30 != KERN_INVALID_ADDRESS) return SIGSEGV
0020ca80 li r0,0xa
0020ca84 b 0x20cb0c
0020ca88 li r0,0x4
0020ca8c b 0x20cb0c
0020ca90 li r0,0x8
0020ca94 b 0x20cb0c
0020ca98 li r0,0x7
0020ca9c b 0x20cb0c
0020caa0 lis r0,0x1
0020caa4 ori r0,r0,0x1
0020caa8 cmpw r30,r0
0020caac beq 0x20caf0
0020cab0 bgt 0x20cac4
0020cab4 lis r0,0x1
0020cab8 cmpw r30,r0
0020cabc beq 0x20cae8
0020cac0 b 0x20cb10
0020cac4 lis r0,0x1
0020cac8 ori r0,r0,0x2
0020cacc cmpw r30,r0
0020cad0 beq 0x20caf8
0020cad4 lis r0,0x1
0020cad8 ori r0,r0,0x3
0020cadc cmpw r30,r0
0020cae0 beq 0x20cb00
0020cae4 b 0x20cb10
0020cae8 li r0,0xc
0020caec b 0x20cb0c
0020caf0 li r0,0xd
0020caf4 b 0x20cb0c
0020caf8 li r0,0x6
0020cafc b 0x20cb0c
0020cb00 li r0,0x9
0020cb04 b 0x20cb0c
0020cb08 li r0,kLog2CacheLineSize
0020cb0c stw r0,__framesize(r29)
0020cb10 lwz r0,0x58(r1)
0020cb14 addi r1,r1,0x50
0020cb18 lmw r29,0xfff4(r1)
0020cb1c mtspr lr,r0
0020cb20 blr
We could make this patch:
echo << EOF > x.s
; replacement for code starting at 0020ca74
cmpwi r30,0x2 ; if <= 2
li r0,0xb ; SIGSEGV (if <= 2)
ble 0x1b0c
li r0,0xa ; SIGBUS (if > 2)
b 0x1b0c
EOF
[jsg3-10:~] sbytnar% cc -c -o x.o x.s
[jsg3-10:~] sbytnar% otool -vVt x.o
x.o:
(__TEXT,__text) section
00000000 cmpwi r30,0x2
00000004 li r0,0xb
00000008 ble 0x1b0c
0000000c li r0,0xa
00000010 b 0x1b0c
[jsg3-10:~] sbytnar% hexdump x.o
0000000 feed face 0000 0012 0000 0000 0000 0001
0000010 0000 0001 0000 007c 0000 0000 0000 0001
0000020 0000 007c 0000 0000 0000 0000 0000 0000
0000030 0000 0000 0000 0000 0000 0014 0000 0098
0000040 0000 0014 0000 0007 0000 0007 0000 0001
0000050 0000 0000 5f5f 7465 7874 0000 0000 0000
0000060 0000 0000 5f5f 5445 5854 0000 0000 0000
0000070 0000 0000 0000 0000 0000 0014 0000 0098
0000080 0000 0000 0000 00ac 0000 0002 8000 0400
0000090 0000 0000 0000 0000 2c1e 0002 3800 000b
00000a0 4081 1b04 3800 000a 4800 1afc 0000 0010
00000b0 0000 00c3 0000 0008 0000 00c2
00000bc
That looks like PowerPC code starting at offset 0x98.
It looks like our constants are visible in the opcodes.
Interestingly enough, offset 0x3C points to this, so
it must be it.
2c1e0002 // cmpwi
3800000b // li...
4081xxxx // insert appropriate offset from original
3800000a // li...
4800xxxx // insert appropriate offset from original
This binary patch assumes that it's ok to return SIGSEGV for
code == KERN_SUCCESS, when before, it would return SIGBUS.
I'll leave it as an excercise for the reader to find the actual offset
in the /mach_kernel binary and to do the hex editing. :)
I'm not sure if there are any checksums or date-checking by the
kernel loader/linker, so binary patching may or maynot work. Does
anyone recall offhand if Mach-O/BootX has either of those features?
Enjoy,
--Steve
_______________________________________________
darwin-kernel mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/darwin-kernel
Do not post admin requests to the list. They will be ignored.