summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormillert <millert@openbsd.org>2003-05-08 16:30:52 +0000
committermillert <millert@openbsd.org>2003-05-08 16:30:52 +0000
commitabf784ab70b12f8d5b1c409de8c27b8cb7494d05 (patch)
treebdaa1a32ef04d69f207c14d09b8ed53f47f3d0fb
parentKNF (diff)
downloadwireguard-openbsd-abf784ab70b12f8d5b1c409de8c27b8cb7494d05.tar.xz
wireguard-openbsd-abf784ab70b12f8d5b1c409de8c27b8cb7494d05.zip
Previously, ld.so would use a single page for mapping the hints file
and then, if that was not big enough, map the rest of it contiguously. However, there is no guarantee that the address space after the first mmap has not already been used by something else. Instead, just fstat the file and map up to st_size. Also reorganized the code a tad and added some sanity checks for st_size. Problem tracked down by dhartmei@ and mickey@; drahn@ OK.
-rw-r--r--gnu/usr.bin/ld/rtld/rtld.c63
-rw-r--r--libexec/ld.so/sod.c67
2 files changed, 54 insertions, 76 deletions
diff --git a/gnu/usr.bin/ld/rtld/rtld.c b/gnu/usr.bin/ld/rtld/rtld.c
index bc7a9f64630..22dd67b1013 100644
--- a/gnu/usr.bin/ld/rtld/rtld.c
+++ b/gnu/usr.bin/ld/rtld/rtld.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtld.c,v 1.36 2003/01/19 23:35:02 espie Exp $ */
+/* $OpenBSD: rtld.c,v 1.37 2003/05/08 16:30:52 millert Exp $ */
/* $NetBSD: rtld.c,v 1.43 1996/01/14 00:35:17 pk Exp $ */
/*
* Copyright (c) 1993 Paul Kranenburg
@@ -46,6 +46,7 @@
#include <dlfcn.h>
#include <fcntl.h>
#include <a.out.h>
+#include <limits.h>
#include <stab.h>
#include <stdio.h>
#include <stdlib.h>
@@ -1227,54 +1228,42 @@ static char *hint_search_path = "";
static void
maphints(void)
{
- caddr_t addr;
+ struct stat sb;
+ caddr_t addr = MAP_FAILED;
- if ((hfd = open(_PATH_LD_HINTS, O_RDONLY, 0)) == -1) {
- hheader = (struct hints_header *)-1;
- return;
- }
+ if ((hfd = open(_PATH_LD_HINTS, O_RDONLY, 0)) < 0)
+ goto bad_hints;
- hsize = PAGSIZ;
- addr = mmap(0, hsize, PROT_READ, MAP_COPY, hfd, 0);
+ if (fstat(hfd, &sb) != 0 || !S_ISREG(sb.st_mode) ||
+ sb.st_size < sizeof(struct hints_header) || sb.st_size > LONG_MAX)
+ goto bad_hints;
- if (addr == (caddr_t)MAP_FAILED) {
- close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
+ hsize = (long)sb.st_size;
+ addr = mmap(0, hsize, PROT_READ, MAP_COPY, hfd, 0);
+ if (addr == MAP_FAILED)
+ goto bad_hints;
hheader = (struct hints_header *)addr;
- if (HH_BADMAG(*hheader)) {
- munmap(addr, hsize);
- close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
+ if (HH_BADMAG(*hheader) || hheader->hh_ehints > hsize)
+ goto bad_hints;
if (hheader->hh_version != LD_HINTS_VERSION_1 &&
- hheader->hh_version != LD_HINTS_VERSION_2) {
- munmap(addr, hsize);
- close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
-
- if (hheader->hh_ehints > hsize) {
- if (mmap(addr+hsize, hheader->hh_ehints - hsize,
- PROT_READ, MAP_COPY|MAP_FIXED,
- hfd, hsize) != (caddr_t)(addr+hsize)) {
-
- munmap((caddr_t)hheader, hsize);
- close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
- }
+ hheader->hh_version != LD_HINTS_VERSION_2)
+ goto bad_hints;
hbuckets = (struct hints_bucket *)(addr + hheader->hh_hashtab);
hstrtab = (char *)(addr + hheader->hh_strtab);
if (hheader->hh_version >= LD_HINTS_VERSION_2)
hint_search_path = hstrtab + hheader->hh_dirlist;
+
+ return;
+
+bad_hints:
+ if (addr != MAP_FAILED)
+ munmap(addr, hsize);
+ if (hfd != -1)
+ close(hfd);
+ hheader = (struct hints_header *)-1;
}
static void
diff --git a/libexec/ld.so/sod.c b/libexec/ld.so/sod.c
index f8589611ddf..eb42997162b 100644
--- a/libexec/ld.so/sod.c
+++ b/libexec/ld.so/sod.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: sod.c,v 1.16 2003/02/02 16:57:58 deraadt Exp $ */
+/* $OpenBSD: sod.c,v 1.17 2003/05/08 16:30:52 millert Exp $ */
/*
* Copyright (c) 1993 Paul Kranenburg
@@ -37,6 +37,7 @@
#include <fcntl.h>
#include <nlist.h>
#include <link.h>
+#include <limits.h>
#include <machine/exec.h>
#include <sys/mman.h>
#include <string.h>
@@ -48,7 +49,6 @@
#include "util.h"
#include "sod.h"
-#define PAGSIZ __LDPGSZ
int _dl_hinthash(char *cp, int vmajor, int vminor);
/*
@@ -129,8 +129,6 @@ backout:
sodp->sod_name = (long)_dl_strdup(name);
}
-static int hfd;
-static long hsize;
static struct hints_header *hheader = NULL;
static struct hints_bucket *hbuckets;
static char *hstrtab;
@@ -141,48 +139,30 @@ char *_dl_hint_search_path = NULL;
void
_dl_maphints(void)
{
- caddr_t addr;
+ struct stat sb;
+ caddr_t addr = MAP_FAILED;
+ long hsize = 0;
+ int hfd;
- if ((hfd = _dl_open(_PATH_LD_HINTS, O_RDONLY)) < 0) {
- hheader = (struct hints_header *)-1;
- return;
- }
+ if ((hfd = _dl_open(_PATH_LD_HINTS, O_RDONLY)) < 0)
+ goto bad_hints;
- hsize = PAGSIZ;
- addr = (void *) _dl_mmap(0, hsize, PROT_READ, MAP_PRIVATE, hfd, 0);
+ if (_dl_fstat(hfd, &sb) != 0 || !S_ISREG(sb.st_mode) ||
+ sb.st_size < sizeof(struct hints_header) || sb.st_size > LONG_MAX)
+ goto bad_hints;
- if (addr == MAP_FAILED) {
- _dl_close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
+ hsize = (long)sb.st_size;
+ addr = (void *)_dl_mmap(0, hsize, PROT_READ, MAP_PRIVATE, hfd, 0);
+ if (addr == MAP_FAILED)
+ goto bad_hints;
hheader = (struct hints_header *)addr;
- if (HH_BADMAG(*hheader)) {
- _dl_munmap(addr, hsize);
- _dl_close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
+ if (HH_BADMAG(*hheader) || hheader->hh_ehints > hsize)
+ goto bad_hints;
if (hheader->hh_version != LD_HINTS_VERSION_1 &&
- hheader->hh_version != LD_HINTS_VERSION_2) {
- _dl_munmap(addr, hsize);
- _dl_close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
-
- if (hheader->hh_ehints > hsize) {
- if ((caddr_t)_dl_mmap(addr+hsize, hheader->hh_ehints - hsize,
- PROT_READ, MAP_PRIVATE|MAP_FIXED,
- hfd, hsize) != (caddr_t)(addr+hsize)) {
- _dl_munmap((caddr_t)hheader, hsize);
- _dl_close(hfd);
- hheader = (struct hints_header *)-1;
- return;
- }
- }
+ hheader->hh_version != LD_HINTS_VERSION_2)
+ goto bad_hints;
hbuckets = (struct hints_bucket *)(addr + hheader->hh_hashtab);
hstrtab = (char *)(addr + hheader->hh_strtab);
@@ -191,6 +171,15 @@ _dl_maphints(void)
/* close the file descriptor, leaving the hints mapped */
_dl_close(hfd);
+
+ return;
+
+bad_hints:
+ if (addr != MAP_FAILED)
+ _dl_munmap(addr, hsize);
+ if (hfd != -1)
+ _dl_close(hfd);
+ hheader = (struct hints_header *)-1;
}
char *