Breaking into RedHat/CentOS 7

So, that time’s come around I guess — time to get moving and figure out how Red Hat Enterprise Linux 7 / CentOS 7 tick. Today’s fun-time task was to get familiar with systemd, the controversial replacement for init.

Being relatively au-fait with starting and stopping services with systemctl already (despite my tendancy to type sysctl instead), I decided to brush up on runlevels. Or rather, the lack thereof!

I soon gathered that we’ve replaced runlevels with targets. Four important ones:

  • graphical.target is basically runlevel 5.
  • multi-user.target is basically runlevel 3.
  • rescue.target, single-user(-ish). Root mounted read-write.
  • emergency.target, closest to runlevel 1. Root mounted read-only.

We can switch to these targets by using systemctl isolate <target>. However, it amused me that the init command still works in the classic fashion (for example, issuing init 6 to reboot the system), even though it’s a symlink to /usr/lib/systemd/systemd. A nice touch, for backwards compatibility!

rescue.target and emergency.target both need the system’s current root password in order to obtain a shell. However, one reason for going into single-user mode may be to reset a root password that someone’s long since lost.

In el5 and el6, the trick was to pass init=/bin/bash to the kernel parameter from the bootloader. This executed a root shell as process ID 1 instead of the usual init program.

That doesn’t work in el7, however. We’ve got a slightly different dance to do. Instead, we pass rd.break as a kernel parameter from the bootloader to interrupt the boot sequence and drop to a root shell. Here’s how:

  • Reboot.
  • Press any key before your kernel boots to access at the GRUB2 menu.
  • Hit `e` to edit the default kernel line.
  • Find the line that starts with linux16 and append rd.break to it.
  • Continue with Control+X.

After a minute, we’re at the same place you’d be if you’d appended init=/bin/bash to the kernel parameters of any init-controlled Linux box. Except that our root partition is handily already mounted read-only under /sysroot.

Let’s change that root password:

  • Remount /sysroot read-write with mount -o remount,rw /sysroot.
  • Switch into a chroot jail using with chroot /sysroot.
  • Change root’s password with passwd.

I rebooted here. Big mistake.

My test box was set to boot into graphical.target (runlevel 5, to me). However, my graphical user environment failed to load. I had a black screen. From outside, I could see that sshd was running and responding to my connection attempts, but none of my login attempts were honoured — I kept getting authentication failures. What happened?

I rebooted, broke back in and checked out the system log. Read some stuff. Saw the ill-fated word: SELinux. Damn.

To fix it, I had to:

# touch /.autorelabel
# exit
# exit

Everything came back up in a few minutes, sweet as a nut.

Cause? The passwd command seems to create a new set of files before moving them into place. So, that’ll be a new file with an incorrect SELinux context, then.

That’ll teach me for being itchy with the ol’ reboot. Story of my life, really.