системный вызов: аргумент не передается в функцию

#c #linux

Вопрос:

Я пишу функцию системного вызова и тестирую ее с помощью модулей ядра.

Это моя процедура:

  1. соберите ядро (получите mod.ko)
  2. sudo insmod mod.ko
  3. написать тестовый файл c

во-первых, я узнал, что номер 336 свободен для системного вызова, поэтому я использую 336 в качестве смещения, подключил свою функцию в sys_call_table:

 static int __init init_addsyscall(void)
{
    printk("My syscall is starting...n");
    sys_call_table = (unsigned long *)0xffffffffaae002c0;
    printk("sys_call_table: 0x%pn", sys_call_table);
    anything_saved = (int(*)(void))(sys_call_table[__NR_syscall]);  /* save original one */
    orig_cr0 = clear_and_return_cr0();  /* make cr0 writable */
    sys_call_table[__NR_syscall] = (unsigned long)amp;sys_mycall;  /* change function pointer */
    setback_cr0(orig_cr0);  /* recover cr0 */
    return 0;
}
 

мой системный вызов-это:

 asmlinkage long sys_mycall(unsigned long long num)
{
    printk("my call, num = %llu", num);
    if (num % 2 == 0)
        return num % 1000000;
    else
        return num % 100000;
}
 

мой тестовый файл c:

 // t.c
#include <sys/syscall.h>
#include <stdio.h>
#include <unistd.h>

int main()
{
    printf("%dn",syscall(336, 19030123456));
    return 0;
}
 

Ожидается , что t.c будет напечатан 123456 , но он напечатает случайное число. Я много раз пытался запустить эту тестовую функцию и каждый раз получал разное возвращаемое значение. Я использую sudo dmesg для проверки журнала и могу быть уверен, что мой системный вызов вызван, а аргумент системного вызова также не является моим вводом. Более вероятно, что аргумент является случайным числом…

 [ 9444.176815] My syscall is starting...
[ 9444.176825] sys_call_table: 0x000000002dac30a7
[ 9448.550544] my call, num: 18446667112225996632
[ 9449.256182] my call, num: 18446667112224440152
[ 9449.966801] my call, num: 18446667112225046360
[ 9453.252192] my call, num: 18446667112225177432
[ 9455.373322] my call, num: 18446667112225308504
 

Я новичок и не знаю, что здесь происходит, и могу быть уверен, какая информация необходима для анализа. Если вам нужна более подробная информация, просто дайте мне знать.

Комментарии:

1.Во время printk вызова sys_mycall , почему вы форматируете unsigned long long num использование %d ? Использует ли он другие преобразования , чем обычные printf , или вы должны использовать %llu для unsigned long long ? Я не знаком с работой внутри ядра Linux, но: Вы sys_mycall прошли unsigned long long проверку ? Известно ли, что он возвращает a long ? Какой тип syscall возвращает значение? Если это a long , как вы sys_mycall возвращаете, почему вы форматируете его printf с %d помощью, а не %ld ?

2. @EricPostpischil printk в основном использует то же самое, что и printf (исключения: отсутствие поддержки float, дополнительные модификаторы для %p формата и поддержка уровня журнала). Правильные спецификаторы в printk описаны здесь .

3. @EricPostpischil извините за ошибку. Это небольшая ошибка, потому что я пытаюсь использовать int , long , unsigned long , long long и unsigned long long тестировать свой код. Я неправильно отредактировал его здесь и исправил. На самом деле, unsigned long long является типом аргумента и возвращает «длинный», потому что он находится в диапазоне long (также в int ). Ключевым моментом проблемы является то, что аргумент кажется не тем значением, которое я в него передал(потому что тот же аргумент, другой num в функции).