Linux Why does the user system call with negative numbers not work?

I wrote a special system call for assignment that compares two integers and returns the largest. Here is my kernel side code (max.c):

#include <linux/kernel.h> #include <linux/syscalls.h> asmlinkage long sys_max(int num1, int num2) { if (num1 > num2) { return num1; } else { return num2; } } 

And here is my user space code (max.h):

 #include <unistd.h> #define SYS_MAX 323 int max(int num1, int num2) { int maxnumber = syscall(SYS_MAX, num1, num2); return maxnumber; } 

I use this little program to test the system call:

 #include <stdio.h> #include <max.h> int main() { int a, b; scanf("%d", &a); scanf("%d", &b); printf("%d", max(a, b)); return 0; } 

It works fine for positive numbers, or when it is positive and the other negative, but max always returns -1 when dealing with two negative values. I was wondering if this is due to the int-> long conversion, but I cannot figure out what causes the problem.

+5
source share
1 answer

If a system call returns a negative value, it is treated as an error, and special error handling code is called in libc. Namely, the return value is canceled and moved to the global variable errno , and the return value of the system call becomes -1 .

Actually, reading about this, I found that on Linux only values ​​from -4095 to -1 are considered errors , but this is neither portable nor useful if you want your function to work with any possible values.

In short, you cannot safely use the syscall return value to return a value that may be negative. The usual convention would be to pass a pointer to the target variable to store the result and reserve a return code for success / failure. Note that when doing this with syscall, you will work with a user space pointer from the kernel space, so copy_to_user will need to write the result.

+11
source

Source: https://habr.com/ru/post/1235431/


All Articles