I wrote a hook for the execve
system call and in the beginning when I wrote it to print "hi"
, each time that a file is executed. It worked fine, but when I tried to print the filename
that is passed to the system call this resulted in a crash and of course I had to restart my computer.
This is my code:
static asmlinkage long our_execl(const char __user * filename,
const char __user * const __user * argv,
const char __user * const __user * envp) {
printk("%s\n",filename);
return original_execl(filename, argv, envp);
}
This is how I inject the new syscall:
static int lkm_example_init(void)
{
printk("new new new 2");
write_cr0(read_cr0()&(~ 0x10000));
sys_call_table = (void*)0xdd8c4240//the syscall address from the /proc/kallsyms ;
execl= sys_call_table[__NR_execve];
sys_call_table[__NR_execve]=our_execl;
write_cr0(read_cr0() | 0X10000);
return 0;
}
What is most likely happening here is that SMAP (Supervisor Mode Access Prevention) is preventing the kernel from accessing a raw user space pointer, causing a panic.
The correct way to access a string from user space is to copy its content using strncpy_from_user()
first. Also, be careful and make sure to correctly terminate the string.
static asmlinkage long our_execl(const char __user * filename,
const char __user * const __user * argv,
const char __user * const __user * envp) {
char buf[256];
buf[255] = '\0';
long res = strncpy_from_user(buf, filename, 255);
if (res > 0)
printk("%s\n", buf);
return original_execl(filename, argv, envp);
}
In this case, since we are specifically talking about a file name, depending on the kernel version you may be able to use the getname()
and putname()
from linux/fs.h
(if they are exported in the kernel version you are working with). These work using a struct filename
.
static asmlinkage long our_execl(const char __user * filename,
const char __user * const __user * argv,
const char __user * const __user * envp) {
struct filename *fname = getname(filename);
if (!IS_ERR(fname)) {
printk("%s\n", fname->name);
putname(fname);
}
return original_execl(filename, argv, envp);
}