Saturday, July 18, 2015

New syscalls for armv8-64 kernel

I decided to use a different target platform for my project. Initially, I was using Android Kitkat + Galaxy Nexus (ARMv7 + TI OMAP 4460). To obtain best performance with some crypto operations, I am now using Android Lollipop + Nexus 9 (ARMv8 64bits). I did some tests with basic OpenSSL examples (for example, AES-128 and SHA1) and the numbers are impressive.

The goal of this post is to document some problems that I had building the Android image and its respective kernel. You might think that I am being redundant, as you [might] have the same issues with a traditional Linux kernel. I've done this only for Android platform, so I don't know for other kernels. I'm also having some other problems, such as ARMv8-64 asm file compilation inside the kernel, but this will be described in another poster.

Basically, in my project, I have to create new syscalls and also change the sys_call_table to intercept existing ones, such as NR_write, NR_open, etc. You can check another post that describes how to create new syscalls and how to intercept existing syscalls. So, what is different?

1. Some syscalls have changed, some have been created and some others are not supported anymore. 


 __NR_open, __NR_link, __NR_chmod, __NR_rename, ... are not supported anymore. Instead, you should use __NR_openat, __NR_mkdirat, ...

For example, check the syscalls under the #def body __ARCH_WANT_SYSCALL_DEPRECATED and __ARCH_WANT_SYSCALL_NO_AT (file include/uapi/asm-generic/unistd.h)

In addition, the syscall number has also been changed. For example, NR_write changed from 3 to 63. Remember to change your code in userpsace that has any reference to one of these numbers.

2. Much easier than before: now, you only need to change less files. Add the definition of your syscalls in the following files:


include/linux/syscalls.h

 ...
 asmlinkage long sys_seccomp(unsigned int op, unsigned int flags,
                            const char __user *uargs);

 asmlinkage long sys_my_syscall(void __user *buf);
 ...

include/uapi/asm-generic/unistd.h

 ...
 #define __NR_seccomp 277
 __SYSCALL(__NR_seccomp, sys_seccomp)

 #define __NR_my_syscall 278
 __SYSCALL(__NR_my_syscall, sys_my_syscall)

 #undef __NR_syscalls
 #define __NR_syscalls 279
 ...

kernel/my_syscall_code.c (this file should contain the implementation of your syscall)

kernel/Makefile

 obj-y = ....
 ...
         async.o range.o groups.o lglock.o smpboot.o \
         my_syscall_code.o
 ...

3. Don't forget to add asm/unistd.h as part of your head files.


4. Kernel modules are implemented the same way as before. To build it, remember to set cflags properly


There's just a small change on building the module. Call make with CFLAGS_MODULE=-fno-pic

5. And of course, the syscall table address table has changed as well. 


Check the symbol sys_call_table in the file System.map.

As said, I am having other problems with it. In my case, I want to add some assembly files into my module and compile them all together. The point is that they are written in a specific format that GCC does not understand, but clang. So, things would be solved if I could use clang to build my module, but it doesn't work like that :-( Let's what comes next!

EDIT (31/07/2015) : this is a good guide for 32 bits -> 64 bits porting