sinkmanu
sinkmanu

Reputation: 1102

Perform a syscall in a kernel module

I am beginning to develop a kernel module with inline assembly, I am trying to perform the write syscall in order to write in a file. It is compiling well (in addition, in a C program works correctly), but when I load the module It drop a segmentation fault and when I look in the diagnostic message (dmesg) i see the following:

[  672.687568] BUG: stack guard page was hit at ffffb8a601d13fa8 (stack is ffffb8a601d14000..ffffb8a601d17fff)
[  672.687577] kernel stack overflow (double-fault): 0000 [#1] SMP
...
[  672.777032]  [<ffffffffa50fda16>] ? SYSC_finit_module+0xc6/0xf0
[  672.777396]  [<ffffffffa55ebebb>] ? system_call_fast_compare_end+0xc/0x9b
[  672.777765] Code: 48 89 e7 48 8b 74 24 78 48 c7 44 24 78 ff ff ff ff e8 28 09 a7 ff e9 53 02 00 00 0f 1f 00 0f 1f 00 66 0f 1f 44 00 00 48 83 c4 88 <e8> 7e 01 00 00 48 89 e7 48 8b 74 24 78 48 c7 44 24 78 ff ff ff 
[  672.779059] RIP  [<ffffffffa55ed27d>] page_fault+0xd/0x30
[  672.779481]  RSP <ffffb8a601d13fb8>
[  672.779901] fbcon_switch: detected unhandled fb_set_par error, error code -16

The code of the kernel module is the following:

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");
int example_init(void);
void example_exit(void);
module_init(example_init);
module_exit(example_exit);


int example_init(void) {
    char *file = "/root/test2";
    char *msg = "AAAAAA\n";

    asm( "mov eax, 0x2;"
        "mov rdi, %0;" 
        "mov rsi, 0x441;"
        "xor rdx, rdx;"
        "syscall;"
        "mov rdi, rax;"
        "mov eax, 0x1;"
        "mov rsi, %1;"
        "mov rdx, 7;"
        "syscall;"
        "mov eax, 0x3;"
        "syscall;"
        : "=m" (file), "=m" (msg)
    );
        printk("Example: module loaded.\n");
        return 0;
}

void example_exit(void) {
       printk("Example: module removed\n");
}

I know that the failure is in the syscall instruction because I tried without syscall instruction and the assembly code works correctly and just does a segmentation fault when syscall is launched.

Upvotes: 0

Views: 1481

Answers (1)

Tsyvarev
Tsyvarev

Reputation: 65888

As noted by @RossRidge in the comments, Linux kernel is not designed for syscalls being used from the kernel code. So syscall instruction shouldn't be used in the kernel code.

Some functionality obtained by syscalls has in-kernel alternative. E.g, for open a file in the kernel one may use filp_open, and for writing a file - vfs_write. See that question for more information about using files in the kernel code.

Upvotes: 1

Related Questions