I am currently playing with the thought of [url=http://linux.die.net/man/1/shred]shredding[/url] files automatically before they are unlinked from the file system (for example on a mail server). I wrote a small library that you can inject into processes using LD_PRELOAD, so all unlink operations result in a call to shred for (A) regular files that (B) have only one hard link left.



The default branch ([url=https://github.com/moba/unlink-shred/blob/master/unlink-shred.c]direct link to source[/url]) contains a version that, for debugging purposes, logs to stdout:



% git clone https://github.com/moba/unlink-shred.git

% cd unlink-shred

% gcc -Wall -fPIC -DPIC -c unlink-shred.c && ld -shared -o unlink-shred.so unlink-shred.o -ldl -lc

% touch test

% LD_PRELOAD=./unlink-shred.so unlink test

yay. shredded test before unlink



There is also a branch that logs into /tmp/unlink-shred.log with timestamps ([url=https://github.com/moba/unlink-shred/blob/create_log/unlink-shred.c]direct link to source[/url]):



% git clone -b create_log https://github.com/moba/unlink-shred.git

% cd unlink-shred

% gcc -Wall -fPIC -DPIC -c unlink-shred.c && ld -shared -o unlink-shred.so unlink-shred.o -ldl -lc

% touch test

% LD_PRELOAD=./unlink-shred.so unlink test

% cat /tmp/unlink-shred.log

[2013-02-06 11:04:37] yay. shredded test before unlink



You can disable logging by deleting the #define DEBUG line.

This is probably not something you want to put into production use. A cleaner, but more complicated approach requires a file system/kernel driver that catches before drive space is freed. The current “unlink replacement” will shred files that may still be in use by other processes (whereas the default unlink will remove the file link, but keep the contents in memory until all processes have closed it).

That said, I have tested the second branch on a Debian VM, applying it system wide to all unlink operations:



# mv unlink-shred.so /usr/local/lib

# echo "/usr/local/lib/unlink-shred.so" >> /etc/ld.so.preload



Don’t do this. In a production environment, I would definitely limit it to certain processes or users, and only after extensive testing in a safe environment. It works surprisingly well globally, but it does break stuff.

Be aware that for effective shredding, you have to disable your file system journal. Quote from the man page of shred:

CAUTION: Note that shred relies on a very important assumption: that the file system overwrites data in place. This is the traditional way to do things, but many modern file system designs do not satisfy this assumption. The following are examples of file systems on which shred is not effective, or is not guaranteed to be effective in all file system modes:

– log-structured or journaled file systems, such as those supplied with AIX and Solaris (and JFS, ReiserFS, XFS, Ext3, etc.)

– file systems that write redundant data and carry on even if some writes fail, such as RAID-based file systems

– file systems that make snapshots, such as Network Appliance’s NFS server

– file systems that cache in temporary locations, such as NFS version 3 clients

– compressed file systems

In the case of ext3 file systems, the above disclaimer applies (and shred is thus of limited effectiveness) only in data=journal mode, which journals file data in addition to just metadata. In both the data=ordered (default) and data=writeback modes, shred works as usual. Ext3 journaling modes can be changed by adding the data=something option to the mount options for a particular file system in the /etc/fstab file, as documented in the mount man page (man mount).

In addition, file system backups and remote mirrors may contain copies of the file that cannot be removed, and that will allow a shredded file to be recovered later.

Comments?