Eat ALL my data
or how to LD_PRELOAD with sudo
+10 to unsafety]
eatmydata is a library that blocks an application to
fsync. It speeds up actions that frequently
fsync data, such as
apt-get update. (What is
fsync? It’s when an application made some writes to disk and wants to be sure that all data have been safely written: the app calls for
fsync and system flushes all dirty pages to disk, synchronously, which is very sloow. If you’re lucky the system will sync dirty pages that belong to your application only but it is still slow.)
We’ll better do this:
$ sudo eatmydata apt-get update
and notice speed imporovement in
But we can go even further, and "eat" our whole desktop!
How eatmydata works
Here's a (a little simplified) piece of
eatmydata shell script which configures
libeatmydata to load into an app:
# set up environment LD_LIBRARY_PATH=/usr/lib/libeatmydata LD_PRELOAD=libeatmydata.so export LD_LIBRARY_PATH LD_PRELOAD
So, as you can see, it's pretty simple.
LD_PRELOAD is the name of library to inject and
LD_LIBRARY_PATH is the path where to search it.
To make all our data eaten we just add this code to our
.bashrc or f.ex.
environment script of openbox or whatever WM you like.
How eatmydata doesn't work
But if you log in with "eatmydated" desktop and try to
sudo something you receive such an error:
$ sudo apt-get update ERROR: ld.so: object 'libmydata.so.3' from LD_PRELOAD cannot be preloaded: ignored.
sudo works hard(-coded) to guard you from your dirty tricks. It filters out all
LD_* environment variables what can be checked through funny command
sudo sudo -V:
Environment variables to remove: RUBYOPT RUBYLIB PYTHONUSERBASE PYTHONINSPECT PYTHONPATH PYTHONHOME TMPPREFIX ZDOTDIR READNULLCMD NULLCMD FPATH PERL5DB PERL5OPT PERL5LIB PERLLIB PERLIO_DEBUG JAVA_TOOL_OPTIONS SHELLOPTS GLOBIGNORE PS4 BASH_ENV ENV TERMCAP TERMPATH TERMINFO_DIRS TERMINFO _RLD* LD_* PATH_LOCALE NLSPATH HOSTALIASES RES_OPTIONS LOCALDOMAIN CDPATH IFS
sudo has config in
/etc/sudoers file, where we can control these white and black lists of variables. But even if you comment out
env_keep='LD_PRELOAD LD_LIBRARY_PATH', add
SETENV tag everywhere and execute
-E (don’t reset environment) flag the error will stay. To be exact with all this done
sudo will keep
LD_* variables for the program you execute with it but for itself it still will ignore them.
The fix is very simple, just symlink your libary to
# ln -s /usr/lib/x86_64-linux-gnu/libeatmydata.so /usr/lib/libeatmydata.so
LD_PRELOAD with full path:
With this done you don’t have to set
LD_LIBRARY_PATH any more. Next, execute
LD_PRELOAD to it as command line parameter:
$ sudo LD_PRELOAD=/usr/lib/libeatmydata.so apt-get update
sudo will find and load the library as expected. (Note also that this will work with default
sudoers file because command line arguments have bigger priority here.) Last thing is to add such an alias to
alias sudo='sudo LD_PRELOAD=/usr/lib/libeatmydata.so'
In this configuration all the programs in our desktop environment and those ones that were called by
sudo interactively (from bash) will be sync-free.
Cheers, and backup your data]