Skip to content

Commit 37f44c7

Browse files
iamhuskarrocallahan
authored andcommitted
fix: copy_file skip files larger than 1GB (Fixes #4039)
1 parent b6a34ae commit 37f44c7

3 files changed

Lines changed: 43 additions & 2 deletions

File tree

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,7 @@ set(BASIC_TESTS
11881188
memfd_create_efault
11891189
memfd_create_shared
11901190
memfd_create_shared_huge
1191+
memfd_create_dotnet_huge_mapping
11911192
mincore
11921193
mknod
11931194
mlock

src/TraceStream.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -995,10 +995,13 @@ TraceWriter::RecordInTrace TraceWriter::write_mapped_region(
995995
// debuggers can't find the file, but the Linux loader doesn't create
996996
// shared mappings so situations where a shared-mapped executable contains
997997
// usable debug info should be very rare at best...
998+
// copy files when the mapping is PROT_EXEC, unless the file is too big
999+
// sometimes km.size() does not equal the file size from fstat().
9981000
string backing_file_name;
9991001
if ((km.prot() & PROT_EXEC) &&
1000-
copy_file(km.fsname(), file_name, &backing_file_name) &&
1001-
!(km.flags() & MAP_SHARED)) {
1002+
!(km.flags() & MAP_SHARED) &&
1003+
stat.st_size <= 1024 * 1024 * 1024 &&
1004+
copy_file(km.fsname(), file_name, &backing_file_name)) {
10021005
src.initFile().setBackingFileName(str_to_data(backing_file_name));
10031006
} else {
10041007
src.setTrace();
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
#include "util.h"
2+
/*
3+
https://github.com/dotnet/runtime/blob/23aeecc9f91a9ae0a211702dbd849c90cdd81d36/src/coreclr/minipal/Unix/doublemapping.cpp#L85
4+
#ifdef TARGET_64BIT
5+
static const off_t MaxDoubleMappedSize = 2048ULL*1024*1024*1024;
6+
#else
7+
static const off_t MaxDoubleMappedSize = UINT_MAX;
8+
#endif
9+
To prevent bugs that could result in writing a 2TB file, a 20GB limit is used instead.
10+
*/
11+
#define _1GB (1024 * 1024 * 1024ULL)
12+
unsigned long long MaxDoubleMappedSize = 20 * _1GB;
13+
#define PAGE_SIZE_4K 4096
14+
15+
void test_ftruncate_huge_mapping(void) {
16+
int fd = memfd_create("double_mapper_test", MFD_CLOEXEC);
17+
test_assert(fd >= 0);
18+
test_assert(ftruncate(fd, MaxDoubleMappedSize) == 0);
19+
void* executable_addr = mmap(NULL, PAGE_SIZE_4K, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0);
20+
test_assert(executable_addr != MAP_FAILED);
21+
test_assert(0 == close(fd));
22+
}
23+
24+
int main(void) {
25+
#if defined(__i386__)
26+
atomic_puts("Skipping test on 32 bit");
27+
#else
28+
struct timespec start, end;
29+
test_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &start));
30+
test_ftruncate_huge_mapping();
31+
test_assert(-1 != clock_gettime(CLOCK_MONOTONIC, &end));
32+
//check timeout
33+
test_assert((end.tv_sec - start.tv_sec) <= 2);
34+
#endif
35+
atomic_puts("EXIT-SUCCESS");
36+
return 0;
37+
}

0 commit comments

Comments
 (0)