Разработка ядра: подключение Execve и печать char * const argv [] - PullRequest
0 голосов
/ 21 марта 2020

Я пытаюсь HookExecve и печатать аргументы. Я могу напечатать имя файла просто отлично. Как я могу напечатать аргументы char * const argv [] в режиме ядра? Мне нужно иметь возможность получить их количество и распечатать их.

Так что, если я запущу ls -lah. Я должен видеть в argv ["ls", "-lah"]; Я могу сделать это в пользовательском пространстве, но все попытки скопировать информацию из пользовательского пространства в пространство ядра, похоже, приводят к cra sh.

    char CharBuffer [255] = {'\0'};
    char Argz       [255] = {'\0'};

    asmlinkage int (*origional_execve)(const char *filename, char *const argv[], char *const envp[]);
    asmlinkage int HookExecve(const char *filename, char *const argv[], char *const envp[]) {
       unsigned int len     = sizeof(CharBuffer) / sizeof(CharBuffer[0]);
       unsigned int Argzlen = sizeof(Argz)       / sizeof(Argz[0]);

        copy_from_user(&CharBuffer , filename , len );
        //copy_from_user(Argz , argv[0] , sizeof(argv[0]) );     
        //strncpy_from_user(Argz, argv[0], len ); // Might break stuff
        printk( KERN_INFO "Executable Name %s \n", CharBuffer  );
        memset(CharBuffer, 0 , len);

      return (*origional_execve)(filename, argv, envp);
    }

1 Ответ

0 голосов
/ 21 марта 2020

sizeof (CharBuffer) / sizeof (CharBuffer [0])

Нет . Это просто sizeof(char*)/sizeof(char).

sizeof (Argz) / sizeof (Argz [0])

Нет . Это просто равно sizeof(char**)/sizeof(char*).

sizeof делает не , чтобы получить количество элементов в массиве. sizeof возвращает размер базового типа.

Чтобы получить длину строки (ie. Количество символов, пока не будет найден завершающий нулевой символ), используйте strlen. strlen возвращает тип size_t, как и sizeof.

argv Массив заканчивается значением sentinel NULL. Чтобы напечатать содержимое массива char **argv, выполняйте итерацию до тех пор, пока не найдете ноль:

for (char *i = argv; *i != NULL; ++i) {
    printf("%s\n", *i);
}

или:

for (size_t i = 0; argv[i] != NULL; ++i) {
    printf("%s\n", argv[i]);
}

char CharBuffer [255] = {'\ 0' }; & CharBuffer

Хотя оно равно значению, &CharBuffer не является char* типом. &CharBuffer имеет тип char (*)[255] - это указатель на массив из 255 символов. Включите предупреждения компилятора и устраните их - в ядре не допускайте ошибок. Просто используйте CharBuffer, который преобразуется в char* тип в strcpy -likei sh функциях.

Вы, похоже, хотите:

char char_buffer[255] = {0};
// Note: Do not name variables similar, especially globals.
// The argc <-> argz <-> argv differ only in one char.
// and 2d array to hold arguments strings
char argz[255][255] = {0};
// the count of arguments
size_t argc = 0;

asmlinkage int (*origional_execve)(const char *filename, char *const argv[], char *const envp[]);
asmlinkage int HookExecve(const char *filename, char *const argv[], char *const envp[]) {

    if (strlen_user(filename) + 1 > sizeof(char_buffer)) {
         // TODO: no memory for filename
         return -1;
    }
    copy_from_user(char_buffer, filename, strlen_user(filename) + 1);

    size_t i = 0;
    for (i = 0; argv[i] != 0; ++i) {

         // note: argz has type `char (*)[255][255]`
         // so: sizeof(argz) = 255 * 255 * sizeof(char)
         // *argz has type `char (*)[255]`
         // so: sizeof(*argz) = 255 * 255 * sizeof(char)
         // so: sizeof(argz)/sizeof(*argz) = 255
         // This would NOT work if `argz` would be a `char**`...
         // if (i > sizeof(argz)/sizeof(*argz)) {
         // but there is ARRAY_SIZE macro that does the same
         if (i > ARRAY_SIZE(argz)) {
              // TODO: not enough indexes
              return -1;
         }

         // sizeof(argz[i]) = sizeof(char(*)[255]) = 
         //                 = 255 * sizeof(char) = 255
         if (strlen_user(argv[i]) + 1 > sizeof(argz[i])) {
              // TODO: no memory to copy
              return -1;
         }
         copy_from_user(argz[i], argv[i], strlen_user(argv[i]) + 1);
    }
    argc = i;

    printk( KERN_INFO "Executable Name %s \n", char_buffer);
    for (size_t i = 0; i < argc; ++i) {
        printk( KERN_INFO "arg[i] = %s\n", argz[i]);            
    }

    return (*origional_execve)(filename, argv, envp);
}

Я ДЕЙСТВИТЕЛЬНО НЕ ИСПЫТАТЬ КОД, и, скорее всего, он содержит много ошибок. Также было бы лучше лучше обрабатывать ошибки и просто использовать динамическое распределение c и обрабатывать ошибки выделения.

...