For a variety of reasons, Robert's company needed to ship a small linux box with a USB ethernet adapter. The driver for said adapter was giving him some issues with their setup, but fortunately the driver was open source, so Robert could at least try and diagnose the problems.

In the file inst.c, he found this:

#include <stdio.h>

main()
{
	
system("mkdir /usr/lib/smm9431");
system("cp scm9431.ko  /usr/lib/smm9431");
system("insmod scm9431.ko");
system("touch /tmp/nprtmp");
system("grep -v 'cd /usr/lib/smm9431' /etc/rc.d/rc.local > /tmp/nprtmp");
system("cp /tmp/nprtmp /etc/rc.d/rc.local > /dev/null 2>&1");
system("rm -f /tmp/nprtmp > /dev/null 2>&1");
system("echo 'cd /usr/lib/smm9431' >> /etc/rc.d/rc.local");
system("ln -s /etc/rc.d/rc.local /etc/rc.local > /dev/null 2>&1");
system("chmod 755 /etc/rc.d/rc.local");

system("touch /tmp/nprtmp");
system("grep -v smmdriver /etc/rc.d/rc.local > /tmp/nprtmp");
system("cp /tmp/nprtmp /etc/rc.d/rc.local > /dev/null 2>&1");
system("rm -f /tmp/nprtmp > /dev/null 2>&1");
system("echo 'insmod scm9431.ko ' >> /etc/rc.d/rc.local");
system("ln -s /etc/rc.d/rc.local /etc/rc.local > /dev/null 2>&1");
system("chmod 755 /etc/rc.d/rc.local");

}

This is, of course, a shell script with extra steps. The call to system is just a call to the shell to luanch new processes to execute each step. I do not know why it was done this way.

Even once we get past "you wrote your shell script in C", the whole thing is a bit weird. It's worth noting that this was about a decade ago, so it made more sense that this was designed for SystemV's init architecture.

It starts fine- make a directory, copy our kernel module into the tirectory, an insmod it. Then we touch a file because we're going to redirect output to it. We take rc.local an find every line that isn't cd /usr/lib/smm9431, and pipe it to that temp file. Then we copy that file right back over rc.local just so we can… echo that line in again.

It's not useless, as it ensures that the cd is the last line. Then we repeat this process to remove any lines containing smmdriver (probably an old version) and put an insmod at the end- ensuring that our rc.local script will load the driver on next boot.

Now, at this point in my life, I've been infected by the systemd brainworms, and have forgotten most of the SysV configuration, but most distros let you have rdN.d directories, where N is the runlevel you want the script to run at, and drivers can just create a script at that runlevel- they don't need to munge your rc.local to make this happen. I don't really love all the ways in which this mucks with your rc.local file.

Which, there's a huge difference between this and a shell script. In a shell script, if a command fails, the script stops. Here, if a command fails, system() returns the exit status of the command- an exit status we are not checking here. While it's unlikely, there's a world where the touch works, the grep fails, and then we copy an empty file back over rc.local.

[Advertisement] Keep the plebs out of prod. Restrict NuGet feed privileges with ProGet. Learn more.