我想在将数据写入硬盘之前做一些事情。我不知道任何解决方案。为避免编辑内核源代码,是否有任何位置可以使用钩子函数作为可加载模块?
更新:谢谢大家,LSM 对 API 挂钩很有用。但我想找到其他提供机制挂钩读/写数据块的解决方案。它可以避免在更新文件后重新加密所有文件。
我认为我可以在文件系统(ext2、ext3、...)和缓冲区缓存之间进行修改。
我想在将数据写入硬盘之前做一些事情。我不知道任何解决方案。为避免编辑内核源代码,是否有任何位置可以使用钩子函数作为可加载模块?
更新:谢谢大家,LSM 对 API 挂钩很有用。但我想找到其他提供机制挂钩读/写数据块的解决方案。它可以避免在更新文件后重新加密所有文件。
我认为我可以在文件系统(ext2、ext3、...)和缓冲区缓存之间进行修改。
使用Linux 安全模块。这些是可加载的内核模块,它们提供挂钩来调解对内核中各种内部对象的访问。您可以根据需要使用文件系统或 inode 的挂钩。一个很好的起点是阅读 Greg Kroah Hartman关于 LSM的论文。然后您可以访问此链接,其中显示了如何使用 LSM 挂钩的示例。该示例仅在插入特定 USB 时调解对系统的访问,并且是有关如何开始使用 LSM 挂钩的一个很好的参考点。
嗯,这是个有趣的问题。
不幸的是,即使是 LSM 也无济于事。作为一种可能的解决方案,我会推荐使用address_space_operations
表和钩子writepage
函数。例如,查看ext3_writeback_aops:
1984 static const struct address_space_operations ext3_writeback_aops = {
1985 .readpage = ext3_readpage,
1986 .readpages = ext3_readpages,
1987 .writepage = ext3_writeback_writepage,
1988 .write_begin = ext3_write_begin,
1989 .write_end = ext3_writeback_write_end,
1990 .bmap = ext3_bmap,
1991 .invalidatepage = ext3_invalidatepage,
1992 .releasepage = ext3_releasepage,
1993 .direct_IO = ext3_direct_IO,
1994 .migratepage = buffer_migrate_page,
1995 .is_partially_uptodate = block_is_partially_uptodate,
1996 .error_remove_page = generic_error_remove_page,
1997 };
因此,在ext3
文件系统的情况下,我们需要在内存中找到这个结构并替换writepage
指向our_writepage
包装器的指针。另请注意,此表位于只读内存中,您需要正确处理它。
编辑:
使用 LSM,可以挂钩打开操作并就地inode
更换。inode->i_mapping->a_ops
试试FUSE ( https://github.com/libfuse/libfuse )。
这是用户空间中的文件系统。您可以在用户空间中编写文件 I/O 处理程序,然后简单地将其挂载为应用程序的执行。
这个示例示例演示了如何破解 libc 函数,例如 open\close\read\write 等。
您可以制作一个动态库文件your_write_lib.so,它实现了一个新的写入功能。
/* your_write_lib.c */
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <dlfcn.h>
#include <stdarg.h>
ssize_t write (int fd, const void * buf, size_t count){
ssize_t (*glibc_write)(int fd, const void * buf, size_t count);
glibc_write = dlsym(RTLD_NEXT, "write");
// do whatever you want
return glibc_write(fd, buffer, strlen(buffer));
}
将 your_write_lib.c编译成.so文件:
gcc -Wall -fPIC -shared -o your_write_lib.so your_write_lib.c -ldl
然后像这样运行您的应用程序:
LD_PRELOAD=./your_write_lib.so your_application
在LD_PRELOAD=./your_write_lib.so的帮助下,Linux 操作系统将首先加载your_write_lib.so,然后是glibc。新的open会将glibc的 origin open功能隐藏到您的应用程序中。你可以在新的open函数中做任何事情,比如“写之前做点什么”。
我不认为这是可能的。当用户空间调用文件 I/O 时,将从 VFS 调用文件系统实现或通用实现。您需要更改此函数指针以指向您的模块,该模块会加密您的数据,然后调用文件系统函数。
我在大学里做过类似的事情,但它是一个旧内核,你必须设置一个特定的配置标志。如果我记得这个标志已经消失了,因为您不希望内核模块在其范围之外乱用函数指针。
无论如何,您都可以在这里找到该模块:https ://motzblog.wordpress.com/2007/10/27/linux-monitoring-module/
但请注意,这是一个大学项目,所以代码质量不是你想要的,除了 Linux 内核代码。