xref: /freebsd/sbin/reroot_seed/reroot_seed.c (revision 4c9f648852629d757165796bb3cd97bb84a0e483)
1*4c9f6488SKonstantin Belousov /*-
2*4c9f6488SKonstantin Belousov  * SPDX-License-Identifier: BSD-3-Clause
3*4c9f6488SKonstantin Belousov  *
4*4c9f6488SKonstantin Belousov  * Copyright (c) 1991, 1993
5*4c9f6488SKonstantin Belousov  *	The Regents of the University of California.  All rights reserved.
6*4c9f6488SKonstantin Belousov  *
7*4c9f6488SKonstantin Belousov  * This code is derived from software contributed to Berkeley by
8*4c9f6488SKonstantin Belousov  * Donn Seeley at Berkeley Software Design, Inc.
9*4c9f6488SKonstantin Belousov  *
10*4c9f6488SKonstantin Belousov  * Redistribution and use in source and binary forms, with or without
11*4c9f6488SKonstantin Belousov  * modification, are permitted provided that the following conditions
12*4c9f6488SKonstantin Belousov  * are met:
13*4c9f6488SKonstantin Belousov  * 1. Redistributions of source code must retain the above copyright
14*4c9f6488SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer.
15*4c9f6488SKonstantin Belousov  * 2. Redistributions in binary form must reproduce the above copyright
16*4c9f6488SKonstantin Belousov  *    notice, this list of conditions and the following disclaimer in the
17*4c9f6488SKonstantin Belousov  *    documentation and/or other materials provided with the distribution.
18*4c9f6488SKonstantin Belousov  * 3. Neither the name of the University nor the names of its contributors
19*4c9f6488SKonstantin Belousov  *    may be used to endorse or promote products derived from this software
20*4c9f6488SKonstantin Belousov  *    without specific prior written permission.
21*4c9f6488SKonstantin Belousov  *
22*4c9f6488SKonstantin Belousov  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*4c9f6488SKonstantin Belousov  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*4c9f6488SKonstantin Belousov  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*4c9f6488SKonstantin Belousov  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*4c9f6488SKonstantin Belousov  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*4c9f6488SKonstantin Belousov  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*4c9f6488SKonstantin Belousov  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*4c9f6488SKonstantin Belousov  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*4c9f6488SKonstantin Belousov  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*4c9f6488SKonstantin Belousov  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*4c9f6488SKonstantin Belousov  * SUCH DAMAGE.
33*4c9f6488SKonstantin Belousov  */
34*4c9f6488SKonstantin Belousov 
35*4c9f6488SKonstantin Belousov #include <sys/param.h>
36*4c9f6488SKonstantin Belousov #include <sys/mount.h>
37*4c9f6488SKonstantin Belousov #include <sys/reboot.h>
38*4c9f6488SKonstantin Belousov #include <sys/sysctl.h>
39*4c9f6488SKonstantin Belousov 
40*4c9f6488SKonstantin Belousov #include <err.h>
41*4c9f6488SKonstantin Belousov #include <kenv.h>
42*4c9f6488SKonstantin Belousov #include <paths.h>
43*4c9f6488SKonstantin Belousov #include <stdarg.h>
44*4c9f6488SKonstantin Belousov #include <stdlib.h>
45*4c9f6488SKonstantin Belousov #include <string.h>
46*4c9f6488SKonstantin Belousov #include <syslog.h>
47*4c9f6488SKonstantin Belousov #include <unistd.h>
48*4c9f6488SKonstantin Belousov 
49*4c9f6488SKonstantin Belousov static void emergency(const char *, ...) __printflike(1, 2);
50*4c9f6488SKonstantin Belousov 
51*4c9f6488SKonstantin Belousov static void
emergency(const char * message,...)52*4c9f6488SKonstantin Belousov emergency(const char *message, ...)
53*4c9f6488SKonstantin Belousov {
54*4c9f6488SKonstantin Belousov 	va_list ap;
55*4c9f6488SKonstantin Belousov 	va_start(ap, message);
56*4c9f6488SKonstantin Belousov 
57*4c9f6488SKonstantin Belousov 	vsyslog(LOG_EMERG, message, ap);
58*4c9f6488SKonstantin Belousov 	va_end(ap);
59*4c9f6488SKonstantin Belousov }
60*4c9f6488SKonstantin Belousov 
61*4c9f6488SKonstantin Belousov int
main(void)62*4c9f6488SKonstantin Belousov main(void)
63*4c9f6488SKonstantin Belousov {
64*4c9f6488SKonstantin Belousov 	char init_path[PATH_MAX], *path, *path_component;
65*4c9f6488SKonstantin Belousov 	size_t init_path_len;
66*4c9f6488SKonstantin Belousov 	int nbytes, error;
67*4c9f6488SKonstantin Belousov 
68*4c9f6488SKonstantin Belousov 	openlog("init", LOG_CONS, LOG_AUTH);
69*4c9f6488SKonstantin Belousov 
70*4c9f6488SKonstantin Belousov 	/*
71*4c9f6488SKonstantin Belousov 	 * Ask the kernel to mount the new rootfs.
72*4c9f6488SKonstantin Belousov 	 */
73*4c9f6488SKonstantin Belousov 	error = reboot(RB_REROOT);
74*4c9f6488SKonstantin Belousov 	if (error != 0) {
75*4c9f6488SKonstantin Belousov 		emergency("RB_REBOOT failed: %m");
76*4c9f6488SKonstantin Belousov 		_exit(1);
77*4c9f6488SKonstantin Belousov 	}
78*4c9f6488SKonstantin Belousov 
79*4c9f6488SKonstantin Belousov 	/*
80*4c9f6488SKonstantin Belousov 	 * Figure out where the destination init(8) binary is.  Note that
81*4c9f6488SKonstantin Belousov 	 * the path could be different than what we've started with.  Use
82*4c9f6488SKonstantin Belousov 	 * the value from kenv, if set, or the one from sysctl otherwise.
83*4c9f6488SKonstantin Belousov 	 * The latter defaults to a hardcoded value, but can be overridden
84*4c9f6488SKonstantin Belousov 	 * by a build time option.
85*4c9f6488SKonstantin Belousov 	 */
86*4c9f6488SKonstantin Belousov 	nbytes = kenv(KENV_GET, "init_path", init_path, sizeof(init_path));
87*4c9f6488SKonstantin Belousov 	if (nbytes <= 0) {
88*4c9f6488SKonstantin Belousov 		init_path_len = sizeof(init_path);
89*4c9f6488SKonstantin Belousov 		error = sysctlbyname("kern.init_path",
90*4c9f6488SKonstantin Belousov 		    init_path, &init_path_len, NULL, 0);
91*4c9f6488SKonstantin Belousov 		if (error != 0) {
92*4c9f6488SKonstantin Belousov 			emergency("failed to retrieve kern.init_path: %m");
93*4c9f6488SKonstantin Belousov 			_exit(1);
94*4c9f6488SKonstantin Belousov 		}
95*4c9f6488SKonstantin Belousov 	}
96*4c9f6488SKonstantin Belousov 
97*4c9f6488SKonstantin Belousov 	/*
98*4c9f6488SKonstantin Belousov 	 * Repeat the init search logic from sys/kern/init_path.c
99*4c9f6488SKonstantin Belousov 	 */
100*4c9f6488SKonstantin Belousov 	path_component = init_path;
101*4c9f6488SKonstantin Belousov 	while ((path = strsep(&path_component, ":")) != NULL) {
102*4c9f6488SKonstantin Belousov 		/*
103*4c9f6488SKonstantin Belousov 		 * Execute init(8) from the new rootfs.
104*4c9f6488SKonstantin Belousov 		 */
105*4c9f6488SKonstantin Belousov 		execl(path, path, NULL);
106*4c9f6488SKonstantin Belousov 	}
107*4c9f6488SKonstantin Belousov 	emergency("cannot exec init from %s: %m", init_path);
108*4c9f6488SKonstantin Belousov 	_exit(1);
109*4c9f6488SKonstantin Belousov }
110