/frelink

Undelete open files and loop mounts ("improved" version of fdlink)

Primary LanguageC

frelink - recover deleted open or loop-mounted files
====================================================

Introduction
------------

Did you ever happen to delete a precious file by mistake but
it is still open by a process or loop-mounted?

If still open by a process, is it too big to copy it from the
/proc/<pid>/fd/X "symlink" or is it randomly changing so that
you can't use cp or 'tail' to copy it safely? (E.g., a virtual
machine image or a big MySQL innodb tablespace).

If yes, then this project tries to be the answer to your problem.
FRelink consists of a Linux kernel module and a CLI userspace
app that are together able to "restore" (re-hardlink at VFS level)
deleted files that are still open by a process or loop-mounted.


BIG FAT WARNING
---------------

THIS MODULE IS A REAL HACK. IT MESSES WITH IN-MEMORY KERNEL
STRUCTURES IN A WAY THAT PEOPLE NORMALLY SHOULDN'T. DO *NOT*
USE THIS ON A PRODUCTION MACHINE BEFORE TESTING ON A VM WITH
THE EXACT SAME KERNEL AS YOUR PRODUCTION MACHINE FIRST. THE
RISK OF DESTROYING YOUR FILE SYSTEM COMPLETELY IS QUITE HIGH
OTHERWISE. FURTHERMORE, THE KERNEL MODULE IS A BIG SECURITY
RISK. ONLY INSTALL FOR A SPECIFIC RECOVERY AND THEN DELETE
THE TOOL AND REBOOT AS SOON AS POSSIBLE.

THIS CODE IS GIVEN TO YOU FREE OF CHARGE AND WITH ALL RIGHTS
OF GPLV2 OR LATER (AT YOUR OPTION) BUT THE AUTHOR HAS *NO*
RESPONSIBILITY OR LIABILITY TO YOU OR ANYONE ELSE FOR ANY
DAMAGE YOU CAUSE TO YOUR SYSTEM, YOUR CLIENTS, YOUR DOG
OR ANYTHING ELSE. IF ANYTHING BREAKS, YOU GET TO KEEP THE
PIECES :P

That said, at least this approach has a fair chance to work,
and is cross-filesystem, while the alternative (using debugfs)
will destroy your filesystem for sure and will not recover
the file you want either (at least in modern journalled
filesystems) ...

Nevertheless, only use as a last option, only when you know
what you are doing. If you don't feel confident it is much
better to get someone else to recover the file for you, at
least this way you can curse someone else instead of yourself
if the recovery fails :P

If this project saves your life or job etc and you want to
send a "thank you" note, or donate money, books or hardware
to the author, he can be reached at <pktoss@gmail.com>


Compiling and installing
------------------------

Just issue

make

Then

insmod frelink.ko

as root and

make test

(also as root) to see if everything works.


Running (examples)
------------------

./frelink /proc/574/fd/4 (recover open file)

./frelink /dev/loop1     (recover loop mounted file)

A hardlink to the file will be created (again) using
the original (deleted) path name and the symlink on
/proc/<pid>/fd/X will also be restored and not say
"(deleted)" anymore.

DO NOT try any "fancy" tricks like changing backing
store for the loop device or anything like this because
in this case you WILL destroy your system and panic
your kernel. Don't say I didn't warn you ...



Prerequisites
-------------

frelink has only been tested in Ubuntu maverick default kernel
on both x86 and x86_64.

Especially for recovering loop-mounted files your kernel needs
to support kprobes (because the only way I 've found to get the
struct file pointer for the backing file of a loop device
is to "steal" it using a kprobe).



Theory of Operation and Related work
------------------------------------

The module exposes a file "/proc/frecover" in which it accepts
IOCTL requests.

For open files:

The userspace app figures out the original path by doing a
readlink(2) on the /proc/<pid>/fd/X path you give. Then it
opens the /proc file and passes the fd and original name
to the module.

The module in turn proceeds to create a new dentry for the
path and vfs_link it with the old one.

It also puts the old one back to the dentry cache so that
the /proc link appears restored (doesn't say "(deleted)"
anymore). Error checking performed is really minimal,
since this module is only supposed to be used on a
case-by-case basis and then removed as soon as possible.

Play tricks like giving a different than the original
name to the kernel (by not using the frelink app) and
you will destroy your system. 


For loop-mounted files:

There is no way I know that someone can get an fd or
dentry back in a "normal" way from the loop module
about it's backing file.

So, we use a really ugly hack, a jprobe with which
we "steal" the struct file of the backing file
from the module and subsequently we use it to
do the undelete from a workqueue.

To activate the jprobe we need to do an IOCTL
to the loop device as well (so, again, use
the frelink app, don't play with the module
by yourself).

Because the undelete is scheduled and no locking
or checking is performed (to keep the code short
and easy to understand), if you do tricks like
changing the backing file of the loopback device
before the recovery is completed, you are almost
guaranteed to crash your system ... Don't say
I didn't warn you ...


References:

There are 2 more similar modules (that don't support
loop-mounted files though):

fdlink: http://fdlink.sourceforge.net
        (by amos shapira)

vfs-undelete: http://vfs-undelete.sourceforge.net

frelink has been based mostly on fdlink code.

The request to make this functionality a syscall
also seems to come to LKML every 2-3 years or so
and every time it gets shot down for (valid)
security reasons, e.g.,

http://lkml.org/lkml/2003/4/6/112

To my knowledge, all the features that people have
asked for such a project (recover original name,
restore the /proc link, restore also loop-mounted
files) have been implemented in frelink. But should
you want anything more, or to contribute better/saner
ways to implement this functionality, you can contact
the author at <pktoss@gmail.com>

-Pantelis