jcs's openbsd hax
openbsd
at jcs 223 lines 5.9 kB view raw
1/* $OpenBSD: boot.c,v 1.57 2023/02/23 19:48:22 miod Exp $ */ 2 3/* 4 * Copyright (c) 2003 Dale Rahn 5 * Copyright (c) 1997,1998 Michael Shalayeff 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 */ 30 31#include <sys/param.h> 32#include <sys/reboot.h> 33#include <sys/stat.h> 34#include <libsa.h> 35#include <lib/libsa/colorchar.h> 36#include <lib/libsa/loadfile.h> 37#include <lib/libkern/funcs.h> 38#include <lib/libsa/arc4.h> 39 40#include <stand/boot/bootarg.h> 41 42#include "cmd.h" 43 44#ifndef KERNEL 45#define KERNEL "/bsd" 46#endif 47 48char prog_ident[40]; 49char *progname = "BOOT"; 50 51extern const char version[]; 52struct cmd_state cmd; 53 54/* bootprompt can be set by MD code to avoid prompt first time round */ 55int bootprompt = 1; 56char *kernelfile = KERNEL; /* can be changed by MD code */ 57int boottimeout = 5; /* can be changed by MD code */ 58 59char rnddata[BOOTRANDOM_MAX] __aligned(sizeof(long)); 60struct rc4_ctx randomctx; 61 62void 63boot(dev_t bootdev) 64{ 65 int fd, isupgrade = 0; 66 int i, try = 0, st; 67 uint64_t marks[MARK_MAX]; 68 69 machdep(); 70 71 snprintf(prog_ident, sizeof(prog_ident), 72 ">> OpenBSD/" MACHINE " %s %s", progname, version); 73 74 printf(">> "); 75 colorchar('O', COLOR_DEFAULT_BG, COLOR_BRIGHT_YELLOW); 76 colorchar('p', COLOR_DEFAULT_BG, COLOR_BRIGHT_YELLOW); 77 colorchar('e', COLOR_DEFAULT_BG, COLOR_BRIGHT_YELLOW); 78 colorchar('n', COLOR_DEFAULT_BG, COLOR_BRIGHT_YELLOW); 79 colorchar('B', COLOR_DEFAULT_BG, COLOR_RED); 80 colorchar('S', COLOR_DEFAULT_BG, COLOR_RED); 81 colorchar('D', COLOR_DEFAULT_BG, COLOR_RED); 82 83 colorchar('/', COLOR_DEFAULT_BG, COLOR_DEFAULT_FG); 84 85 for (i = 0; i < strlen(MACHINE); i++) 86 colorchar(MACHINE[i], COLOR_DEFAULT_BG, COLOR_BRIGHT_WHITE); 87 88 printf(" %s %s\n", progname, version); 89 90 devboot(bootdev, cmd.bootdev); 91 strlcpy(cmd.image, kernelfile, sizeof(cmd.image)); 92 cmd.boothowto = 0; 93 cmd.conf = "/etc/boot.conf"; 94 cmd.timeout = boottimeout; 95 96 if (upgrade()) { 97 strlcpy(cmd.image, "/bsd.upgrade", sizeof(cmd.image)); 98 printf("upgrade detected: switching to %s\n", cmd.image); 99 isupgrade = 1; 100 } 101 102 st = read_conf(); 103 104#ifdef HIBERNATE 105 int bootdev_has_hibernate(void); 106 107 if (bootdev_has_hibernate()) { 108 strlcpy(cmd.image, "/bsd.booted", sizeof(cmd.image)); 109 printf("unhibernate detected: switching to %s\n", cmd.image); 110 cmd.boothowto |= RB_UNHIBERNATE; 111 } 112#endif 113 114 if (!bootprompt) 115 snprintf(cmd.path, sizeof cmd.path, "%s:%s", 116 cmd.bootdev, cmd.image); 117 118 while (1) { 119 /* no boot.conf, or no boot cmd in there */ 120 if (bootprompt && st <= 0) { 121 do { 122 printf("boot> "); 123 } while(!getcmd()); 124 } 125 126 if (loadrandom(BOOTRANDOM, rnddata, sizeof(rnddata)) == 0) 127 cmd.boothowto |= RB_GOODRANDOM; 128#ifdef MDRANDOM 129 if (mdrandom(rnddata, sizeof(rnddata)) == 0) 130 cmd.boothowto |= RB_GOODRANDOM; 131#endif 132#ifdef FWRANDOM 133 if (fwrandom(rnddata, sizeof(rnddata)) == 0) 134 cmd.boothowto |= RB_GOODRANDOM; 135#endif 136 rc4_keysetup(&randomctx, rnddata, sizeof rnddata); 137 rc4_skip(&randomctx, 1536); 138 139 st = 0; 140 bootprompt = 1; /* allow reselect should we fail */ 141 142 printf("booting %s: ", cmd.path); 143 marks[MARK_START] = 0; 144 if ((fd = loadfile(cmd.path, marks, LOAD_ALL)) != -1) { 145 146 /* Prevent re-upgrade: chmod a-x bsd.upgrade */ 147 if (isupgrade) { 148 struct stat st; 149 150 if (fstat(fd, &st) == 0) { 151 st.st_mode &= ~(S_IXUSR|S_IXGRP|S_IXOTH); 152 if (fchmod(fd, st.st_mode) == -1) 153 printf("fchmod a-x %s: failed\n", 154 cmd.path); 155 } 156 } 157 close(fd); 158 break; 159 } 160 161 kernelfile = KERNEL; 162 try++; 163 strlcpy(cmd.image, kernelfile, sizeof(cmd.image)); 164 printf(" failed(%d). will try %s\n", errno, kernelfile); 165 166 if (try < 2) { 167 if (cmd.timeout > 0) 168 cmd.timeout++; 169 } else { 170 if (cmd.timeout) 171 printf("Turning timeout off.\n"); 172 cmd.timeout = 0; 173 } 174 } 175 176 /* exec */ 177 run_loadfile(marks, cmd.boothowto); 178} 179 180int 181loadrandom(char *name, char *buf, size_t buflen) 182{ 183 char path[MAXPATHLEN]; 184 struct stat sb; 185 int fd, i, error = 0; 186 187 /* Extract the device name from the kernel we are loading. */ 188 for (i = 0; i < sizeof(cmd.path); i++) { 189 if (cmd.path[i] == ':') { 190 strlcpy(path, cmd.path, i + 1); 191 snprintf(path + i, sizeof(path) - i, ":%s", name); 192 break; 193 } else if (cmd.path[i] == '\0') { 194 snprintf(path, sizeof path, "%s:%s", 195 cmd.bootdev, name); 196 break; 197 } 198 } 199 200 fd = open(path, O_RDONLY); 201 if (fd == -1) { 202 if (errno != EPERM) 203 printf("cannot open %s: %s\n", path, strerror(errno)); 204 return -1; 205 } 206 if (fstat(fd, &sb) == -1) { 207 error = -1; 208 goto done; 209 } 210 if (read(fd, buf, buflen) != buflen) { 211 error = -1; 212 goto done; 213 } 214 if (sb.st_mode & S_ISTXT) { 215 printf("NOTE: random seed is being reused.\n"); 216 error = -1; 217 goto done; 218 } 219 fchmod(fd, sb.st_mode | S_ISTXT); 220done: 221 close(fd); 222 return (error); 223}