Page MenuHomeFreeBSD

D58164.id181756.diff
No OneTemporary

D58164.id181756.diff

diff --git a/sbin/Makefile b/sbin/Makefile
--- a/sbin/Makefile
+++ b/sbin/Makefile
@@ -25,6 +25,8 @@
ggate \
growfs \
ifconfig \
+ reroot_seed \
+ .WAIT \
init \
kldconfig \
kldload \
diff --git a/sbin/init/Makefile b/sbin/init/Makefile
--- a/sbin/init/Makefile
+++ b/sbin/init/Makefile
@@ -2,9 +2,11 @@
PACKAGE=runtime
PROG= init
MAN= init.8
+SRCS= init.c reroot_seed.embed.s
PRECIOUSPROG=
INSTALLFLAGS=-b -B.bak
-CFLAGS+=-DDEBUGSHELL -DSECURE -DLOGIN_CAP -DCOMPAT_SYSV_INIT
+CFLAGS.init.c+=-DDEBUGSHELL -DSECURE -DLOGIN_CAP -DCOMPAT_SYSV_INIT
+ACFLAGS.reroot_seed.embed.s+=-I${.OBJDIR}/../reroot_seed
LIBADD= util crypt
CONFTTYSNAME= ttys
diff --git a/sbin/init/init.c b/sbin/init/init.c
--- a/sbin/init/init.c
+++ b/sbin/init/init.c
@@ -116,7 +116,6 @@
static state_func_t death(void);
static state_func_t death_single(void);
static state_func_t reroot(void);
-static state_func_t reroot_phase_two(void);
static state_func_t run_script(const char *);
@@ -269,7 +268,7 @@
* This code assumes that we always get arguments through flags,
* never through bits set in some random machine register.
*/
- while ((c = getopt(argc, argv, "dsfr")) != -1)
+ while ((c = getopt(argc, argv, "dsf")) != -1)
switch (c) {
case 'd':
devfs = true;
@@ -280,9 +279,6 @@
case 'f':
runcom_mode = FASTBOOT;
break;
- case 'r':
- initial_transition = reroot_phase_two;
- break;
default:
warning("unrecognized flag '-%c'", c);
break;
@@ -388,15 +384,13 @@
free(s);
}
- if (initial_transition != reroot_phase_two) {
- /*
- * Unmount reroot leftovers. This runs after init(8)
- * gets reexecuted after reroot_phase_two() is done.
- */
- error = unmount(_PATH_REROOT, MNT_FORCE);
- if (error != 0 && errno != EINVAL)
- warning("Cannot unmount %s: %m", _PATH_REROOT);
- }
+ /*
+ * Unmount reroot leftovers. This runs after init(8) gets
+ * re-executed after reroot_seed is done.
+ */
+ error = unmount(_PATH_REROOT, MNT_FORCE);
+ if (error != 0 && errno != EINVAL)
+ warning("Cannot unmount %s: %m", _PATH_REROOT);
/*
* Start the state machine.
@@ -628,57 +622,6 @@
write(STDERR_FILENO, message, strlen(message));
}
-static int
-read_file(const char *path, void **bufp, size_t *bufsizep)
-{
- struct stat sb;
- size_t bufsize;
- void *buf;
- ssize_t nbytes;
- int error, fd;
-
- fd = open(path, O_RDONLY);
- if (fd < 0) {
- emergency("%s: %m", path);
- return (-1);
- }
-
- error = fstat(fd, &sb);
- if (error != 0) {
- emergency("fstat: %m");
- close(fd);
- return (error);
- }
-
- bufsize = sb.st_size;
- buf = malloc(bufsize);
- if (buf == NULL) {
- emergency("malloc: %m");
- close(fd);
- return (error);
- }
-
- nbytes = read(fd, buf, bufsize);
- if (nbytes != (ssize_t)bufsize) {
- emergency("read: %m");
- close(fd);
- free(buf);
- return (error);
- }
-
- error = close(fd);
- if (error != 0) {
- emergency("close: %m");
- free(buf);
- return (error);
- }
-
- *bufp = buf;
- *bufsizep = bufsize;
-
- return (0);
-}
-
static int
create_file(const char *path, const void *buf, size_t bufsize)
{
@@ -738,16 +681,13 @@
return (0);
}
+extern char reroot_seed_start[], reroot_seed_end[];
+
static state_func_t
reroot(void)
{
- void *buf;
- size_t bufsize;
int error;
- buf = NULL;
- bufsize = 0;
-
revoke_ttys();
runshutdown();
@@ -766,13 +706,11 @@
* Copy the init binary into tmpfs, so that we can unmount
* the old rootfs without committing suicide.
*/
- error = read_file(init_path_argv0, &buf, &bufsize);
- if (error != 0)
- goto out;
error = mount_tmpfs(_PATH_REROOT);
if (error != 0)
goto out;
- error = create_file(_PATH_REROOT_INIT, buf, bufsize);
+ error = create_file(_PATH_REROOT_INIT, reroot_seed_start,
+ reroot_seed_end - reroot_seed_start);
if (error != 0)
goto out;
@@ -782,58 +720,6 @@
execl(_PATH_REROOT_INIT, _PATH_REROOT_INIT, "-r", NULL);
emergency("cannot exec %s: %m", _PATH_REROOT_INIT);
-out:
- emergency("reroot failed; going to single user mode");
- free(buf);
- return (state_func_t) single_user;
-}
-
-static state_func_t
-reroot_phase_two(void)
-{
- char init_path[PATH_MAX], *path, *path_component;
- size_t init_path_len;
- int nbytes, error;
-
- /*
- * Ask the kernel to mount the new rootfs.
- */
- error = reboot(RB_REROOT);
- if (error != 0) {
- emergency("RB_REBOOT failed: %m");
- goto out;
- }
-
- /*
- * Figure out where the destination init(8) binary is. Note that
- * the path could be different than what we've started with. Use
- * the value from kenv, if set, or the one from sysctl otherwise.
- * The latter defaults to a hardcoded value, but can be overridden
- * by a build time option.
- */
- nbytes = kenv(KENV_GET, "init_path", init_path, sizeof(init_path));
- if (nbytes <= 0) {
- init_path_len = sizeof(init_path);
- error = sysctlbyname("kern.init_path",
- init_path, &init_path_len, NULL, 0);
- if (error != 0) {
- emergency("failed to retrieve kern.init_path: %m");
- goto out;
- }
- }
-
- /*
- * Repeat the init search logic from sys/kern/init_path.c
- */
- path_component = init_path;
- while ((path = strsep(&path_component, ":")) != NULL) {
- /*
- * Execute init(8) from the new rootfs.
- */
- execl(path, path, NULL);
- }
- emergency("cannot exec init from %s: %m", init_path);
-
out:
emergency("reroot failed; going to single user mode");
return (state_func_t) single_user;
diff --git a/sbin/init/reroot_seed.embed.s b/sbin/init/reroot_seed.embed.s
new file mode 100644
--- /dev/null
+++ b/sbin/init/reroot_seed.embed.s
@@ -0,0 +1,4 @@
+ .globl reroot_seed_start, reroot_seed_end
+reroot_seed_start:
+ .incbin "reroot_seed"
+reroot_seed_end:
diff --git a/sbin/reroot_seed/Makefile b/sbin/reroot_seed/Makefile
new file mode 100644
--- /dev/null
+++ b/sbin/reroot_seed/Makefile
@@ -0,0 +1,6 @@
+PROG= reroot_seed
+MAN=
+NO_SHARED= YES
+INTERNALPROG= YES
+
+.include <bsd.prog.mk>
diff --git a/sbin/reroot_seed/reroot_seed.c b/sbin/reroot_seed/reroot_seed.c
new file mode 100644
--- /dev/null
+++ b/sbin/reroot_seed/reroot_seed.c
@@ -0,0 +1,109 @@
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at Berkeley Software Design, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/reboot.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <kenv.h>
+#include <paths.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+
+static void emergency(const char *, ...) __printflike(1, 2);
+
+static void
+emergency(const char *message, ...)
+{
+ va_list ap;
+ va_start(ap, message);
+
+ vsyslog(LOG_EMERG, message, ap);
+ va_end(ap);
+}
+
+int
+main(void)
+{
+ char init_path[PATH_MAX], *path, *path_component;
+ size_t init_path_len;
+ int nbytes, error;
+
+ openlog("init", LOG_CONS, LOG_AUTH);
+
+ /*
+ * Ask the kernel to mount the new rootfs.
+ */
+ error = reboot(RB_REROOT);
+ if (error != 0) {
+ emergency("RB_REBOOT failed: %m");
+ _exit(1);
+ }
+
+ /*
+ * Figure out where the destination init(8) binary is. Note that
+ * the path could be different than what we've started with. Use
+ * the value from kenv, if set, or the one from sysctl otherwise.
+ * The latter defaults to a hardcoded value, but can be overridden
+ * by a build time option.
+ */
+ nbytes = kenv(KENV_GET, "init_path", init_path, sizeof(init_path));
+ if (nbytes <= 0) {
+ init_path_len = sizeof(init_path);
+ error = sysctlbyname("kern.init_path",
+ init_path, &init_path_len, NULL, 0);
+ if (error != 0) {
+ emergency("failed to retrieve kern.init_path: %m");
+ _exit(1);
+ }
+ }
+
+ /*
+ * Repeat the init search logic from sys/kern/init_path.c
+ */
+ path_component = init_path;
+ while ((path = strsep(&path_component, ":")) != NULL) {
+ /*
+ * Execute init(8) from the new rootfs.
+ */
+ execl(path, path, NULL);
+ }
+ emergency("cannot exec init from %s: %m", init_path);
+ _exit(1);
+}

File Metadata

Mime Type
text/plain
Expires
Mon, Jul 13, 1:21 AM (10 h, 26 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35019677
Default Alt Text
D58164.id181756.diff (9 KB)

Event Timeline