I want to do something before writing data into hard disk. I don't known any solutions. To avoid editing kernel source code, is there any locations that I can use hook function as a loadable module?
UPDATE: Thanks all, LSM is good for API hooks. But I want to find other solution that provides mechanism hook read/write block of data. It can avoid re-encrypting all file after updating file.
I think there is something that I can modify between filesystem (ext2, ext3,...) and buffer cache.
Use Linux Security Modules. These are loadable kernel modules, that provide hooks to mediate accesses to various internal objects in the kernel. You can use the hook to filesystem, or inodes as per your requirement. A god place to start is to read Greg Kroah Hartman's paper on LSM. Then you can visit this link, where it is shown along with an example how to make use of LSM hooks. The example is to mediate access to the system only when a particular USB is inserted, and is a good reference point on how to start with LSM hooks.
Well, it's interesting question.
Unfortunately, even LSM doesn't help here. As a possible solution I'll recommend use address_space_operations
tables and hook writepage
function. For example, look at 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 };
So, in case of ext3
filesystem we need to find this struct in memory and replace the writepage
pointer to point to our_writepage
wrapper. Note also that this table is in read-only memory and you need to handle it correctly.
EDIT:
With LSM it is possible to hook on inode
open operation and replace inode->i_mapping->a_ops
inplace.
Try the FUSE(https://github.com/libfuse/libfuse).
This is a file system in userspace. You can write file I/O handler in user space and simply mount it as execution of application.
I don't think this is possible. When userspace invokes a file I/O the file system implementation or the generic implementation will be called from VFS.
what you would need is to change this function pointers to point to your module, which encrypts your data and then invokes the file system function.
I did something like this in university, but it was an old kernel and you had to set a specific configuration flag. If I remember this flag has disappeared as you don't want kernel modules to mess around with functions pointers outside their scope.
In any case, you can find the module here: https://motzblog.wordpress.com/2007/10/27/linux-monitoring-module/
But be warned, it was a university project, so the code quality isn't what you except from Linux kernel code.