After further experimenting I have a first version working. When a file is written, a makes a copy of the existing file with the name of this file, trailed with 14 characters, of which the first an dthe last are underscores, and in between only numbers (actually the time seconds since the epoch). So the file “test.txt” gets a backup “_001693031634_test.txt”.
More specific’, there is a hook in the file_operations.open kernel function:
- When a file is read, everything goes as normal.
- When a file is
- It checks whether the filename has a backup file format (_NNNNNNNNNNNN_).
- If it is a backup file: If the file does not exist (or is empty) it can be written (*), otherwise it cannot be written
- If it is not a backup file, it makes a copy of the file as backup file. If the backup is successful, the file can be modified. Otherwise it cannot be modified.
(*) This step seems maybe unnecessary. However, the file_operations.open function is called both form user space as from kernel space. And the kernel module cannot distinguish between them. And we want to be able to write to the backup file from the kernel module, but not from ransomware from the servers in the user space. But this is not possible. So the solution here is that it treats the backup file as WORM: you can write them once, but not change them afterwards.
I also write “(or is empty)”. This is due to the Linux kernel. The kernel knows already form the directory listing whether a file exist or not. If a file does not exist, it first calls the vfat_create function, before the file_operations.open function. So the file does exits already, but is empty (and has different flags). So this does determine whether it ‘exists’ or not.
The PRFS works fine when editing text within the RPi linux environment. And also the FTP server (proftpd) works reliable. Samba does not work properly yet.
Still to do:
- Fix samba
- Connect the switch for the cleaning the disc
- Make a backup copy at delete and rename