Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/elf2aout/elf2aout.c
Show All 22 Lines | |||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/capsicum.h> | |||||
#include <sys/elf64.h> | #include <sys/elf64.h> | ||||
#include <sys/endian.h> | #include <sys/endian.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <sys/stat.h> | #include <sys/stat.h> | ||||
#include <err.h> | #include <err.h> | ||||
#include <errno.h> | |||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) | #define xe16toh(x) ((data == ELFDATA2MSB) ? be16toh(x) : le16toh(x)) | ||||
#define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) | #define xe32toh(x) ((data == ELFDATA2MSB) ? be32toh(x) : le32toh(x)) | ||||
Show All 15 Lines | |||||
static void usage(void); | static void usage(void); | ||||
/* | /* | ||||
* elf to a.out converter for freebsd/sparc64 bootblocks. | * elf to a.out converter for freebsd/sparc64 bootblocks. | ||||
*/ | */ | ||||
int | int | ||||
main(int ac, char **av) | main(int ac, char **av) | ||||
{ | { | ||||
cap_rights_t rights; | |||||
Elf64_Half phentsize; | Elf64_Half phentsize; | ||||
Elf64_Half machine; | Elf64_Half machine; | ||||
Elf64_Half phnum; | Elf64_Half phnum; | ||||
Elf64_Xword filesz; | Elf64_Xword filesz; | ||||
Elf64_Xword memsz; | Elf64_Xword memsz; | ||||
Elf64_Addr entry; | Elf64_Addr entry; | ||||
Elf64_Off offset; | Elf64_Off offset; | ||||
Elf64_Off phoff; | Elf64_Off phoff; | ||||
Elf64_Word type; | Elf64_Word type; | ||||
unsigned char data; | unsigned char data; | ||||
struct stat sb; | struct stat sb; | ||||
struct exec a; | struct exec a; | ||||
Elf64_Phdr *p; | Elf64_Phdr *p; | ||||
Elf64_Ehdr *e; | Elf64_Ehdr *e; | ||||
void *v; | void *v; | ||||
int efd; | int efd; | ||||
int fd; | int fd; | ||||
int c; | int c; | ||||
int i; | int i; | ||||
fd = STDIN_FILENO; | fd = STDOUT_FILENO; | ||||
cem: This is the output fd. Did this program even work without `-o`? | |||||
while ((c = getopt(ac, av, "o:")) != -1) | while ((c = getopt(ac, av, "o:")) != -1) | ||||
switch (c) { | switch (c) { | ||||
case 'o': | case 'o': | ||||
if ((fd = open(optarg, O_CREAT|O_RDWR, 0644)) < 0) | if ((fd = open(optarg, O_CREAT|O_RDWR, 0644)) < 0) | ||||
err(1, "%s", optarg); | err(1, "%s", optarg); | ||||
cap_rights_init(&rights, CAP_WRITE); | |||||
Not Done Inline ActionsBelow, for the output descriptor, only CAP_WRITE is required. I'm not sure the CAP_FSTAT here is needed here? Or might CAP_FSTAT be needed below? rwatson: Below, for the output descriptor, only CAP_WRITE is required. I'm not sure the CAP_FSTAT here… | |||||
if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS) | |||||
err(1, "unable to limit rights for %s", optarg); | |||||
break; | break; | ||||
case '?': | case '?': | ||||
default: | default: | ||||
usage(); | usage(); | ||||
} | } | ||||
ac -= optind; | ac -= optind; | ||||
av += optind; | av += optind; | ||||
if (ac == 0) | if (ac == 0) | ||||
usage(); | usage(); | ||||
if ((efd = open(*av, O_RDONLY)) < 0 || fstat(efd, &sb) < 0) | if ((efd = open(*av, O_RDONLY)) < 0 || fstat(efd, &sb) < 0) | ||||
err(1, NULL); | err(1, NULL); | ||||
cap_rights_init(&rights, CAP_MMAP_R); | |||||
if (cap_rights_limit(efd, &rights) < 0 && errno != ENOSYS) | |||||
err(1, "unable to limit rights for %s", *av); | |||||
Done Inline ActionsLeaving {stdin, stdout, stderr} in a closed state always makes me nervous, as a later operation in libc might perform I/O. I wonder if it would be better to simply set capability rights on it to 0 and leave fd 0 open? rwatson: Leaving {stdin, stdout, stderr} in a closed state always makes me nervous, as a later operation… | |||||
/* Restrict stdio streams. */ | |||||
Done Inline ActionsI'm actually slightly surprised that err() and friends don't require CAP_FSTAT here, in fact .. but haven't checked. The stdio stack does like to fstat() its descriptors, I thought? rwatson: I'm actually slightly surprised that err() and friends don't require CAP_FSTAT here, in fact .. | |||||
Not Done Inline ActionsI expect stdout and stderr need CAP_FSTAT. Maybe even CAP_IOCTL + the isatty(3) ioctl, if you care about output line buffering. cem: I expect stdout and stderr need CAP_FSTAT. Maybe even CAP_IOCTL + the `isatty(3)` ioctl, if… | |||||
CAP_NONE(&rights); | |||||
if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) | |||||
err(1, "unable to limit rights for stdin"); | |||||
cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE); | |||||
if ((cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) || | |||||
(cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)) | |||||
err(1, "unable to limit rights for stdout/stderr"); | |||||
if (cap_enter() < 0 && errno != ENOSYS) | |||||
err(1, "unable to enter capability mode"); | |||||
v = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, efd, 0); | v = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, efd, 0); | ||||
if ((e = v) == MAP_FAILED) | if ((e = v) == MAP_FAILED) | ||||
err(1, NULL); | err(1, NULL); | ||||
if (!IS_ELF(*e)) | if (!IS_ELF(*e)) | ||||
errx(1, "not an elf file"); | errx(1, "not an elf file"); | ||||
if (e->e_ident[EI_CLASS] != ELFCLASS64) | if (e->e_ident[EI_CLASS] != ELFCLASS64) | ||||
errx(1, "wrong class"); | errx(1, "wrong class"); | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |
This is the output fd. Did this program even work without -o?