Felis
Felis

Reputation: 11

My syscall cause segmentation fault (core dumped)

I'm writing a simple syscall based on this tutorial, and boot into the new kernel with my syscall in it, but when I compile a test, and execute it, it cause segmentation fault (core dumped). My my_syscall.h (hello.c equivalent in the tutorial) looks like this.

#include <linux/module.h> 
#include <linux/kernel.h> 
#include <linux/sched.h>  
#include <asm/current.h>

struct smallStruct {
    int integer;
    char str[20];
};

struct bigStruct {
    long id;
    struct smallStruct a;
    struct smallStruct b;
    struct smallStruct c;
};

asmlinkage long test_syscall(int pid, struct bigStruct *info)
{
    info->id = pid;

    info->a.integer = 0;
    info->a.str[0] = 'A';
    info->a.str[1] = '\0';

    info->b.integer = 1;
    info->b.str[0] = 'B';
    info->b.str[1] = '\0';

    info->c.integer = 2;
    info->c.str[0] = 'C';
    info->c.str[1] = '\0';

    return 0;
}

I actually try to write a syscall that get some information and store back into *info, and I need the str in the smallStruct, but everytime I try to modify the str, it cause segmentation fault (core dumped), and when I remove those modification to the str to temporarily avoid core dump, it still doesn't work as I expected. This is what my test file looks like:

#include <sys/syscall.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

struct smallStruct
{
    int integer;
    char str[20];
};

struct bigStruct
{
    long id;
    struct smallStruct a;
    struct smallStruct b;
    struct smallStruct c;
};

int main()
{
    long sys_return_value;
    struct bigStruct info;
    sys_return_value = syscall(548, 1, &info);
    printf("id = %ld, return %ld\n", info.id, sys_return_value);
    return 0;
}

It seems that the info in my test isn't modified by the syscall at all. I even use printk in the my_syscall.h and the pid I pass to my syscall isn't correct at all. this is what the printk print in dmesg

this is what the <code>printk</code> print in <code>dmesg</code>

The id in my_syscall is supposed to be the pid, and it is passed in my test with the value of 1. (syscall(548, 1, &info);)

I know it is quite long, but I would be grateful if anyone can explain what is wrong with my implement, Thank you.

Upvotes: 1

Views: 803

Answers (1)

ichaudry
ichaudry

Reputation: 17

You are passing a user pointer that is part of the part of the process stack to the kernel. This is bad practice and will never work because kernel memory and user memory are separate entities. You need to use System Apis to pass pointer to and from user to kernel memory. Look at copy_to_user and copy_from_user functions. You can also put ioctl method into use which creates a backdoor between user/application and kernel

Upvotes: 1

Related Questions