Scheduled Maintenance: We are aware of an issue with Google, AOL, and Yahoo services as email providers which are blocking new registrations. We are trying to fix the issue and we have several internal and external support tickets in process to resolve the issue. Please see: viewtopic.php?t=158230

 

 

 

Creating and using a custom OS initialiser.

Share your HowTo, Documentation, Tips and Tricks. Not for support questions!.
Post Reply
Message
Author
User avatar
edbarx
Posts: 5401
Joined: 2007-07-18 06:19
Location: 35° 50 N, 14 º 35 E
Been thanked: 2 times

Creating and using a custom OS initialiser.

#1 Post by edbarx »

Contrary to what many might imagine, an OS init is not rocket science but can be implemented under 20 lines of C code. This seemingly impossible feat was accomplished by Rich Felker author of musl libc. The code is as follows:

Source: https://gist.github.com/rofl0r/6168719

Code: Select all

#define _XOPEN_SOURCE 700
#include <signal.h>
#include <unistd.h>

int main()
{
	sigset_t set;
	int status;

	if (getpid() != 1) return 1;

	sigfillset(&set);
	sigprocmask(SIG_BLOCK, &set, 0);

	if (fork()) for (;;) wait(&status);

	sigprocmask(SIG_UNBLOCK, &set, 0);

	setsid();
	setpgid(0, 0);
	return execve("/etc/rc", (char *[]){ "rc", 0 }, (char *[]){ 0 });
} 
What does the code do?
First it checks whether the user is root exiting if the user in not root. Then, it blocks all messages before forking the process to produce a child that is used to do the actual OS loading. The fork works as follows: in the calling process, the parent process, fork() returns the non-zero PID of the child while in the newly created child process it returns 0. Execution in the child follows from the same point in the parent. This means, the parent process will enter the infinite loop that repeatedly calls wait(&status) which clears zombies from the kernel's process table completely freeing their resources. In the child, as a result of fork() returning 0, the infinite loops is skipped and the succeeding lines of code are executed. The first instruction is to unblock messages so that newly created processes can communicate. At the end, it calls execve which replaces the child process with a shell that runs /etc/rc. Under Debian the rc script is found under /etc/init.d.

I found using /etc/init.d/rc directly does not successfully load Debian or Devuan provided /etc/init.d is properly filled with scripts and rcN and not emplty. I used a simple shell script to first call "rc S" and then "rc 2". This successfully loaded a useable operating system.

The custom script to load the OS:

Code: Select all

#!/bin/sh

if /etc/init.d/rc S; then
  /etc/init.d/rc 2
fi
I modified Felker's code as follows so that the above script would run. I placed the script under /sbin with all execution bits set using chmod 755 osloader.sh. I named the script osloader.sh.

Modified Felker's C init to load Devuan/Debian provided there /etc/init.d is properly populated and /etc/rcN directories are filled with working symbolic links.

Code: Select all

#define _XOPEN_SOURCE 700
#include <signal.h>
#include <unistd.h>

int main()
{
	sigset_t set;
	int status;

	if (getpid() != 1) return 1;

	sigfillset(&set);
	sigprocmask(SIG_BLOCK, &set, 0);

	if (fork()) for (;;) wait(&status);

	sigprocmask(SIG_UNBLOCK, &set, 0);

	setsid();
	setpgid(0, 0);
	return execve("/sbin/osloader.sh", (char *[]){ 0 }, (char *[]){ 0 });
} 
Debian == { > 30, 000 packages }; Debian != systemd
The worst infection of all, is a false sense of security!
It is hard to get away from CLI tools.

Post Reply