在内核中更改文件权限

Posted

技术标签:

【中文标题】在内核中更改文件权限【英文标题】:Changing file permissions in kernel 【发布时间】:2010-11-23 19:37:14 【问题描述】:

我正在编写内核模块(Linux 中的 C),我想更改其中其他文件的权限。 任何解决方案? 因为我在内核中,所以我不能使用 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

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

【问题讨论】:

您要更改哪些文件的权限?在内核模块中? 普通文件。就像家里的那些等等。唯一的一点是我的代码在内核中。 嗯,我得听听这个“为什么”。您可以从用户空间执行此操作,那么为什么要在内核中执行此操作? @derobert - 有时,无知是幸福 ;) 好吧,我打算制作一个内核模块,它可以做很多类似的事情。我总是喜欢了解更多:D 【参考方案1】:

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

您想了解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);

【讨论】:

+1(希望我能 +4)出色的回答 Pafy。我提名这个代替我自己的“猜测”的正确答案 哇!谢谢!我会尽快尝试的!看起来很不错:-D :) 而且,您可以劫持它们(只需将系统调用表中的正确指针替换为您自己的函数)。如果你保存原始指针,你就有一个包装器:)【参考方案2】:

欢迎来到 ***! 你想要的 IIRC sys_chmod()

来自 Linux 内核邮件列表

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

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

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

调用 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 内容的适当接口,并且您没有捷径任何其他可能实现安全挂钩的调用,例如。

另外,This link contains information on syscalls 及其符号。此外,Here 是用户空间 API 系统调用及其在内核中实现位置的快速参考。

【讨论】:

谢谢!它使用 sys_chmod 编译并给出警告:“sys_chmod 未定义”。当通过“sudo insmod ...”加载时出现错误:“模块中的未知符号”我已经包含了所有头文件,包括系统调用、sys 和其他 40 个。 lxr.linux.no/#linux+v2.6.30.5/include/linux/syscalls.h#L428 gelato.unsw.edu.au/lxr/ident?i=sys_chmod 这些可能会有所帮助。 另外,请参阅编辑。我添加了来自源 sn-p 的包含(这是 initramfs 的源) 还要检查你的链接器的东西,比如你的 Makefile/GCC 中的“-L/linux-2.6.x/...” 真的真的很感谢你花时间!但它仍然有警告和错误。我把细节放在了编辑上。

以上是关于在内核中更改文件权限的主要内容,如果未能解决你的问题,请参考以下文章

在Linux系统中,如何更改文件的访问权限

无法在linux中更改文件权限

WIN10需要来自管理员权限才能对此文件进行更改

如何在 Ubuntu 中更改文件权限 [重复]

你需要来自 计算机管理员 的权限才能对此文件进行更改

如何更改文件权限