Skip to content

Commit

Permalink
In cgmemmgr, allow writing permissions on the read page for the debugger
Browse files Browse the repository at this point in the history
The permissions specified in MapViewOfFile specify the maximum permissions
the file can ever have, which means that even permissions bypass by the
debugger is not allowed to write it. Instead, set the maximum permissions
to RWX and VirtualProtect down to the permissions we need. This is the same
behavior as we use on Mac/Linux.
  • Loading branch information
Keno committed Aug 25, 2016
1 parent 3ab4d76 commit 4f1ba0c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/cgmemmgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,18 @@ static intptr_t init_shared_map()
static void *alloc_shared_page(size_t size, size_t *id, bool exec)
{
assert(size % jl_page_size == 0);
auto file_mode = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
DWORD file_mode = exec ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
HANDLE hdl = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
file_mode, 0, size, NULL);
*id = (size_t)hdl;
auto map_mode = FILE_MAP_READ | (exec ? FILE_MAP_EXECUTE : 0);
// We set the maximum permissions for this to the maximum for this file, and then
// VirtualProtect, such that the debugger can still access these
// pages and set breakpoints if it wants to.
DWORD map_mode = FILE_MAP_ALL_ACCESS | (exec ? FILE_MAP_EXECUTE : 0);
void *addr = MapViewOfFile(hdl, map_mode, 0, 0, size);
assert(addr && "Cannot map RO view");
DWORD protect_mode = exec ? PAGE_EXECUTE_READ : PAGE_READONLY;
VirtualProtect(addr, size, protect_mode, &file_mode);
return addr;
}
#else // _OS_WINDOWS_
Expand Down
15 changes: 15 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -435,3 +435,18 @@ let creds = Base.LibGit2.CachedCredentials()
securezero!(creds)
@test LibGit2.get_creds!(creds, "foo", nothing).pass == "\0\0\0"
end

# Test that we can VirtualProtect jitted code to writable
if is_windows()
@noinline function WeVirtualProtectThisToRWX(x, y)
x+y
end

let addr = cfunction(WeVirtualProtectThisToRWX, UInt64, (UInt64, UInt64))
addr = addr-(UInt64(addr)%4096)
const PAGE_EXECUTE_READWRITE = 0x40
oldPerm = Ref{UInt32}()
err = ccall(:VirtualProtect,stdcall,Cint,(Ptr{Void}, Csize_t, UInt32, Ptr{UInt32}), addr, 4096, PAGE_EXECUTE_READWRITE, oldPerm)
err == 0 && error(Libc.GetLastError())
end
end

0 comments on commit 4f1ba0c

Please sign in to comment.