Skip to content

Commit

Permalink
Replace mmap with xmmap, better handling MAP_FAILED.
Browse files Browse the repository at this point in the history
In some cases we did not even bother to check the return value of
mmap() and just assume it worked.  This is bad, because if we are
out of virtual address space the kernel returned MAP_FAILED and we
would attempt to dereference that address, segfaulting without any
real error output to the user.

We are replacing all calls to mmap() with xmmap() and moving all
MAP_FAILED checking into that single location.  If a mmap call
fails we try to release enough least-recently-used pack windows
to possibly succeed, then retry the mmap() attempt.  If we cannot
mmap even after releasing pack memory then we die() as none of our
callers have any reasonable recovery strategy for a failed mmap.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Junio C Hamano <junkio@cox.net>
  • Loading branch information
spearce authored and Junio C Hamano committed Dec 29, 2006
1 parent 97bfeb3 commit c4712e4
Show file tree
Hide file tree
Showing 6 changed files with 22 additions and 19 deletions.
2 changes: 1 addition & 1 deletion config.c
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ int git_config_set_multivar(const char* key, const char* value,
}

fstat(in_fd, &st);
contents = mmap(NULL, st.st_size, PROT_READ,
contents = xmmap(NULL, st.st_size, PROT_READ,
MAP_PRIVATE, in_fd, 0);
close(in_fd);

Expand Down
4 changes: 1 addition & 3 deletions diff.c
Original file line number Diff line number Diff line change
Expand Up @@ -1341,10 +1341,8 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only)
fd = open(s->path, O_RDONLY);
if (fd < 0)
goto err_empty;
s->data = mmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
s->data = xmmap(NULL, s->size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (s->data == MAP_FAILED)
goto err_empty;
s->should_munmap = 1;
}
else {
Expand Down
13 changes: 13 additions & 0 deletions git-compat-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,19 @@ static inline void *xcalloc(size_t nmemb, size_t size)
return ret;
}

static inline void *xmmap(void *start, size_t length,
int prot, int flags, int fd, off_t offset)
{
void *ret = mmap(start, length, prot, flags, fd, offset);
if (ret == MAP_FAILED) {
release_pack_memory(length);
ret = mmap(start, length, prot, flags, fd, offset);
if (ret == MAP_FAILED)
die("Out of memory? mmap failed: %s", strerror(errno));
}
return ret;
}

static inline ssize_t xread(int fd, void *buf, size_t len)
{
ssize_t nr;
Expand Down
2 changes: 1 addition & 1 deletion read-cache.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ int read_cache_from(const char *path)
cache_mmap_size = st.st_size;
errno = EINVAL;
if (cache_mmap_size >= sizeof(struct cache_header) + 20)
cache_mmap = mmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
cache_mmap = xmmap(NULL, cache_mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
}
close(fd);
if (cache_mmap == MAP_FAILED)
Expand Down
2 changes: 1 addition & 1 deletion refs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,7 +1026,7 @@ int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *
fstat(logfd, &st);
if (!st.st_size)
die("Log %s is empty.", logfile);
logdata = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
logdata = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
close(logfd);

lastrec = NULL;
Expand Down
18 changes: 5 additions & 13 deletions sha1_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -355,10 +355,8 @@ static void read_info_alternates(const char * relative_base, int depth)
close(fd);
return;
}
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (map == MAP_FAILED)
return;

link_alt_odb_entries(map, map + st.st_size, '\n', relative_base, depth);

Expand Down Expand Up @@ -442,10 +440,8 @@ static int check_packed_git_idx(const char *path, unsigned long *idx_size_,
return -1;
}
idx_size = st.st_size;
idx_map = mmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
idx_map = xmmap(NULL, idx_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (idx_map == MAP_FAILED)
return -1;

index = idx_map;
*idx_map_ = idx_map;
Expand Down Expand Up @@ -630,7 +626,7 @@ unsigned char* use_pack(struct packed_git *p,
while (packed_git_limit < pack_mapped
&& unuse_one_window(p))
; /* nothing */
win->base = mmap(NULL, win->len,
win->base = xmmap(NULL, win->len,
PROT_READ, MAP_PRIVATE,
p->pack_fd, win->offset);
if (win->base == MAP_FAILED)
Expand Down Expand Up @@ -828,10 +824,8 @@ void *map_sha1_file(const unsigned char *sha1, unsigned long *size)
*/
sha1_file_open_flag = 0;
}
map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
map = xmmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (map == MAP_FAILED)
return NULL;
*size = st.st_size;
return map;
}
Expand Down Expand Up @@ -1987,10 +1981,8 @@ int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, con

buf = "";
if (size)
buf = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
buf = xmmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
close(fd);
if (buf == MAP_FAILED)
return -1;

if (!type)
type = blob_type;
Expand Down

0 comments on commit c4712e4

Please sign in to comment.