Изменение прав доступа к файлам в ядре - PullRequest
8 голосов
/ 28 августа 2009

Я пишу модуль ядра (C в Linux) и хочу изменить разрешение других файлов в нем. любое решение? так как я в ядре, я не могу использовать системный вызов chmod и ... спасибо за вашу помощь

Это мой Makefile:

> obj-m += ca.o
> 
>     all:
>       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
>     
>     clean:
>       make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

А это мой код:

> #include <linux/string.h>
> #include <linux/mm.h>
> /* Snip, tons of includes (all of them :))*/
> #include <linux/delay.h> .... int procfile_write(struct file *file,
> const char *buffer, unsigned long
> count,
>          void *data) { ...    sys_chmod(path, per); ... } ...

При изготовлении выдает предупреждение:

WARNING: "sys_chmod" [file] undefiened

и при загрузке модуля с помощью "sudo insmod" выдает эту ошибку:

Unknown sybol in module

похоже, что эта ошибка происходит особенно в модулях ядра. любая идея? еще раз спасибо!

Ответы [ 2 ]

5 голосов
/ 28 августа 2009

Добро пожаловать в stackoverflow! IIRC, который вы хотите sys_chmod()

Из списка рассылки ядра Linux

В четверг, 20 февраля 2003 г. в 23:10:27 +0100, Андреа Арканджели написала: В четверг, 20 февраля 2003 г., 12:40:43 - 05:00 Джефф Гарзик написал:

В четверг, 20 февраля 2003 г., в 11:04:37 +0530, Прасад написал:

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

Вызовите sys_whwhat (). Посмотрите на код ядра для примеров.

Ядро уже делает это в различные места. sys_read, sys_write, open_filp, sys_close и другие функции безопасны для вызова из ядра код - хотя это не рекомендуется. init / do_mounts.c является особенно досадный случай, и это большая причина, почему klibc нужно объединить. Системные вызовы должно быть сделано из пространства пользователя, а не из ядро.

Люди начинают беспокоиться, поскольку это не то, что вы можете делать в ядре (если вы не используете, вы знаете, что делаете). Если вы просто хотите изменить разрешения для определенного события, сделайте это из пространства пользователя с помощью inotify или аналогичного.

Отказ от ответственности в сторону:

Вот код, который я нашел в другом модуле ядра, который использует вызовы sys_ *:

#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <linux/fcntl.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/syscalls.h>
/* Snip */

int openflags = O_WRONLY|O_CREAT;
if (ml != 1)
        openflags |= O_TRUNC;
wfd = sys_open(collected, openflags, mode);

if (wfd >= 0) {
    sys_fchown(wfd, uid, gid);
    sys_fchmod(wfd, mode);
    state = CopyFile;
}

Также найдено:

asmlinkage long sys_rename(const char __user *oldname, const char __user *newname);
asmlinkage long sys_chmod(const char __user *filename, mode_t mode);
asmlinkage long sys_fchmod(unsigned int fd, mode_t mode);

в include/linux/syscalls.h

Имейте в виду, прошло много времени с тех пор, как я занимался ядром. Проверьте , что это подходящий интерфейс для chmod, и что вы не используете ярлыки для других вызовов, которые могут реализовывать хуки безопасности, например.

Также Эта ссылка содержит информацию о системных вызовах и их символах. Также Здесь - краткий справочник системных вызовов API пользовательского пространства и того, где они реализованы в ядре.

3 голосов
/ 30 августа 2009

Системные вызовы не являются экспортируемыми символами. Вам нужно немного взломать, если вы хотите их.

вы хотите, чтобы ваши пальцы на sys_call_table. Он содержит указатель на каждый системный вызов. Посмотрите на arch/x86/kernel/syscall_table_32.S или arch/i386/kernel/entry.S на старых ядрах.

Вы можете grep sys_call_table /usr/src/linux/System.map (или /proc/kallsyms, если символы экспортируются), чтобы найти базовый адрес этой таблицы. Вы можете использовать этот адрес в качестве параметра для вашего модуля (потребуется преобразование шестнадцатеричной строки в указатель).

Вы сможете вызвать правильный системный вызов со смещением, определенным в arch/x86/include/asm/unistd_32.h (или include/asm-i386/unistd.h в старых ядрах). Вы получаете что-то вроде: #define __NR_chmod 15

Макросы полезны:

#define DO_SYSCALL_2(sc, t1, a1, t2, a2)                       \
    (((asmlinkage long (*)(t1, t2)) sys_call_table[__NR_##sc]) (a1, a2));
#define USER_SYSCALL_2(sc, t1, a1, t2, a2)                     \
    static inline asmlinkage long syscall_##sc(t1 a1, t2 a2)   \
    { return DO_SYSCALL_2(sc, t1, a1, t2, a2) }

USER_SYSCALL_2(chmod, const char __user *, filename, mode_t, mode);
int my_code(void) { return syscall_chmod(arg1, arg2); }

Кроме того, если вы передаете буфер ядра (для имени файла для примеров), который должен быть пользовательским буфером, не забудьте изменить сегмент данных:

mm_segment_t oldfs = get_fs(); set_fs(KERNEL_DS);
ret = syscall_XXX(...);
set_fs(oldfd);
...