xref: /openbsd-src/usr.sbin/config/exec_elf.c (revision b7041c0781c8668129da8084451ded41b0c43954)
1*b7041c07Sderaadt /*	$OpenBSD: exec_elf.c,v 1.18 2021/10/24 21:24:18 deraadt Exp $ */
235319decSderaadt 
335319decSderaadt /*
435319decSderaadt  * Copyright (c) 1999 Mats O Jansson.  All rights reserved.
535319decSderaadt  *
635319decSderaadt  * Redistribution and use in source and binary forms, with or without
735319decSderaadt  * modification, are permitted provided that the following conditions
835319decSderaadt  * are met:
935319decSderaadt  * 1. Redistributions of source code must retain the above copyright
1035319decSderaadt  *    notice, this list of conditions and the following disclaimer.
1135319decSderaadt  * 2. Redistributions in binary form must reproduce the above copyright
1235319decSderaadt  *    notice, this list of conditions and the following disclaimer in the
1335319decSderaadt  *    documentation and/or other materials provided with the distribution.
1435319decSderaadt  *
1535319decSderaadt  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1635319decSderaadt  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1735319decSderaadt  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1835319decSderaadt  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1935319decSderaadt  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2035319decSderaadt  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2135319decSderaadt  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2235319decSderaadt  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2335319decSderaadt  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2435319decSderaadt  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2535319decSderaadt  */
2635319decSderaadt 
27c6b62359Sedd #include <sys/types.h>
28c6b62359Sedd #include <sys/exec.h>
29c6b62359Sedd 
309f79a698Smpi #include <elf.h>
3135319decSderaadt #include <err.h>
3235319decSderaadt #include <errno.h>
3335319decSderaadt #include <fcntl.h>
3435319decSderaadt #include <nlist.h>
3535319decSderaadt #include <stdio.h>
36c6b62359Sedd #include <stdlib.h>
3735319decSderaadt #include <unistd.h>
3835319decSderaadt 
3935319decSderaadt #include "ukc.h"
401c946cd5Sderaadt #include "config.h"
414d92a8bcSguenther #include "exec.h"
4235319decSderaadt 
4335319decSderaadt caddr_t		ptr, rest, pre;
446377a087Sart Elf_Ehdr	elf_ex;
456377a087Sart Elf_Phdr	*elf_phdr;
466377a087Sart Elf_Shdr	*elf_shdr;
4735319decSderaadt char		*elf_total;
4835319decSderaadt char		*elf_shstrtab;
4935319decSderaadt off_t		elf_size;
5035319decSderaadt 
5135319decSderaadt caddr_t
adjust(caddr_t x)524d92a8bcSguenther adjust(caddr_t x)
5335319decSderaadt {
5435319decSderaadt 	int i;
556377a087Sart 	Elf_Shdr *s;
5635319decSderaadt 	unsigned long y = 0;
5735319decSderaadt 
5835319decSderaadt 	s = elf_shdr;
5935319decSderaadt 
6035319decSderaadt 	for (i = 0; i < elf_ex.e_shnum; i++) {
6135319decSderaadt 		if (s[i].sh_addr == 0)
6235319decSderaadt 			continue;
6335319decSderaadt 		if (((unsigned long)x >= s[i].sh_addr) &&
6435319decSderaadt 		    ((unsigned long)x < (s[i].sh_addr+s[i].sh_size))) {
6535319decSderaadt 			y = (unsigned long)&elf_total[(unsigned long)x -
66a8d5091fSderaadt 			    s[i].sh_addr + s[i].sh_offset];
6735319decSderaadt 			break;
6835319decSderaadt 		}
6935319decSderaadt 	}
7035319decSderaadt 
7135319decSderaadt 	return((caddr_t)y);
7235319decSderaadt }
7335319decSderaadt 
7435319decSderaadt caddr_t
readjust(caddr_t x)754d92a8bcSguenther readjust(caddr_t x)
7635319decSderaadt {
7735319decSderaadt 	int i;
786377a087Sart 	Elf_Shdr *s;
7935319decSderaadt 	unsigned long y = 0;
8035319decSderaadt 
8135319decSderaadt 	s = elf_shdr;
8235319decSderaadt 
8335319decSderaadt 	for (i = 0; i < elf_ex.e_shnum; i++) {
8435319decSderaadt 		if (s[i].sh_addr == 0)
8535319decSderaadt 			continue;
8635319decSderaadt 		if (((x - elf_total) >= s[i].sh_offset) &&
8735319decSderaadt 		    ((x - elf_total) <= (s[i].sh_offset + s[i].sh_size)))
88b90f1bdfSart 			y = (unsigned long)x - (unsigned long)elf_total +
89b90f1bdfSart 			    (unsigned long)s[i].sh_addr - s[i].sh_offset;
9035319decSderaadt 	}
9135319decSderaadt 
9235319decSderaadt 	return((caddr_t)y);
9335319decSderaadt }
9435319decSderaadt 
9535319decSderaadt void
loadkernel(char * file)964d92a8bcSguenther loadkernel(char *file)
9735319decSderaadt {
9835319decSderaadt 	int fd;
9935319decSderaadt 
100*b7041c07Sderaadt 	if ((fd = open(file, O_RDONLY | O_EXLOCK)) == -1)
1012cc28a79Saaron 		err(1, "%s", file);
10235319decSderaadt 
10335319decSderaadt 	if (read(fd, (char *)&elf_ex, sizeof(elf_ex)) != sizeof(elf_ex))
10435319decSderaadt 		errx(1, "can't read elf header");
10535319decSderaadt 
10635319decSderaadt 	if (!IS_ELF(elf_ex))
10746347781Smpech 		errx(1, "bad elf magic");
10835319decSderaadt 
1097411eadaSderaadt 	elf_size = lseek(fd, (off_t)0, SEEK_END);
1107411eadaSderaadt 	(void)lseek(fd, (off_t)0, SEEK_SET);
1117411eadaSderaadt 	elf_total = emalloc((size_t)elf_size);
11235319decSderaadt 
1137411eadaSderaadt 	if (read(fd, elf_total, (size_t)elf_size) != elf_size)
11435319decSderaadt 		errx(1, "can't read elf kernel");
11535319decSderaadt 
1163fd68e11Sotto 	if (elf_ex.e_phoff > (size_t)elf_size)
1173fd68e11Sotto 		errx(1, "incorrect ELF header or truncated file");
1183fd68e11Sotto 	if (elf_ex.e_shoff > (size_t)elf_size)
1193fd68e11Sotto 		errx(1, "incorrect ELF header or truncated file");
1203fd68e11Sotto 
1216377a087Sart 	elf_phdr = (Elf_Phdr *)&elf_total[elf_ex.e_phoff];
1226377a087Sart 	elf_shdr = (Elf_Shdr *)&elf_total[elf_ex.e_shoff];
12335319decSderaadt 
1243fd68e11Sotto 	if ((char *)&elf_shdr[elf_ex.e_shstrndx] +
1253fd68e11Sotto 	    sizeof(elf_shdr[elf_ex.e_shstrndx]) >= elf_total + (size_t)elf_size)
1263fd68e11Sotto 		errx(1, "incorrect ELF header or truncated file");
1273fd68e11Sotto 
1283fd68e11Sotto 	if ((char *)&elf_shdr[elf_ex.e_shstrndx].sh_offset +
1293fd68e11Sotto 	    sizeof(elf_shdr[elf_ex.e_shstrndx].sh_offset) >=
1303fd68e11Sotto 	    elf_total + (size_t)elf_size)
1313fd68e11Sotto 		errx(1, "incorrect ELF header or truncated file");
1323fd68e11Sotto 
13335319decSderaadt 	elf_shstrtab = &elf_total[elf_shdr[elf_ex.e_shstrndx].sh_offset];
13435319decSderaadt 
13535319decSderaadt 	close(fd);
13635319decSderaadt }
13735319decSderaadt 
13835319decSderaadt void
savekernel(char * outfile)1394d92a8bcSguenther savekernel(char *outfile)
14035319decSderaadt {
14135319decSderaadt 	int fd;
14235319decSderaadt 
143df69c215Sderaadt 	if ((fd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC, 0700)) == -1)
1442cc28a79Saaron 		err(1, "%s", outfile);
14535319decSderaadt 
1467411eadaSderaadt 	if (write(fd, elf_total, (size_t)elf_size) != elf_size)
14735319decSderaadt 		errx(1, "can't write file %s", outfile);
14835319decSderaadt 
14935319decSderaadt 	close(fd);
15035319decSderaadt }
151