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

 



 

free hit counters