3

For a homework assignment, I have to modify the linux kernel.

I am working on a virtual machine, and I added a system call to the kernel, which I called get_unique_id. Here is the code for get_unique_id.c :

#include <linux/linkage.h>
#include <asm/uaccess.h>

asmlinkage long sys_get_unique_id(int * uuid)
{
    // static because we want its state to persist between calls
    static int uid = 0;

    ++uid;

    // assign new uid value to user-provided mem location
    // returns non-zero if success or -EFAULT otherwise
    int ret = put_user(uid, uuid);
    return ret;
}

I also added this line to syscalls.h :

asmlinkage long sys_get_unique_id(int * uuid);

This line to syscall_32.tbl :

383 i386    get_unique_id       sys_get_unique_id

And finally this line to syscall_64.tbl :

548 common  get_unique_id       sys_get_unique_id

After recompiling and reloading the kernel, I wrote a little C program to test my system call, here is the code for the C test file :

// get_unique_id_test.c
#include <stdio.h>
#include <limits.h>

#include "syscalls_test.h"

int main(void)
{
    // initialize the ints we want
    int id1;
    int id2;

    // check the id's are unique and that no error occured
    for (int i = INT_MIN; i < INT_MAX - 1; i += 2) {
        long ret1 = get_unique_id(&id1);
        long ret2 = get_unique_id(&id2);

        if (ret1 != 0)
            printf("ERROR: get_unique_id returned: %ld\n", ret1);

        if (ret2 != 0)
            printf("ERROR: get_unique_id returned: %ld\n", ret2);

        if (id2 != id1 + 1)
            printf("ERROR: successive id's did not increment properly: id1 = %d, id2 = %d\n", id1, id2);
    }

    return 0;
}

And its header file :

// syscalls_test.h
#include <errno.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

#define __NR_get_unique_id 383

inline long get_unique_id(int * uuid)
{
    return syscall(__NR_get_unique_id, uuid) ? errno : 0;
}

Unfortunately, while trying to compile the C test file with the following command : gcc -std=c99 get_unique_id_test.c -o get_unique_id_test, I get the following error :

In file included from get_unique_id_test.c:4:0:
syscalls_test.h: In function ‘get_unique_id’:
syscalls_test.h:10:5: warning: implicit declaration of function        ‘syscall’ [-Wimplicit-function-declaration]
     return syscall(__NR_get_unique_id, uuid) ? errno : 0;
     ^
syscalls_test.h: In function ‘get_unique_id’:
syscalls_test.h:10:5: warning: implicit declaration of function ‘syscall’ [-Wimplicit-function-declaration]
     return syscall(__NR_get_unique_id, uuid) ? errno : 0;
     ^
/tmp/cc1euZ3r.o: In function `main':
get_unique_id_test.c:(.text+0x22): undefined reference to `get_unique_id'
get_unique_id_test.c:(.text+0x34): undefined reference to `get_unique_id'
collect2: error: ld returned 1 exit status

It appears gcc cannot find the function get_unique_id(int * uuid), which is declared in syscalls_test.h, and the syscall function, which should be declared, I believe, in syscall.h, right ?

I don't understand why this happens. Does anybody have an idea ?

EDIT : my problems were solved using a3f's solution (see below) PLUS moving the #include "syscalls_test.h" at the very top of the file, as he said in the comments. Thank you very much.

3
  • 2
    Start by adding #define _GNU_SOURCE to the top of your syscalls_test.h Commented Feb 26, 2017 at 14:29
  • 2
    FYI sys_get_unique_id is not thread-safe; multiple threads could call it simultaneously and get the same value. You could fix this with atomic_t. Commented Feb 26, 2017 at 14:39
  • Yes I know, for now my system call is very simple, but I am currently trying to make it thread safe. Commented Feb 26, 2017 at 15:56

2 Answers 2

5
  • #define _GNU_SOURCE before including unistd.h or any other header as syscall(2) is not POSIX.
  • Use static inline instead of plain inline. Plain inline supplies an inline definition, but the compiler is free to ignore it and use the external definition instead, which you aren't providing.
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks, adding static to my function solved the error. There's something I don't understand though, wouldn't it make the get_unique_id function invisible outside the syscalls_test.h file ?
And I added #define _GNU_SOURCE as you said, but I still get the warning of implicit function declaration of syscall. I get it only once though, not twice like before.
#define it as the very first thing, before including any headers. static makes a function internal to a translation unit, a file may #include multiple headers, so a translation unit may contain multiple files and the static function is accessible in all of them.
Thank you for the clarification. About the #define though, I did put it as the very first line in the file, and I still get the warning.
Because you include files in get_unique_id_test.c before defining it. Either #define it at the very top or pass it on the command line.
|
0

Try the following one:

#include <unistd.h>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.