更改内核中的文件权限

时间:2009-08-28 17:24:09

标签: c linux file-permissions kernel-module

我正在编写内核模块(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

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

2 个答案:

答案 0 :(得分:5)

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

  

来自Linux内核邮件列表

     

2003年2月20日星期四下午11:10:27 + 0100,Andrea Arcangeli写道:   在2003年2月20日星期四下午12:40:43 -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系统调用的快速参考,以及它们在内核中的实现。

答案 1 :(得分: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);