1/* $OpenBSD: ukc.c,v 1.25 2019/08/13 21:36:18 deraadt Exp $ */ 2 3/* 4 * Copyright (c) 1999-2001 Mats O Jansson. All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/types.h> 28#include <sys/device.h> 29 30#include <err.h> 31#include <fcntl.h> 32#include <kvm.h> 33#include <limits.h> 34#include <nlist.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <unistd.h> 39 40#define UKC_MAIN 41#include "ukc.h" 42#include "exec.h" 43#include "config.h" 44 45void init(void); 46__dead void usage(void); 47 48int ukc_mod_kernel = 0; 49 50static void 51check_int(int idx, const char *name) 52{ 53 if (nl[idx].n_type == 0) 54 printf("WARNING this kernel doesn't support modification " 55 "of %s.\n", name); 56} 57 58int 59ukc(char *file, char *outfile, int uflag, int force) 60{ 61 int i; 62 kvm_t *kd; 63 char errbuf[_POSIX2_LINE_MAX]; 64 int histlen = 0, ok = 1; 65 char history[1024], kversion[1024]; 66 67 if (file == NULL) { 68 warnx("no file specified"); 69 usage(); 70 } 71 72 loadkernel(file); 73 74 if (nlist(file, nl) == -1) 75 errx(1, "nlist: %s", file); 76 77 if (uflag) { 78 struct nlist *knl; 79 80 knl = emalloc(sizeof(nl)); 81 memcpy(knl, &nl, sizeof nl); 82 83 if ((kd = kvm_openfiles(NULL,NULL,NULL,O_RDONLY, errbuf)) == 0) 84 errx(1, "kvm_openfiles: %s", errbuf); 85 86 if (kvm_nlist(kd, knl) == -1) 87 errx(1, "kvm_nlist: %s", kvm_geterr(kd)); 88 89 i = 0; 90 while (i < NLENTRIES) { 91 if (nl[i].n_type != knl[i].n_type || 92 nl[i].n_desc != knl[i].n_desc || 93 nl[i].n_value != knl[i].n_value) 94 ok = 0; 95 i++; 96 } 97 98 if (knl[I_HISTLEN].n_type != 0 && ok) { 99 if (kvm_read(kd, knl[I_HISTLEN].n_value, &histlen, 100 sizeof(histlen)) != sizeof(histlen)) 101 warnx("cannot read %s: %s", 102 knl[I_HISTLEN].n_name, 103 kvm_geterr(kd)); 104 } 105 if (knl[CA_HISTORY].n_type != 0 && ok) { 106 if (kvm_read(kd, knl[CA_HISTORY].n_value, history, 107 sizeof(history)) != sizeof(history)) 108 warnx("cannot read %s: %s", 109 knl[CA_HISTORY].n_name, 110 kvm_geterr(kd)); 111 } 112 if (knl[P_VERSION].n_type != 0 && ok) { 113 if (kvm_read(kd, knl[P_VERSION].n_value, kversion, 114 sizeof(kversion)) != sizeof(kversion)) 115 warnx("cannot read %s: %s", 116 knl[P_VERSION].n_name, 117 kvm_geterr(kd)); 118 } 119 } 120 121 if (force == 0 && outfile == NULL) 122 printf("WARNING no output file specified\n"); 123 124 if (nl[IA_EXTRALOC].n_type == 0 || nl[I_REXTRALOC].n_type == 0 || 125 nl[I_TEXTRALOC].n_type == 0 || 126 nl[I_HISTLEN].n_type == 0 || nl[CA_HISTORY].n_type == 0) { 127 printf("\ 128WARNING this kernel doesn't contain all information needed!\n\ 129WARNING the commands add and change might not work.\n"); 130 oldkernel = 1; 131 } 132 133 if (nl[P_PDEVNAMES].n_type == 0 || 134 nl[I_PDEVSIZE].n_type == 0 || 135 nl[S_PDEVINIT].n_type == 0) { 136 printf("\ 137WARNING this kernel doesn't support pseudo devices.\n"); 138 nopdev = 1; 139 } 140 141 check_int(I_NKMEMPG, "NKMEMPAGES"); 142 143 init(); 144 145 if (uflag) { 146 if (ok) { 147 if (strcmp(adjust((caddr_t)nl[P_VERSION].n_value), 148 kversion) != 0) 149 ok = 1; 150 } 151 if (!ok) { 152 printf("WARNING kernel mismatch. -u ignored.\n"); 153 printf("WARNING the running kernel version:\n"); 154 printf("%s", kversion); 155 } else 156 process_history(histlen, history); 157 } 158 159 printf("%s", adjust((caddr_t)nl[P_VERSION].n_value)); 160 161 if (config()) { 162 if (force == 0 && outfile == NULL) { 163 fprintf(stderr, "not forced\n"); 164 return (1); 165 } 166 if (outfile == NULL) 167 outfile = file; 168 if (ukc_mod_kernel == 0) { 169 fprintf(stderr, "Kernel not modified\n"); 170 return (1); 171 } else { 172 printf ("Saving modified kernel.\n"); 173 savekernel(outfile); 174 } 175 } 176 return(0); 177} 178 179void 180init(void) 181{ 182 int i = 0; 183 struct cfdata *cd; 184 short *ln; 185 int *p; 186 187 if ((cd = get_cfdata(0)) == NULL) /* get first item */ 188 errx(1, "failed to get first cfdata"); 189 190 while (cd->cf_attach != 0) { 191 maxdev = i; 192 totdev = i; 193 194 ln = get_locnamp(cd->cf_locnames); 195 while (*ln != -1) { 196 if (*ln > maxlocnames) 197 maxlocnames = *ln; 198 ln++; 199 } 200 i++; 201 cd++; 202 } 203 204 while (cd->cf_attach == 0) { 205 totdev = i; 206 i++; 207 cd++; 208 } 209 210 totdev = totdev - 1; 211 212 if (nopdev == 0) { 213 p = (int *)adjust((caddr_t)nl[I_PDEVSIZE].n_value); 214 maxpseudo = *p; 215 } 216} 217