1
0
mirror of https://github.com/nmap/nmap.git synced 2026-01-18 20:29:02 +00:00

Fixed a TOCTOU race in mmapfile()

Let open() fail in case of a missing file, then use fstat on the
returned file descriptor to get the actual file size.

Reported by Camille Mougey.
This commit is contained in:
henri
2015-02-25 16:36:42 +00:00
parent db717c7543
commit 828db443b2
2 changed files with 25 additions and 6 deletions

View File

@@ -1,5 +1,8 @@
# Nmap Changelog ($Id$); -*-text-*-
o Fixed a benign TOCTOU race between stat() and open() in mmapfile().
Reported by Camille Mougey. [Henri Doreau]
o Reduce CPU consumption when using nsock poll engine with no registered FD,
by actually calling Poll() for the time until timeout, instead of directly
returning zero and entering the loop again. [Henri Doreau]

View File

@@ -584,16 +584,28 @@ int cpe_get_part(const char *cpe) {
}
#ifndef WIN32
static int open2mmap_flags(int open_flags)
{
switch (open_flags) {
case O_RDONLY: return PROT_READ;
case O_RDWR: return PROT_READ | PROT_WRITE;
case O_WRONLY: return PROT_WRITE;
default:
return -1;
}
}
/* mmap() an entire file into the address space. Returns a pointer to the
beginning of the file. The mmap'ed length is returned inside the length
parameter. If there is a problem, NULL is returned, the value of length is
undefined, and errno is set to something appropriate. The user is responsible
for doing an munmap(ptr, length) when finished with it. openflags should be
O_RDONLY or O_RDWR, or O_WRONLY. */
#ifndef WIN32
char *mmapfile(char *fname, int *length, int openflags) {
struct stat st;
int fd;
int mmap_flags;
char *fileptr;
if (!length || !fname) {
@@ -603,8 +615,9 @@ char *mmapfile(char *fname, int *length, int openflags) {
*length = -1;
if (stat(fname, &st) == -1) {
errno = ENOENT;
mmap_flags = open2mmap_flags(openflags);
if (mmap_flags == -1) {
errno = EINVAL;
return NULL;
}
@@ -613,9 +626,12 @@ char *mmapfile(char *fname, int *length, int openflags) {
return NULL;
}
fileptr = (char *)mmap(0, st.st_size, (openflags == O_RDONLY) ? PROT_READ :
(openflags == O_RDWR) ? (PROT_READ | PROT_WRITE)
: PROT_WRITE, MAP_SHARED, fd, 0);
if (fstat(fd, &st) == -1) {
close(fd);
return NULL;
}
fileptr = (char *)mmap(0, st.st_size, mmap_flags, MAP_SHARED, fd, 0);
close(fd);