Skip to content

Commit c5baf18

Browse files
committed
Merge branch 'jk/diagnose-config-mmap-failure' into maint
The configuration reader/writer uses mmap(2) interface to access the files; when we find a directory, it barfed with "Out of memory?". * jk/diagnose-config-mmap-failure: xmmap(): drop "Out of memory?" config.c: rewrite ENODEV into EISDIR when mmap fails config.c: avoid xmmap error messages config.c: fix mmap leak when writing config read-cache.c: drop PROT_WRITE from mmap of index
2 parents c533125 + 9ca0aaf commit c5baf18

File tree

4 files changed

+29
-11
lines changed

4 files changed

+29
-11
lines changed

config.c

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,6 +1937,8 @@ int git_config_set_multivar_in_file(const char *config_filename,
19371937
int ret;
19381938
struct lock_file *lock = NULL;
19391939
char *filename_buf = NULL;
1940+
char *contents = NULL;
1941+
size_t contents_sz;
19401942

19411943
/* parse-key returns negative; flip the sign to feed exit(3) */
19421944
ret = 0 - git_config_parse_key(key, &store.key, &store.baselen);
@@ -1986,8 +1988,7 @@ int git_config_set_multivar_in_file(const char *config_filename,
19861988
goto write_err_out;
19871989
} else {
19881990
struct stat st;
1989-
char *contents;
1990-
size_t contents_sz, copy_begin, copy_end;
1991+
size_t copy_begin, copy_end;
19911992
int i, new_line = 0;
19921993

19931994
if (value_regex == NULL)
@@ -2050,8 +2051,17 @@ int git_config_set_multivar_in_file(const char *config_filename,
20502051

20512052
fstat(in_fd, &st);
20522053
contents_sz = xsize_t(st.st_size);
2053-
contents = xmmap(NULL, contents_sz, PROT_READ,
2054-
MAP_PRIVATE, in_fd, 0);
2054+
contents = xmmap_gently(NULL, contents_sz, PROT_READ,
2055+
MAP_PRIVATE, in_fd, 0);
2056+
if (contents == MAP_FAILED) {
2057+
if (errno == ENODEV && S_ISDIR(st.st_mode))
2058+
errno = EISDIR;
2059+
error("unable to mmap '%s': %s",
2060+
config_filename, strerror(errno));
2061+
ret = CONFIG_INVALID_FILE;
2062+
contents = NULL;
2063+
goto out_free;
2064+
}
20552065
close(in_fd);
20562066

20572067
if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) {
@@ -2106,8 +2116,6 @@ int git_config_set_multivar_in_file(const char *config_filename,
21062116
contents_sz - copy_begin) <
21072117
contents_sz - copy_begin)
21082118
goto write_err_out;
2109-
2110-
munmap(contents, contents_sz);
21112119
}
21122120

21132121
if (commit_lock_file(lock) < 0) {
@@ -2133,6 +2141,8 @@ int git_config_set_multivar_in_file(const char *config_filename,
21332141
if (lock)
21342142
rollback_lock_file(lock);
21352143
free(filename_buf);
2144+
if (contents)
2145+
munmap(contents, contents_sz);
21362146
return ret;
21372147

21382148
write_err_out:

git-compat-util.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,7 @@ extern char *xstrndup(const char *str, size_t len);
717717
extern void *xrealloc(void *ptr, size_t size);
718718
extern void *xcalloc(size_t nmemb, size_t size);
719719
extern void *xmmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
720+
extern void *xmmap_gently(void *start, size_t length, int prot, int flags, int fd, off_t offset);
720721
extern ssize_t xread(int fd, void *buf, size_t len);
721722
extern ssize_t xwrite(int fd, const void *buf, size_t len);
722723
extern ssize_t xpread(int fd, void *buf, size_t len, off_t offset);

read-cache.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1540,7 +1540,7 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
15401540
if (mmap_size < sizeof(struct cache_header) + 20)
15411541
die("index file smaller than expected");
15421542

1543-
mmap = xmmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1543+
mmap = xmmap(NULL, mmap_size, PROT_READ, MAP_PRIVATE, fd, 0);
15441544
if (mmap == MAP_FAILED)
15451545
die_errno("unable to map index file");
15461546
close(fd);

sha1_file.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -707,8 +707,8 @@ static void mmap_limit_check(size_t length)
707707
(uintmax_t)length, (uintmax_t)limit);
708708
}
709709

710-
void *xmmap(void *start, size_t length,
711-
int prot, int flags, int fd, off_t offset)
710+
void *xmmap_gently(void *start, size_t length,
711+
int prot, int flags, int fd, off_t offset)
712712
{
713713
void *ret;
714714

@@ -719,12 +719,19 @@ void *xmmap(void *start, size_t length,
719719
return NULL;
720720
release_pack_memory(length);
721721
ret = mmap(start, length, prot, flags, fd, offset);
722-
if (ret == MAP_FAILED)
723-
die_errno("Out of memory? mmap failed");
724722
}
725723
return ret;
726724
}
727725

726+
void *xmmap(void *start, size_t length,
727+
int prot, int flags, int fd, off_t offset)
728+
{
729+
void *ret = xmmap_gently(start, length, prot, flags, fd, offset);
730+
if (ret == MAP_FAILED)
731+
die_errno("mmap failed");
732+
return ret;
733+
}
734+
728735
void close_pack_windows(struct packed_git *p)
729736
{
730737
while (p->windows) {

0 commit comments

Comments
 (0)