fix: copy_file skip files larger than 1GB (Fixes #4039)#4051
fix: copy_file skip files larger than 1GB (Fixes #4039)#4051IamHuskar wants to merge 4 commits intorr-debugger:masterfrom
Conversation
|
Why is the MAP_SHARED check placed after copy_file? Line 1001 in 1f6d9a0 If the km region is MAP_SHARED, src.setTrace will be executed, but at that point, the file copying has already been completed. |
src/TraceStream.cc
Outdated
| // the size of km is not equal to the file size obtained through the fstat | ||
| struct stat src_stat; | ||
| ScopedFd src_fd(file_name.c_str(), O_RDONLY); | ||
| if (src_fd.is_open() && (fstat(src_fd.get(), &src_stat) == 0)) { |
There was a problem hiding this comment.
You can use the stat that's a parameter to TraceWriter::write_mapped_region().
There was a problem hiding this comment.
You can use the
statthat's a parameter toTraceWriter::write_mapped_region().
I searched through all the code and found that some function calls to write_mapped_region pass xxx.fake_stat() as an argument, meaning the stat here might be the result of fake_stat. Can we still directly use stat here?
| typedef void (*simple_func_t)(void); | ||
|
|
||
| #ifdef __x86_64__ | ||
| static const unsigned char x86_ret_instruction = 0xC3; // ret |
There was a problem hiding this comment.
I don't think you actually need to map and execute code. All you need to do is construct a really large totally empty mapping, map it PROT_EXEC, and hopefully that will cause the test to time out if this bug is not fixed properly.
|
It seems that after running scripts/reformat.sh, the code formatting changes dramatically. I wonder if it's due to the version of clang-format. How should I format my code? |
| if ((km.prot() & PROT_EXEC) && | ||
| copy_file(km.fsname(), file_name, &backing_file_name) && | ||
| !(km.flags() & MAP_SHARED)) { | ||
| (!(km.flags() & MAP_SHARED) && |
There was a problem hiding this comment.
The first ( (and the matching )) is unnecessary.
| copy_file(km.fsname(), file_name, &backing_file_name) && | ||
| !(km.flags() & MAP_SHARED)) { | ||
| (!(km.flags() & MAP_SHARED) && | ||
| (stat.st_size <= 1024 * 1024 * 1024/*1GB*/) && |
There was a problem hiding this comment.
This ( and the matching ) are also unnecessary.
| @@ -0,0 +1,61 @@ | |||
| #include "util.h" | |||
| #include <time.h> | |||
There was a problem hiding this comment.
Pretty sure this #include is not necessary.
| unsigned long long MaxDoubleMappedSize = 20 * _1GB; | ||
| #define PAGE_SIZE_4K 4096 | ||
| int test_ftruncate_huge_mapping(void) | ||
| { |
There was a problem hiding this comment.
Please manually format this the way we normally do, with { on the same line as the function declaration.
| int ret=-1; | ||
| int fd = memfd_create("double_mapper_test", MFD_CLOEXEC); | ||
| do | ||
| { |
There was a problem hiding this comment.
Similar here and below.
| int fd = memfd_create("double_mapper_test", MFD_CLOEXEC); | ||
| do | ||
| { | ||
| if (fd == -1) |
There was a problem hiding this comment.
Use test_assert(fd >= 0) instead.
| atomic_puts("memfd_create failed"); | ||
| break; | ||
| } | ||
| if (ftruncate(fd, MaxDoubleMappedSize) == -1) |
| break; | ||
| } | ||
| void* executable_addr = mmap(NULL, PAGE_SIZE_4K, PROT_READ | PROT_EXEC, MAP_PRIVATE, fd, 0); | ||
| if (executable_addr == MAP_FAILED) |
| atomic_puts("mmap for executable mapping failed"); | ||
| break; | ||
| } | ||
| munmap(executable_addr, PAGE_SIZE_4K); |
There was a problem hiding this comment.
You don't really need to munmap, it's fine to leak it in a test.
| #define _1GB (1024 * 1024 * 1024ULL) | ||
| unsigned long long MaxDoubleMappedSize = 20 * _1GB; | ||
| #define PAGE_SIZE_4K 4096 | ||
| int test_ftruncate_huge_mapping(void) |
There was a problem hiding this comment.
This function can return void.
6d491ec to
2517dff
Compare
The original PR at #4048 . should use rebase instead of merge.