Fakeroot vs fakeroot-ng comparison

From Fakeroot NG
Revision as of 15:58, 22 April 2019 by Shachar (talk | contribs) (Move page from old installation)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Some people are wondering whether fakeroot-ng is meant to kill off fakeroot. It is important to understand that fakeroot, developed by Clint Adams and Timo Savola, is an independent project that will live so long as they (or anyone else) decided to keep it alive. Trying to provide a quick answer, there are some area where it is almost impossible for fakeroot-ng to compete with fakeroot, just as there are some areas where fakeroot has no way to compete with fakeroot-ng. It can be said that fakeroot's coverage is wider, while fakeroot-ng's is deeper.

Design advantages of fakeroot

Speed

Fakeroot-ng runs as a separate process. Every time the program performs a system call, the kernel performs at least two context switchs to fakeroot-ng (one before and one after the system call), even if the system call is not handled. As a result, at least under some scenarios, fakeroot-ng is considerably slower than fakeroot.

For example, creating a copy of the /dev folder:

$ time fakeroot cp -a /dev/ /tmp/

real    0m0.132s
user    0m0.028s
sys     0m0.076s
$ rm -rf /tmp/dev
$ time fakeroot-ng cp -a /dev/ /tmp/

real    0m0.434s
user    0m0.020s
sys     0m0.076s

building fakeroot-ng:

$ time fakeroot make -j2
real    0m0.900s
user    0m0.776s
sys     0m0.284s
$ time fakeroot-ng make -j2
real    0m1.816s
user    0m0.784s
sys     0m0.384s

Platform Support

Fakeroot runs as part of the process, getting standard C interface function calls (glibc versioning trickery non-withstanding). Porting fakeroot to a new platform for an already supported operating system (say, a new CPU of Linux) is, in theory, just a matter of recompiling for the new platform. As a result, fakeroot easily spans all hardware platforms supported by, for example, Debian, including the non-Linux platforms.

The need to know which registers are used, how system calls are performed and other parameters mean that fakeroot-ng needs to be ported to each new operating system/CPU combination individually. As a result, at the time of this writing, only Linux is supported, and there, only PowerPC and Intel's x86 and x86_64 platforms are supported. Further platforms support depends on someone familiar with the platforms writing the support code needed. The original author now has access to an ARM and a SPARC platforms, so support for these two platforms is not unlikely in the near future.

Another aspect of the same problem is that, at least on Linux, the interface to the kernel is sometimes significantly different than the one defined by Posix or the Linux man pages. It is not uncommon to see a function defined in one way by the manual page, but to actually have that function translated into another by glibc, and implemented differently by the kernel. The different hooking locations mean that fakeroot has to implement the standard behavior, while fakeroot-ng needs to implement the platform dependent behavior.

Simplicity of Design

From the July 26, 1997 version of the fakeroot manual page:

Bugs
None so far. Be warned, though: although I've written quite a few much larger (and smaller) programs, I've never written anything that was as tiny as fakeroot, had as many bugs as fakeroot, and still was as usable as, say, fakeroot version 0.0_3, the first version that could be used to build itself.

This simplicity cannot be attributed to fakeroot-ng, no matter how you stretch it. Fakeroot-ng is built as a stateful non-blocking server, attempting to use a single process to handle as many simultaneous requests from different processes as possible. It uses hacks, tricks and, occasionally, coercion to make the debugged program do what it wants. There is nothing simple about it.

Fakeroot-ng advantages

Many of the advantages listed below boil down to one point - with ptrace, the control you have over the application is absolute. As such, there is nothing you can't do.

Static linked executables

Because fakeroot uses the dynamic linker to wrap the system calls, executables that are statically linked, use a non-standard dynamic linker (that does not honor LD_PRELOAD), or that do not use glibc in order to access the kernel are not visible to fakeroot, and cannot be wrapped by it. While most programs are dynamically linked, a major example of a statically linked binary that is very often used is the dynamic linker itself. Fakeroot does not, and cannot, wrap the system calls performed by it. Fakeroot-ng has no problem.

Fakeroot Limitations

The man page for fakeroot has a section titled "Limitations". They list three major limitations. At the time of writing, fakeroot-ng has none of those limitations. It does not depend on the version of any library used, does wrap "open" and "create" in a reliable race free manner, and does not care about environment variables or any other by-product semantics, and therefor runs "configure' without a problem.

Fakeroot-ng does have its own limitations, but they are a result of how far the author wished to go emulating the kernel, and not any inherent limitations of the technology. At the moment, the most pressing limitation is that the dynamic linker is loaded by the kernel, and is therefor loaded from the real root of the system, and not from the chroot (if applicable). There is a plan laid out to fix this.

Handling open and chroot

As fakeroot-ng has no problem in handling open, file ownership for unknown files is their real ownership. As a result, immediately after running fakeroot-ng, there is no change in how old files are displayed. New files are, of course, owned by the fake uid of the process (actually, the fake file system uid). Fakeroot-ng also supports chroot environments. Both are unsupported by fakeroot, due to its inability to handle "open".

Please note that there are other projects (most notable - fakechroot) that do wrap the open system call. Check out the fakeroot-ng vs fakechroot page for more details on it.

Library and Language Independence

Somewhat covered above, but worth expanding. Fakeroot needs to be linked with the precise same glibc version as the one the end program is linked. If the versions don't match, the best case is that fakeroot does not work at all, and the worse case is that subtle bugs appear in unexpected places. This may not be a huge problem for open source programs compiled as part of the distribution, but when 3rd party, and especially closed source precompiled programs, are involved, this might be a major drawback.

Program Address Space Presence

Fakeroot is a library that gets loaded into the program's address space. This means that any further libraries that fakeroot may need to load itself are also loaded into the program's address space. Furthermore, any data structures that fakeroot might need for normal operation are subtracted from the memory available for running the actual program. Fakeroot's solution (not only due to this reason) is to "outsource" all database required to an external daemon, that performs the actual data lookup (mostly the file fake owners and type).

Fakeroot-ng's presence inside the programs's address space, on the other hand, is minimal. The program runs while totally oblivious to the fact it is being debugged. Fakeroot-ng is written in C++, but it does not load any C++ run time library into the program's address space. The entire program address space presence is limited to a handful of memory pages, typically four, allocated explicitly by fakeroot-ng.

Security

Security is a goal for neither fakeroot nor fakeroot-ng. Still, as far as the technology goes, there is a world of difference between the two. With fakeroot security is not a goal partly because, had it been a goal, it would be unobtainable. Bypassing the fakeroot syscall wrapping is as easy as compiling part of the program statically. As of this writing, fakeroot actually exhibits accidental breaking away of processes run by an autoconf generated configure script.

Fakeroot-ng, on the other hand, uses a technology that leaves the actual program no say over whether it wants to be traced. The system calls hooks are enforced by the kernel, and the data stored in the pages mapped into the process is protected by the machine's MMU from alteration. While the system may not be full proof, it can be made so if desired.

Relative Roles

Fakeroot-ng is not likely to kill fakeroot, nor is it likely to any time soon. Fakeroot's wider platform support and better performance means it is likely to be the preferred tool wherever it gets the job done. Fakeroot is still continuously developed, and, in any case, is much more mature than fakeroot-ng.

That said, fakeroot-ng does have capabilities that fakeroot does not, and where those are needed, it makes an excellent tool.