From nobody Mon Jul 20 20:53:21 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4h3t5g2nMzz6dPlp for ; Mon, 20 Jul 2026 20:53:27 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h3t5g0m0Mz47C4 for ; Mon, 20 Jul 2026 20:53:27 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1784580807; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=K99l8J6YOl+PW2tWBpFBNIMm3Ib8e193xiA7mUHZTgQ=; b=WO0pEEYmnwEsVSq3Hj4yJxBu5WZF+58tdjqIiMQGeAgYIP7ImlafPhggz/bRMebu7K8a2h Zv1mBqaERaQ3cioJSlJVPnyklx1m6DQEYAfvaLVPKki22/2YWOAa3rcgJBsDHABRYmeyOL PUNVsQ7qNjjlKY6GP/91An/x2UljmS62dbF4H7BeoUv3qtn1jMWy14QHfVHoR21LOqOfwf AIW6wk2g/YLlm//9fgSIIl3Tw2HYSp/78quN/OirQSeuUG1HD/L6uec4TdzeTLFL1iYCtr zGQqCCoameTcT2k9rB6fCHBt3NRSYs0BQ2g+2AiqWNiJoObrr8bA9c3UugeBUA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1784580807; a=rsa-sha256; cv=none; b=TJ7BwuFydLYWYlhMaROqlp0/rTwKo0+YBzKRwMTGnGIVvgGKu2CUc8yhTktNdQmO2NSjhw G+7+4cQljwH8uQQ3GIW0gyeBRxcNYl0oznJmFjo90yV8vOw36uxPxIVFic3aIMU9GcuD0L eeFoM3c0p6JGwpa80y6nuckXSSX7v/Z3EmC1r05mAXzKdp0OQ6DTOsIokEQ1bo2TC3/VEc SyktyIOWzLQumiaXNIWaTKmnXGPktxpEDcUYPMbY6SkVq9fz2tdIz6k9I0W51pV/761lQ1 CiNLRiuTmqTmebOZgdBvT5ZGIci98LbzQE+YRKExLVL1/r90wUXoxmy3XYpdpw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1784580807; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=K99l8J6YOl+PW2tWBpFBNIMm3Ib8e193xiA7mUHZTgQ=; b=E8zUBQU2Mo7KxMopqveAFn1IlPAVjX+p9TowSHEhXCeLwEXz66b6SnFrFzACySv/6A531C vp1XYCaoqZhylLp5Bk5FtluQE9h9JZmXG0aPLovF+mGA22vJmgYQJkBFuJ+KP1PkuFyvab z6F2WPI9Aren6DV0rrozgVDDusbQwozgJ5ul+uGPUaEkkEYuaVQMeZb+OVmVDrlC9zz9rH U+NcaVUJfqe5jl/NEMFt5wZ2bzpV/Us0usMff6a1pugfwAgUYFK+z2424CoZQScsTz+sRf 7AUnaEiRfOem4vlVy86fzb8ayi53R6svbNc5p+BmIgTTmxaGv3rtvlXur0EKBQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h3t5f6pMvz33h for ; Mon, 20 Jul 2026 20:53:26 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 1d590 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Mon, 20 Jul 2026 20:53:21 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Konstantin Belousov Subject: git: c7663578a278 - stable/15 - init(8): extract reroot transient code into reroot_seed List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kib X-Git-Repository: src X-Git-Refname: refs/heads/stable/15 X-Git-Reftype: branch X-Git-Commit: c7663578a278fa7ef76e035f197bc0cb462af198 Auto-Submitted: auto-generated Date: Mon, 20 Jul 2026 20:53:21 +0000 Message-Id: <6a5e8ac1.1d590.1fd5add@gitrepo.freebsd.org> The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=c7663578a278fa7ef76e035f197bc0cb462af198 commit c7663578a278fa7ef76e035f197bc0cb462af198 Author: Konstantin Belousov AuthorDate: 2026-07-10 19:02:54 +0000 Commit: Konstantin Belousov CommitDate: 2026-07-20 20:24:26 +0000 init(8): extract reroot transient code into reroot_seed (cherry picked from commit 4c9f648852629d757165796bb3cd97bb84a0e483) --- sbin/Makefile | 2 + sbin/init/Makefile | 9 +++- sbin/init/init.c | 91 +++++++++++++++++++++++++++------- sbin/init/reroot_seed.embed.s | 4 ++ sbin/reroot_seed/Makefile | 6 +++ sbin/reroot_seed/reroot_seed.c | 109 +++++++++++++++++++++++++++++++++++++++++ 6 files changed, 203 insertions(+), 18 deletions(-) diff --git a/sbin/Makefile b/sbin/Makefile index ef953e80ba1e..f936a9646fa9 100644 --- a/sbin/Makefile +++ b/sbin/Makefile @@ -25,6 +25,8 @@ SUBDIR=adjkerntz \ ggate \ growfs \ ifconfig \ + reroot_seed \ + .WAIT \ init \ kldconfig \ kldload \ diff --git a/sbin/init/Makefile b/sbin/init/Makefile index 342df4596a72..1e319f1bb828 100644 --- a/sbin/init/Makefile +++ b/sbin/init/Makefile @@ -2,9 +2,16 @@ CONFGROUPS= CONFTTYS PACKAGE=runtime PROG= init MAN= init.8 +SRCS= init.c PRECIOUSPROG= INSTALLFLAGS=-b -B.bak -CFLAGS+=-DDEBUGSHELL -DSECURE -DLOGIN_CAP -DCOMPAT_SYSV_INIT +CFLAGS.init.c+=-DDEBUGSHELL -DSECURE -DLOGIN_CAP -DCOMPAT_SYSV_INIT +.ifdef RESCUE +CFLAGS.init.c+=-DRESCUE +.else +SRCS+= reroot_seed.embed.s +ACFLAGS.reroot_seed.embed.s+=-I${OBJTOP}/sbin/reroot_seed +.endif LIBADD= util crypt CONFTTYSNAME= ttys diff --git a/sbin/init/init.c b/sbin/init/init.c index db680c7f73bd..1e07ca1d09c0 100644 --- a/sbin/init/init.c +++ b/sbin/init/init.c @@ -116,7 +116,9 @@ static state_func_t catatonia(void); static state_func_t death(void); static state_func_t death_single(void); static state_func_t reroot(void); +#ifdef RESCUE static state_func_t reroot_phase_two(void); +#endif static state_func_t run_script(const char *); @@ -269,7 +271,11 @@ invalid: * 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" +#ifdef RESCUE + "r" +#endif + )) != -1) switch (c) { case 'd': devfs = true; @@ -280,9 +286,11 @@ invalid: case 'f': runcom_mode = FASTBOOT; break; +#ifdef RESCUE case 'r': initial_transition = reroot_phase_two; break; +#endif default: warning("unrecognized flag '-%c'", c); break; @@ -388,7 +396,10 @@ invalid: free(s); } - if (initial_transition != reroot_phase_two) { +#ifdef RESCUE + if (initial_transition != reroot_phase_two) +#endif + { /* * Unmount reroot leftovers. This runs after init(8) * gets reexecuted after reroot_phase_two() is done. @@ -628,6 +639,7 @@ write_stderr(const char *message) write(STDERR_FILENO, message, strlen(message)); } +#ifdef RESCUE static int read_file(const char *path, void **bufp, size_t *bufsizep) { @@ -678,6 +690,7 @@ read_file(const char *path, void **bufp, size_t *bufsizep) return (0); } +#endif /* RESCUE */ static int create_file(const char *path, const void *buf, size_t bufsize) @@ -738,16 +751,14 @@ mount_tmpfs(const char *fspath) return (0); } +#ifndef RESCUE +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(); @@ -762,32 +773,27 @@ reroot(void) goto out; } - /* - * 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; /* * Execute the temporary init. */ - execl(_PATH_REROOT_INIT, _PATH_REROOT_INIT, "-r", NULL); + execl(_PATH_REROOT_INIT, _PATH_REROOT_INIT, 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; } +#else /* !RESCUE */ + static state_func_t reroot_phase_two(void) { @@ -839,6 +845,57 @@ out: return (state_func_t) single_user; } +static state_func_t +reroot(void) +{ + void *buf; + size_t bufsize; + int error; + + buf = NULL; + bufsize = 0; + + revoke_ttys(); + runshutdown(); + + /* + * Make sure nobody can interfere with our scheme. + * Ignore ESRCH, which can apparently happen when + * there are no processes to kill. + */ + error = kill(-1, SIGKILL); + if (error != 0 && errno != ESRCH) { + emergency("kill(2) failed: %m"); + goto out; + } + + /* + * 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); + if (error != 0) + goto out; + + /* + * Execute the temporary init. + */ + 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"); + return (state_func_t) single_user; +} + +#endif /* !RESCUE */ + /* * Bring the system up single user. */ diff --git a/sbin/init/reroot_seed.embed.s b/sbin/init/reroot_seed.embed.s new file mode 100644 index 000000000000..5871c41f06d0 --- /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 index 000000000000..584775aa287f --- /dev/null +++ b/sbin/reroot_seed/Makefile @@ -0,0 +1,6 @@ +PROG= reroot_seed +MAN= +NO_SHARED= YES +INTERNALPROG= YES + +.include diff --git a/sbin/reroot_seed/reroot_seed.c b/sbin/reroot_seed/reroot_seed.c new file mode 100644 index 000000000000..9ba8516ba70f --- /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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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); +}