Summary
The smsd daemon should create its PID file before dropping
privileges. This represents a minor security issue; additional factors
are needed to make it exploitable.
Details
The purpose of the PID file is to hold the PID of the running daemon,
so that later it can be stopped, restarted, or otherwise signalled
(many daemons reload their configurations in response to a SIGHUP).
To fulfil that purpose, the contents of the PID file need to be
trustworthy. If the PID file is writable by a non-root user, then he
can replace its contents with the PID of a root process. Afterwards,
any attempt to signal the PID contained in the PID file will instead
signal a root process chosen by the non-root user (a vulnerability).
This is commonly exploitable by init scripts that are run as root and
which blindly trust the contents of their PID files. The SMS Server
Tools themselves ship such an init script, scripts/sms3, which
contains e.g. the following:
In the above snippet, the contents of the $PID variable are controlled
by the smsd daemon user, while "kill" is run as root.
Exploitation
An example of a problematic scenario involving an init script would be,
1. I run "/etc/init.d/smsd start" to start the daemon.
2. smsd drops to the "smsd" user.
3. smsd writes its PID file, now owned by the "smsd" user.
4. Someone compromises the daemon.
5. The attacker is generally limited in what he can do because the
daemon doesn't run as root. However, he can write "1" into the
PID file, and he does.
6. I run "/etc/init.d/smsd stop" to stop the daemon while I investigate
the weird behavior resulting from the hack.
7. The machine reboots, because I killed PID 1 (this is normally restricted
to root).
Resolution
The problem is avoided by creating the PID file as root, before dropping
privileges.
Note however that currently, smsd tries to clean up its PID file if the
daemon terminates abnormally:
That will no longer be possible if the PID file is owned by root and the
daemon is running as a restricted user. Instead, the init system should
check to see if killing the daemon worked, and if it did, remove the PID
file.