mem: fix a buffer overflow bug in the mmap() replacement.
This commit is contained in:
parent
21cb084712
commit
8aa27ed6c6
@ -737,3 +737,28 @@ static void offset_check(int fd)
|
|||||||
errno = orig_errno;
|
errno = orig_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Utility function to know how many bytes are left until the end of
|
||||||
|
* the file. */
|
||||||
|
size_t _zz_bytes_until_eof(int fd, size_t offset)
|
||||||
|
{
|
||||||
|
int orig_errno = errno;
|
||||||
|
#if defined HAVE_LSEEK64
|
||||||
|
LOADSYM(lseek64);
|
||||||
|
|
||||||
|
off64_t current = ORIG(lseek64)(fd, 0, SEEK_CUR);
|
||||||
|
off64_t begin = ORIG(lseek64)(fd, offset, SEEK_CUR);
|
||||||
|
off64_t end = ORIG(lseek64)(fd, 0, SEEK_END);
|
||||||
|
ORIG(lseek64)(fd, current, SEEK_SET);
|
||||||
|
#else
|
||||||
|
LOADSYM(lseek);
|
||||||
|
|
||||||
|
off_t current = ORIG(lseek)(fd, 0, SEEK_CUR);
|
||||||
|
off_t begin = ORIG(lseek)(fd, offset, SEEK_CUR);
|
||||||
|
off_t end = ORIG(lseek)(fd, 0, SEEK_END);
|
||||||
|
ORIG(lseek)(fd, current, SEEK_SET);
|
||||||
|
#endif
|
||||||
|
errno = orig_errno;
|
||||||
|
|
||||||
|
return (begin >= end) ? 0 : (size_t)(end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@ -302,6 +302,7 @@ int nbmaps = 0;
|
|||||||
return ORIG(mymmap)(start, length, prot, flags, fd, offset); \
|
return ORIG(mymmap)(start, length, prot, flags, fd, offset); \
|
||||||
\
|
\
|
||||||
char *b = MAP_FAILED; \
|
char *b = MAP_FAILED; \
|
||||||
|
\
|
||||||
ret = ORIG(mymmap)(NULL, length, prot, flags, fd, offset); \
|
ret = ORIG(mymmap)(NULL, length, prot, flags, fd, offset); \
|
||||||
if (ret != MAP_FAILED && length) \
|
if (ret != MAP_FAILED && length) \
|
||||||
{ \
|
{ \
|
||||||
@ -326,13 +327,25 @@ int nbmaps = 0;
|
|||||||
} \
|
} \
|
||||||
maps[i] = b; \
|
maps[i] = b; \
|
||||||
maps[i + 1] = ret; \
|
maps[i + 1] = ret; \
|
||||||
|
\
|
||||||
|
/* If we requested a memory area larger than the end of the
|
||||||
|
* file, it was not actually allocated, so do not try to
|
||||||
|
* copy data beyond that point. */ \
|
||||||
|
size_t data_length = _zz_bytes_until_eof(fd, offset); \
|
||||||
|
if (data_length > length) \
|
||||||
|
data_length = length; \
|
||||||
|
\
|
||||||
oldpos = _zz_getpos(fd); \
|
oldpos = _zz_getpos(fd); \
|
||||||
_zz_setpos(fd, offset); /* mmap() maps the fd at offset 0 */ \
|
_zz_setpos(fd, offset); /* mmap() maps the fd at offset 0 */ \
|
||||||
memcpy(b, ret, length); /* FIXME: get rid of this */ \
|
/* FIXME: we should not blindly memcpy() here because the
|
||||||
|
* memory area might be immense; instead, rely on mprotect()
|
||||||
|
* and sigaction() to detect page faults and only copy memory
|
||||||
|
* areas that get accessed. */ \
|
||||||
|
memcpy(b, ret, data_length); \
|
||||||
_zz_fuzz(fd, (uint8_t *)b, length); \
|
_zz_fuzz(fd, (uint8_t *)b, length); \
|
||||||
_zz_setpos(fd, oldpos); \
|
_zz_setpos(fd, oldpos); \
|
||||||
ret = b; \
|
ret = b; \
|
||||||
if (length >= 4) \
|
if (data_length >= 4) \
|
||||||
debug("%s(%p, %li, %i, %i, %i, %lli) = %p \"%c%c%c%c...", \
|
debug("%s(%p, %li, %i, %i, %i, %lli) = %p \"%c%c%c%c...", \
|
||||||
__func__, start, (long int)length, prot, flags, fd, \
|
__func__, start, (long int)length, prot, flags, fd, \
|
||||||
(long long int)offset, ret, b[0], b[1], b[2], b[3]); \
|
(long long int)offset, ret, b[0], b[1], b[2], b[3]); \
|
||||||
|
|||||||
@ -40,6 +40,9 @@ extern void _zz_fini(void) __attribute__((destructor));
|
|||||||
/* This function is needed to initialise memory functions */
|
/* This function is needed to initialise memory functions */
|
||||||
extern void _zz_mem_init(void);
|
extern void _zz_mem_init(void);
|
||||||
|
|
||||||
|
/* This function lets us know where the end of a file is. */
|
||||||
|
extern size_t _zz_bytes_until_eof(int fd, size_t offset);
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <windows.h>
|
# include <windows.h>
|
||||||
extern CRITICAL_SECTION _zz_pipe_cs;
|
extern CRITICAL_SECTION _zz_pipe_cs;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user