Thursday, November 20, 2014

Sudo on Minix 3.1.8

Minix 3.3.0 came out a while ago and I had all kinds of fun playing with it.  I'd long been running 3.2.1 but never gave 3.1.8 a try at all.  The fun I had with 3.3.0 got me motivated though and a few weeks back I gave it a shot.

It was fairly straightforward, for the most part.  A few things here and there reminded me of 2.0 but the overall user experience was similar to 3.2.1.  Getting various bits of software running required many of the same tweaks that 3.3.0 and 3.2.1 required, but the most difficult bit by far was sudo.

Sudo 1.7.something-or-other is available via pkgin but it dumps core whenever you do anything with it.

Sudo version 1.6.9p23 has been reliably portable for me though, so I gave it a try.  It took a while to work around various issues, but eventually I got it working.  If anyone out there is interested, here are the tricks:

The code requires a little hackery.

Add the following line after the includes in interfaces.c

#define IFF_LOOPBACK IFF_UP

Edit sudo.tab.c and comment out:

# include <search.h>

it should look like this when you're done:

/*# include <search.h>*/

Minix 3.1.8's implementation of getgroups always returns -1.  This causes a few problems for sudo.  To solve them, edit set_perms.c and make 3 modifications.

Make the declaration of runas_groups (around line 376) look like:

static GETGROUPS_T *runas_groups = NULL;
Update a section of the function runas_setgroups() as follows:

...
if (runas_ngroups <= 0) {
pw = runas_pw ? runas_pw : sudo_user.pw;
if (initgroups(pw->pw_name, pw->pw_gid) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector");

if ((runas_ngroups = getgroups(0, NULL)) > 0) {
runas_groups = emalloc2(runas_ngroups, sizeof(GETGROUPS_T));
if (getgroups(runas_ngroups, runas_groups) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector");
}

} else {
...

Update the function restore_groups() as follows:

static void
restore_groups()
{
if (user_ngroups > 0) {
if (setgroups(user_ngroups, user_groups) < 0)
log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector");
}
}

That third modification is actually a workaround for a bug (or feature) in setgroups().  It goes completely haywire if user_ngroups is -1.  I'll bet that this is the problem that the version of sudo available via pkgin has too.  There might be a libc update that fixes this issue but for now we'll just work around it.

Now build and install.  Some options needs to be enabled in the header files with the _POSIX_SOURCE macro, so we'll pass that in.  I also like to install it under it's own directory tree, so I use the --prefix option for that.

CPPFLAGS="-D_POSIX_SOURCE" ./configure --prefix=/usr/local/sudo-1.6.9p23
make
su
make install

The default permissions are wrong for Minix though, so they need to be set manually:

chmod 555 /usr/local/sudo-1.6.9p23/bin/sudo
chmod u+s /usr/local/sudo-1.6.9p23/bin/sudo

Now add a line for your user (dmuse in my case) to /etc/sudoers.

dmuse ALL=(ALL) NOPASSWD: ALL

Yes, the sudoers file is installed under /etc independent of the --prefix option used earlier.  The NOPASSWD option makes it so you don't have to enter a password.

And the last step is to add /usr/local/sudo-1.6.9p23/bin to your PATH in ~/.ashrc

export PATH=$HOME/bin:/usr/local/bin:/bin:/sbin:/usr/bin:/usr/sbin:\
/usr/pkg/X11R6/bin:/usr/pkg/bin:/usr/pkg/sbin:/usr/llvm/bin:\
/usr/local/sudo-1.6.9p23/bin

And that's it.  Re-login and sudo should work as expected.

$ sudo ls -l /
total 44
drwxr-xr-x 2 root operator 2880 Sep 4 2010 bin
drwxr-xr-x 3 root operator 384 Sep 4 2010 boot
drwxr-xr-x 2 root operator 29120 Sep 20 02:47 dev
drwxr-xr-x 3 root operator 2304 Nov 20 22:53 etc
drwxrwxrwx 5 bin bin 320 Sep 20 02:55 home
drwxrwxrwx 2 root operator 128 Sep 20 02:45 mnt
drwx------ 2 root operator 768 Sep 20 04:09 root
drwxr-xr-x 2 root operator 896 Sep 4 2010 sbin
drwxrwxrwt 2 root operator 640 Nov 20 23:52 tmp
drwxrwxrwx 23 bin bin 1536 Sep 20 03:27 usr
drwxr-xr-x 3 root operator 256 Sep 20 02:45 var

Woohoo!  Sudo on Minix 3.1.8.