Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 3 Jan 2007 11:51:22 +0200
From:      "Erik Udo" <erik.udo@gmail.com>
To:        freebsd-hackers@freebsd.org
Subject:   Re: Init.c, making it chroot
Message-ID:  <6e3d78920701030151o3bcbf129yeff694d9f064985f@mail.gmail.com>
In-Reply-To: <4592C91C.2040801@gmail.com>
References:  <4592C91C.2040801@gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

[-- Attachment #1 --]
I just made patch. It's supposed to run /etc/rc before chrooting. This is
the NetBSD "way" of doing it. All i can say is that it compiled. So if
anyone can look at it before i get to test it becouse i might be forgetting
something. (i can't even test it now)

diff attached.

On 12/27/06, Erik Udo <erik.udo@gmail.com> wrote:
>
> How can i make init chroot after executing /etc/rc, and executing
> /etc/rc again in the chrooted enviroment?
>
> For this to work, i'd like to know at what point do i call chroot(),
> becouse init.c uses fork() at the point where it runs the rc script.
>
> The thing is, i want to run a whole system in a chrooted enviroment in
> this livecd i'm making. But the command "chroot /mnt/root /etc/rc"
> returns after the /etc/rc has been run, dropping me back from the
> chrooted enviroment. And if it doesn't, init never starts the multiuser
> mode.
>
> So how can i go to the multiuser mode in a chrooted enviroment? I guess
> the only way to do that is to modify init.c
>
> Any help/feedback is appreciated.
>
> Cheers, Erik
>
> _______________________________________________
> freebsd-hackers@freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
> To unsubscribe, send any mail to "freebsd-hackers-unsubscribe@freebsd.org"
>

[-- Attachment #2 --]
--- init.c.orig	Wed Jan  3 09:17:33 2007
+++ init.c	Wed Jan  3 10:08:38 2007
@@ -67,6 +67,7 @@
 #include <unistd.h>
 #include <sys/reboot.h>
 #include <err.h>
+#include <kenv.h>
 
 #include <stdarg.h>
 
@@ -115,6 +116,7 @@
 
 state_func_t single_user(void);
 state_func_t runcom(void);
+state_func_t runetcrc(int trychroot);
 state_func_t read_ttys(void);
 state_func_t multi_user(void);
 state_func_t clean_ttys(void);
@@ -175,12 +177,17 @@
 
 void clear_session_logs(session_t *);
 
+int shouldchroot(void);
+char init_chroot[PATH_MAX];
+int did_multiuser_chroot;
+
 int start_session_db(void);
 void add_session(session_t *);
 void del_session(session_t *);
 session_t *find_session(pid_t);
 DB *session_db;
 
+
 /*
  * The mother of all processes.
  */
@@ -718,6 +725,38 @@
 state_func_t
 runcom(void)
 {
+	state_func_t next_step;
+
+	/* Run /etc/rc and choose next state depending on the result. */
+	next_step = runetcrc(0);
+	if (next_step != (state_func_t) read_ttys)
+		return (state_func_t) next_step;
+
+	if (shouldchroot()) {
+		next_step = runetcrc(1);
+		if (next_step != (state_func_t) read_ttys)
+			return (state_func_t) next_step;
+
+		did_multiuser_chroot = 1;
+	} else {
+		did_multiuser_chroot = 0;
+	}
+
+	/*
+	 * Regardless of whether in chroot or not, we booted successfuly.
+	 * It's time to spawn gettys (ie. next_step's value at this point).
+	 */
+	runcom_mode = AUTOBOOT;		/* the default */
+	logwtmp("~", "reboot", "");
+	return (state_func_t) read_ttys;
+}
+
+/*
+ * Run the system startup script.
+ */
+state_func_t
+runetcrc(int trychroot)
+{
 	pid_t pid, wpid;
 	int status;
 	char *argv[4];
@@ -743,6 +782,12 @@
 
 		sigprocmask(SIG_SETMASK, &sa.sa_mask, (sigset_t *) 0);
 
+		if (trychroot)
+			if (chroot(init_chroot) != 0) {
+				warning("failed to chroot to `%s': %m",
+				    init_chroot);
+				_exit(1); 	/* force single user mode */
+			}
 #ifdef LOGIN_CAP
 		setprocresources(RESOURCE_RC);
 #endif
@@ -803,9 +848,6 @@
 	if (WEXITSTATUS(status))
 		return (state_func_t) single_user;
 
-	runcom_mode = AUTOBOOT;		/* the default */
-	/* NB: should send a message to the session logger to avoid blocking. */
-	logwtmp("~", "reboot", "");
 	return (state_func_t) read_ttys;
 }
 
@@ -1633,3 +1675,22 @@
 	}
 }
 #endif
+
+
+int shouldchroot(void) {
+	char icname[] = "init_chroot";
+	*init_chroot = '\0';
+
+	if(kenv(KENV_GET, icname, init_chroot, 
+           sizeof(init_chroot)) == -1) {
+		warning("Can't fetch init_chroot from kenv(): %m");
+		return 0;
+	}
+
+	if (chdir(init_chroot) != 0 || chroot(".") != 0) {
+		warning("Can't chroot to %s: %m", init_chroot);
+		return 0;
+	}
+
+	return 1;
+}

Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6e3d78920701030151o3bcbf129yeff694d9f064985f>