Adding a new syscall to Linux 3.10 for ARM64

Post date: Sep 24, 2016 6:38:4 PM

Today I learned to add a new syscall to the Linux kernel of my Nexus 6P.

I looked at other guides such as this guide by Shane Tully, but I could not find the syscall table for ARM64 in the kernel. Turns out the syscall table for ARM64 is shared between other architectures, and is located in include/uapi/asm-generic/unistd.h. Yay.

After adding my new syscall to the table, I added a declaration for it in include/linux/syscalls.h so other code can find it, and finally added an implementation for it in kernel/sys.c.

I wanted my syscall to give me root access and to disable SELinux. For root access, I did some research and found that most root exploits uses the pair of calls

commit_creds(prepare_kernel_cred(0));

to gain root, so I used the same. For disabling SELinux, I looked at the existing permissive mode SELinux code in security/selinux/selinuxfs.c and copied it over to my syscall.

Then, I followed the official AOSP instructions to build the kernel. Finally, I used bbootimg to replace the stock kernel with the new Image.gz-dtb file I built.

After rebooting with the new kernel, running the backdoor syscall made the process root and disabled SELinux, as planned. Success!

The patch can be found in this gist.