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 apt-get update
.
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.
It's because 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_reset
, configure env_keep
to env_keep='LD_PRELOAD LD_LIBRARY_PATH'
, add SETENV
tag everywhere and execute sudo
with -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
The fix is very simple, just symlink your libary to /usr/lib
# ln -s /usr/lib/x86_64-linux-gnu/libeatmydata.so /usr/lib/libeatmydata.so
and do LD_PRELOAD
with full path:
export LD_PRELOAD=/usr/lib/libeatmydata.so
With this done you don’t have to set LD_LIBRARY_PATH
any more. Next, execute sudo
passing 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 .bashrc
:
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]
shitpoet@gmail.com