Using LD_PRELOAD to override a function
This was blatantly stolen from technovelty, kept here because I hate it when my bookmarks die.
For some reason, people seem to get this quite wrong a lot of the time. Certainly one should not be playing with symbols that start with __ unless you really know what you're doing with them.
pid_t getpid(void) return orig_getpid(); ianw@lime:~/tmp/override$ cat test.c int main(void) ianw@lime:~/tmp/override$ gcc -shared -fPIC -o liboverride.so override.c -ldlianw@lime:~/tmp/override$ cat override.c
#define _GNU_SOURCE 1
#include
#include
#include
#include
#include
{
pid_t (*orig_getpid)(void) = dlsym(RTLD_NEXT, "getpid");
printf("Calling GETPID\n");
}
#include
#include
#include
{
printf("%d\n", getpid());
}
ianw@lime:~/tmp/override$ gcc -o test test.c
ianw@lime:~/tmp/override$ LD_PRELOAD=./liboverride.so ./test
Calling GETPID
15187
How difficult is it to misuse the code you write?
I found these "misuse levels" over at technovelty, which they originally ripped from Rusty Russel's Bleeding Edge Page, which is a page you should definitely check out if you haven't.
Anyway, I found these "misuse levels" both hilarious to read and at the same time somewhat concerning, as I started thinking "Where does my code really go on this list?"
- Impossible to get wrong
- Compiler/linker won't let you get it wrong
- Compiler/linker warns if you get it wrong
- Simplest use is correct
- The name tells you how to use it
- Do it right or breaks at runtime
- Follow the convention and you will get it right
- Read the documentation and you will get it right
- Read the implementation and you will get it right
- Read the correct mailing list and you will get it right
- Read the documentation and you will get it wrong
- Follow the convention and you will get it wrong
- Do it right and it will break at runtime
- The name tells you how not to use it
- The obvious use is wrong
- Compiler/linker will warn you if you get it right
- Compiler/linker won't let you get it right
- Impossible to get right
Debian and Ubuntu auto-login and Xorg without a display manager
If you have a harddrive password (most laptops do this) or full disk encryption, you might not feel the need for an additional login after your system boots.
On most Debian-based systems, TTY's 1 through 6 are available after boot, while TTY 7 is used for Xorg. Therefore, I like to put my auto-login TTY on TTY 8, so it's out of the way and leaves TTY 1 available for troubleshooting and similar.
Auto-login to Xorg requires two things: The actual auto-login and a script which loads Xorg.
First things first. The autologin.
In the olden days on a Debian system, this was done by adding a line similar to this one in /etc/inittab:
8:23:respawn:/bin/login -f bolt tty8 /dev/tty8 2>&1
This spawns a TTY 8 and logs in as "bolt" (change to suit your needs). It will do so on runlevels 2 and 3.
Now, however, the tool "rungetty" is generally used for this, as it's more flexible and performs the same functions with a cleaner syntax. First, "apt-get install rungetty" to make sure it's there, then add a line similar to the following:
8:3:respawn:/sbin/rungetty tty8 --autologin bolt
Note that on Debian Lenny and older, the version of rungetty has a specific check in code which only allows --autologin to work on tty1. If asked to autologin on another tty, rungetty would silently fail and spawn a normal login tty. This restriction has been removed from Squeeze and onwards.
On Ubuntu 10.10, the tty configuration is not in /etc/inittab. There, you have to add a file called "/etc/init.d/tty8.conf" with the following contents:
# tty8 - getty
#
# This service maintains a getty on tty8 from the point the system is
# started until it is shut down again.
start on runlevel [23]
stop on runlevel [!23]
respawn
exec /sbin/rungetty tty8 --autologin bolt
I basically copied tty6.conf and modified it to make that.
Autostarting Xorg
So by default when you login, both Debian and Ubuntu will leave you with a bash prompt, and very little graphical goodness. Thus, you want your login script to start Xorg, but only if Xorg is not already running, and we're on tty8. Otherwise, switching from Xorg to a console with, for example, ctrl+alt+f1, would cause another attempt to launch Xorg.
Thus I made this script, named ".bash_login", and put it in my home directory.
# ~/.bash_login: executed by bash(1) for login shells.
# include .profile if it exists
if [ -f "${HOME}/.profile" ] && [ -r "${HOME}/.profile" ]; then
source "${HOME}/.profile"
fi
# if we're not root and we're logged in on tty8, we assume a rungetty autologin and start xorg
if [ ! -z "${UID:-}" ] && [ "$UID" != "0" ] && [ -z "${DISPLAY}" ] && [ ! -z "${SHLVL:-}" ] && [ "$SHLVL" == "1" ]; then
if [ "$(tty)" == "/dev/tty8" ]; then
trap "chvt 1; logout" INT TERM EXIT
chvt 8
while true; do
echo "starting xorg"
startx
echo "sleeping 2 seconds"
sleep 2
done
fi
fi
This script will do a few sanity checks, then run Xorg. If Xorg exits, it will sleep 2 seconds and run it again. If the script is told to stop, it will change to tty1, then logout of tty8.