在内核模式下在 ext4 中设置自定义扩展属性

ams*_*152 5 c linux linux-kernel

我正在尝试在 linux 内核的 ext4 文件系统中实现自定义扩展属性。我添加了两个新的系统调用来设置和获取文件的 Security_Tag(我的新属性)。在这些系统调用的实现中,我使用了setxattr、getxattr和access函数。

这是我实现系统调用的源代码:

#include <linux/kernel.h>
#include <linux/unistd.h>
#include <linux/syscalls.h>
#include <linux/types.h>
#include <linux/xattr.h>

// Sets the Security_Tag attribute for the given file to the  specified
// integer value.
asmlinkage int sys_set_security_tag(const char *filename, int new_tag)
{
        // Check if the current user has write access to this file
        int permissions = access(filename, W_OK);
        if(permissions < 0){
                printk("ERROR: Permission Denied");
                return -1;
        }

        // Set the value of the Security_Tag attribute to the value of new_tag
        int *val_p = &new_tag;
        int err = setxattr(filename, "Security_Tag", val_p, sizeof(int), 0);
        if(err < 0){
                printk("ERROR: Set attribute failed.");
                return -1;
        }

        return 0;
}

// Returns the value of the Security_Tag attribute for the given file.
asmlinkage int sys_get_security_tag(const char *filename)
{
        // Check if the user has read access to this file
        int permissions = access(filename, R_OK);
        if(permissions < 0){
                printk("ERROR: Permission Denied.");
                return -1;
        }

        // Allocate a buffer for the value of the tag and retrieve it's value
        int *buff = kmalloc(sizeof(int));
        ssize_t bytesRead = getxattr(filename, "Security_Tag", buff, sizeof(int));

        if(bytesRead < 0){
                // Attribute does not exist for this file yet, so create the
                // attribute and set it to the default value of 0.
                int val = 0;
                int *val_p = &val;
                int err = setxattr(filename, "Security_Tag", val_p, sizeof(int), XATTR_CREATE);

                if(err < 0){
                        printk("ERROR: Attribute Creation Failed");
                        return -1;
                }
                return val;
        }

        // Store the return value, free the buff pointer, and return the
        // Security_Tag value.
        int ret = *buff;
        free(buff);
        return ret;
}
Run Code Online (Sandbox Code Playgroud)

当我尝试制作内核时,出现以下错误:

$ sudo make && sudo make install && sudo make modules_install
make[1]: Entering directory '/usr/rep/out/kernel'
  CHK     include/config/kernel.release
  Using /usr/rep/src/kernel as source for kernel
  CHK     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  CHK     include/generated/bounds.h
  CHK     include/generated/timeconst.h
  CHK     include/generated/asm-offsets.h
  CALL    /usr/rep/src/kernel/scripts/checksyscalls.sh
  CHK     include/generated/compile.h
  SKIPPED include/generated/compile.h
  CC      filesecuritytag/filesecuritytag.o
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c: In function 'sys_set_security_tag':
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:12:2: error: implicit declaration of function 'access' [-Werror=implicit-function-declaration]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:12:37: error: 'W_OK' undeclared (first use in this function)
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:12:37: note: each undeclared identifier is reported only once for each function it appears in
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:19:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:20:2: error: implicit declaration of function 'setxattr' [-Werror=implicit-function-declaration]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c: In function 'sys_get_security_tag':
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:33:37: error: 'R_OK' undeclared (first use in this function)
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:40:2: error: too few arguments to function 'kmalloc'
/usr/rep/src/kernel/include/linux/slab.h:478:30: note: declared here
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:40:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:41:2: error: implicit declaration of function 'getxattr' [-Werror=implicit-function-declaration]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:59:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:60:2: error: implicit declaration of function 'free' [-Werror=implicit-function-declaration]
/usr/rep/src/kernel/filesecuritytag/filesecuritytag.c:60:2: warning: incompatible implicit declaration of built-in function 'free' [enabled by default]
cc1: some warnings being treated as errors

/usr/rep/src/kernel/scripts/Makefile.build:293: recipe for target 'filesecuritytag/filesecuritytag.o' failed
make[2]: *** [filesecuritytag/filesecuritytag.o] Error 1
/usr/rep/src/kernel/Makefile:991: recipe for target 'filesecuritytag' failed
make[1]: *** [filesecuritytag] Error 2
make[1]: Leaving directory '/usr/rep/out/kernel'
Makefile:150: recipe for target 'sub-make' failed
make: *** [sub-make] Error 2
Run Code Online (Sandbox Code Playgroud)

据我所知,这意味着我上面列出的所有函数都没有被原型化(我最初想到的是没有正确包含头文件)。免责声明:这是我第一次编译我的代码,所以我不知道我实现的东西是否有效,而且我对 C 比较陌生,所以我可能会忽略一些小东西。

我的问题是:

  1. 是否可以在内核中使用 setxattr、getxattr 和访问?如果不是,我应该使用哪些等效的内核模式函数?(例如,必须在内核中使用 printk 而不是 printf)。

  2. 手册指出我需要包含 unistd.h、sys/types.h 和 attr/xattr.h。我尝试按照手册中的说明包含它们,但出现错误,但是当我使用 linux/types.h、linux/xattr.h 和 linux/unistd.h 时,我没有收到任何错误。这是包含这些标题的正确方法吗?

编辑:响应此被标记为重复。链接的另一篇文章仅回答了使用什么来代替 setxattr 函数的问题(这导致我自己找到了 vfs_getxattr 函数),但它没有解释如何在不使用的情况下处理文件系统权限检查的访问呼叫。所以,继续:

  1. 如果无法使用访问调用,可以使用什么来检查内核中的用户/进程文件权限?