8

我正在编写内核模块(Linux 中的 C),我想更改其中其他文件的权限。任何解决方案?因为我在内核中,所以我不能使用 chmod syscall 并且......感谢您的帮助

这是我的 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

似乎这个错误尤其发生在内核模块中。任何的想法?再次感谢!

4

2 回答 2

5

欢迎来到堆栈溢出!你想要的IIRCsys_chmod()

来自 Linux 内核邮件列表

2003 年 2 月 20 日星期四 11:10:27PM +0100,Andrea Arcangeli 写道: 2003 年 2 月 20 日星期四 12:40:43PM -0500,Jeff Garzik 写道:

2003 年 2 月 20 日星期四晚上 11:04:37+0530,普拉萨德写道:

有没有一种方法可以在内核空间中调用系统调用?系统调用将伪装成另一个进程运行。实际上

调用 sys_whatever()。查看内核代码以获取示例。

内核已经在不同的地方这样做了。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 系统调用的快速参考以及它们在内核中的实现位置。

于 2009-08-28T17:48:22.760 回答
3

系统调用不是导出的符号。如果你想要它们,你需要做一些黑客攻击。

你想得到你的手指sys_call_table。它包含一个指向每个系统调用的指针。查看arch/x86/kernel/syscall_table_32.Sarch/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);
于 2009-08-30T07:34:16.880 回答