Tag Archives: Unix

RIP sysvinit, welcome upstart

After Ubuntu and Fedora, Debian also migrates to upstart.

To summarize the article in the previous link, the main reason for the change is that the kernel is now no more blocking on some hardware scans, and this might make some init scripts (e.g. fsck, network) start before the device is initialized. We now need an event-based init system, so the kernel could "tell" it when the device is ready. This is something that upstart is capable of.

Now I wonder if RHEL6 would inherit upstart from Fedora, this will mean a complete victory for upstart.

/etc/mtab weirdness

There are many ways to fetch the list of currently-mounted-devices: read the files /etc/mtab, /proc/mounts, or exec /bin/mount, /bin/df.

I've been arguing with a colleague (Yaniv), that relying on /etc/mtab is no much worse than relying on /proc/mounts. But after we inspected it on Linux & Solaris (/etc/mnttab), I figured out that I was pretty wrong, and learned some new surprising facts:

On Linux:

  • /proc/mounts is a read-only, kernel-generated file.
  • /etc/mtab (Linux) is a regular file. It's kept up-to-date because the mount/umount commands modify it. It can be modified by a root user, moved and even deleted!
  • df command is using /etc/mtab, thus after rm'ing /etc/mtab, df would stop functioning.
  • mount command doesn't care about /etc/mtab, probably uses /proc/mounts or some internal kernel structure.

On Solaris (prepare for some weird stuff now):

  • Solaris has got /etc/mnttab, but no /proc/mounts equivalent.
  • /etc/mnttab is a mounted filesystem, of the mntfs type. So it's somewhat similar to /proc/mounts on Linux. It cannot be modified.
  • /etc/mnttab is actually a directory! (a mount point has to be a directory..)
  • /etc/mnttab can be unmounted, renamed, rmdir'd (when unmounted) and mounted anywhere else.
  • both df and mount rely on /etc/mnttab, thus not functioning when it's absent

On HP-UX:

  • /etc/mnttab, which is a regular file, is similar to /etc/mtab on Linux.

And on another, non-related subject: looks like Debian Lenny has got only 80 bugs to go (as of 19/01/09)! Go Lenny!

Init script dependency

"Behind my back", a new feature was added to LSB specification and to Debian Lenny accordingly: Init scripts dependency.

The new LSB defines new fields for init script headers: Required, Should (like Required but only if installed) and Provides. This means that the init system should take care of ordering the init scripts according to their dependencies (i.e. "NFS" service requires "portmap" service which requires network and thus order should be Network -> Portmap -> NFS). This eliminates the need to give funny "K01/S99"-style numbers manually to each service.

Cool. But is it enough? The init system is several decades old. Maybe we need something revolutionary such as Upstart or Solaris SMF. Features like starting/stopping independent services in parallel, service monitoring (watchdog/keepalive), or other crazy ideas that Upstart & SMF implement.

Ubuntu's Upstart was adopted also by Fedora 9; this means that RHEL6 might use Upstart as well. In that case, the revolution is over.. Debian, SuSE (and Windows maybe? 🙂 ) would probably follow.

Switch to another UID/GID, with Perl

Originally I wanted to start by describing Linux' setuid()-like functions, which change the user-id of a running process (and more). Some reading made me realize that this area is too big (but interesting!) for a simple post, and also that I still don't master it..

So I'll focus only a single, simple task: switching from root to regular user permissions: when a daemon is being run by root (i.e. init scripts), for security reasons we want them to "transform" to a regular user right asap. In the kernel level we want to do something like setuid or setresuid (set all the user identifiers: Real, Effective and Saved) to a specific, different UID.

However, we don't talk about the kernel, but about a much higher scripting language.. So let's begin with basics: according to perlvar manpage, $> (or $EUID if using 'use English') represents the Effective User ID (Effective is the User ID which matters permission-wise). "print $>" perl command would simply print the EUID.

Now for the surprise.. "$>=44" perl command simply sets the EUID! Oh, the simplicity 🙂

GID can be set in a similar manner, but can't be set after the the uid is switched (we need the initial root permission for the GID switch).

Enough talking, let the code begin:

#!/usr/bin/perl -w
use strict;
ues English;
$EGID=22;
$EUID=22;
sleep 50; # Sleep so we can have time to run "ps axo pid,uid,euid,gid,egid" :)