Skip to content

Conversation

@Keno
Copy link
Member

@Keno Keno commented Jul 12, 2020

Needs decoding of the ARM64 ESR register. Additionally, the Aarch64 ABI requires 16 byte aligned stack
pointers on function entry, so we can't push the return pointer there. Whether we need to construct a
stack frame instead will depend on the unwinder (which doesn't work yet), but I don't believe so,
since the ABI mandates a frame pointer.

@Keno Keno requested a review from yuyichao July 12, 2020 00:38
@Keno Keno mentioned this pull request Jul 12, 2020
31 tasks
@Keno Keno force-pushed the kf/applearm64segv branch from fd59faf to 4e07953 Compare July 12, 2020 00:40
@Keno
Copy link
Member Author

Keno commented Jul 12, 2020

Oh, also added a test for this code path, since I don't think we had one.

#ifdef _CPU_X86_64_
// push (null) $RIP onto the stack
rsp -= sizeof(void*);
*(void**)rsp = NULL;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The corresponding aarch64 operation is setting lr to zero.

ctx->uc_mcontext.regs[29] = 0; // Clear link register (x29)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And is

ucontext64_t *ctx = (ucontext64_t*)_ctx;
used?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I was wondering if we should set lr to NULL, but I haven't looked at the unwinder yet. I guess it can't really hurt.

Copy link
Contributor

@yuyichao yuyichao Jul 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it shoudn't hurt. And I think at least in one case I've seen it helps the unwinder (either ours or gdb) terminates the stack trace. (on linux...)

# Test that read fault on a prot-none region does not incorrectly give
# ReadOnlyMemoryEror, but rather crashes the program
const MAP_ANONYMOUS_PRIVATE = Sys.isbsd() ? 0x1002 : 0x22
let script = :(let ptr = Ptr{Cint}(ccall(:jl_mmap, Ptr{Cvoid},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we actually guarantee this everywhere else?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we have this logic on every platform.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It throws readonlymmoryerror on linux for example. I don't really see why it's that important to differentiate reading PROT_NONE from writing PROT_READ. The linux one only check for permission violation and would tread violation of read/write/execution the same.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imaging what you could do is to unmap the page before issueing the unsafe_load. Assuming the code is compiled it should make sure you are loading from a hole in the mapping and that should be a crash.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imaging what you could do is to unmap the page before issueing the unsafe_load. Assuming the code is compiled it should make sure you are loading from a hole in the mapping and that should be a crash.

That doesn't exercise this code path. We explicitly check that the mapping exists first.

Copy link
Member Author

@Keno Keno Jul 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we may just want to fix the linux behavior here to bring it in line with mac/windows. I don't see a good reason to throw ReadOnlyMemoryError here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

... Sure, that's fine. It's technically breaking but it was an error before anyway...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or it's a bug fix and brings linux in line with the other platforms ;).

Copy link
Contributor

@yuyichao yuyichao Jul 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Breaking" for ppl (like me) who hardly ever use julia anywhere other than linux... Not that I've ever cought any read only memory error when reading things anyway.............

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do agree the name of the exception is very suggestive of what it should do...

Copy link
Contributor

@yuyichao yuyichao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either the test or the implementation needs to be updated.

# Test that read fault on a prot-none region does not incorrectly give
# ReadOnlyMemoryEror, but rather crashes the program
const MAP_ANONYMOUS_PRIVATE = Sys.isbsd() ? 0x1002 : 0x22
let script = :(let ptr = Ptr{Cint}(ccall(:jl_mmap, Ptr{Cvoid},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It throws readonlymmoryerror on linux for example. I don't really see why it's that important to differentiate reading PROT_NONE from writing PROT_READ. The linux one only check for permission violation and would tread violation of read/write/execution the same.

Keno added a commit that referenced this pull request Feb 24, 2021
This replaces #36625. Essentially the question is what should
reading from PROT_NONE memory do. At the moment we throw
ReadOnlyMemoryError on Linux and pass through the segfault on
Windows/Mac. It's not super clear what the right answer is,
though it would be nice to be consistent. After some discussion,
it seemed that not throwing ReadOnlyMemoryError on Linux was probably
the better consistency direction for two reasons:

1. Getting a ReadOnlyMemoryError is confusing if the failing operation
   is a read. We could of course rename the error, but that would be
   a bigger breaking change.
2. The purpose of this exception is to protect people who accidentally
   try to write to mmap'ed memory that they don't have write permissions
   to. It was never intended to become a general memory access error
   exception, so it seems prudent to restrict it as much as possible.

To make this happen, there is some platform specific code here to
read the memory error register out of the signal context.
Decoding this register is shared code between the operating systems,
but the register itself is in an OS-specifc location in the signal
frame. I have implemented the retrieval code for all our CI'ed
platforms. Other users will get an appropriate `#warning` (similar
to other code in this file) and can fill in the necessary code
at their leisure. A new test in test/misc.jl will indicate whether
or not the check is correct.
Keno added a commit that referenced this pull request Feb 24, 2021
This replaces #36625. Essentially the question is what should
reading from PROT_NONE memory do. At the moment we throw
ReadOnlyMemoryError on Linux and pass through the segfault on
Windows/Mac. It's not super clear what the right answer is,
though it would be nice to be consistent. After some discussion,
it seemed that not throwing ReadOnlyMemoryError on Linux was probably
the better consistency direction for two reasons:

1. Getting a ReadOnlyMemoryError is confusing if the failing operation
   is a read. We could of course rename the error, but that would be
   a bigger breaking change.
2. The purpose of this exception is to protect people who accidentally
   try to write to mmap'ed memory that they don't have write permissions
   to. It was never intended to become a general memory access error
   exception, so it seems prudent to restrict it as much as possible.

To make this happen, there is some platform specific code here to
read the memory error register out of the signal context.
Decoding this register is shared code between the operating systems,
but the register itself is in an OS-specifc location in the signal
frame. I have implemented the retrieval code for all our CI'ed
platforms. Other users will get an appropriate `#warning` (similar
to other code in this file) and can fill in the necessary code
at their leisure. A new test in test/misc.jl will indicate whether
or not the check is correct.
Keno added a commit that referenced this pull request Feb 24, 2021
This replaces #36625. Essentially the question is what should
reading from PROT_NONE memory do. At the moment we throw
ReadOnlyMemoryError on Linux and pass through the segfault on
Windows/Mac. It's not super clear what the right answer is,
though it would be nice to be consistent. After some discussion,
it seemed that not throwing ReadOnlyMemoryError on Linux was probably
the better consistency direction for two reasons:

1. Getting a ReadOnlyMemoryError is confusing if the failing operation
   is a read. We could of course rename the error, but that would be
   a bigger breaking change.
2. The purpose of this exception is to protect people who accidentally
   try to write to mmap'ed memory that they don't have write permissions
   to. It was never intended to become a general memory access error
   exception, so it seems prudent to restrict it as much as possible.

To make this happen, there is some platform specific code here to
read the memory error register out of the signal context.
Decoding this register is shared code between the operating systems,
but the register itself is in an OS-specifc location in the signal
frame. I have implemented the retrieval code for all our CI'ed
platforms. Other users will get an appropriate `#warning` (similar
to other code in this file) and can fill in the necessary code
at their leisure. A new test in test/misc.jl will indicate whether
or not the check is correct.
Keno added a commit that referenced this pull request Feb 24, 2021
This replaces #36625. Essentially the question is what should
reading from PROT_NONE memory do. At the moment we throw
ReadOnlyMemoryError on Linux and pass through the segfault on
Windows/Mac. It's not super clear what the right answer is,
though it would be nice to be consistent. After some discussion,
it seemed that not throwing ReadOnlyMemoryError on Linux was probably
the better consistency direction for two reasons:

1. Getting a ReadOnlyMemoryError is confusing if the failing operation
   is a read. We could of course rename the error, but that would be
   a bigger breaking change.
2. The purpose of this exception is to protect people who accidentally
   try to write to mmap'ed memory that they don't have write permissions
   to. It was never intended to become a general memory access error
   exception, so it seems prudent to restrict it as much as possible.

To make this happen, there is some platform specific code here to
read the memory error register out of the signal context.
Decoding this register is shared code between the operating systems,
but the register itself is in an OS-specifc location in the signal
frame. I have implemented the retrieval code for all our CI'ed
platforms. Other users will get an appropriate `#warning` (similar
to other code in this file) and can fill in the necessary code
at their leisure. A new test in test/misc.jl will indicate whether
or not the check is correct.
@Keno Keno closed this Feb 24, 2021
@DilumAluthge DilumAluthge deleted the kf/applearm64segv branch March 25, 2021 21:57
ElOceanografo pushed a commit to ElOceanografo/julia that referenced this pull request May 4, 2021
This replaces JuliaLang#36625. Essentially the question is what should
reading from PROT_NONE memory do. At the moment we throw
ReadOnlyMemoryError on Linux and pass through the segfault on
Windows/Mac. It's not super clear what the right answer is,
though it would be nice to be consistent. After some discussion,
it seemed that not throwing ReadOnlyMemoryError on Linux was probably
the better consistency direction for two reasons:

1. Getting a ReadOnlyMemoryError is confusing if the failing operation
   is a read. We could of course rename the error, but that would be
   a bigger breaking change.
2. The purpose of this exception is to protect people who accidentally
   try to write to mmap'ed memory that they don't have write permissions
   to. It was never intended to become a general memory access error
   exception, so it seems prudent to restrict it as much as possible.

To make this happen, there is some platform specific code here to
read the memory error register out of the signal context.
Decoding this register is shared code between the operating systems,
but the register itself is in an OS-specifc location in the signal
frame. I have implemented the retrieval code for all our CI'ed
platforms. Other users will get an appropriate `#warning` (similar
to other code in this file) and can fill in the necessary code
at their leisure. A new test in test/misc.jl will indicate whether
or not the check is correct.
antoine-levitt pushed a commit to antoine-levitt/julia that referenced this pull request May 9, 2021
This replaces JuliaLang#36625. Essentially the question is what should
reading from PROT_NONE memory do. At the moment we throw
ReadOnlyMemoryError on Linux and pass through the segfault on
Windows/Mac. It's not super clear what the right answer is,
though it would be nice to be consistent. After some discussion,
it seemed that not throwing ReadOnlyMemoryError on Linux was probably
the better consistency direction for two reasons:

1. Getting a ReadOnlyMemoryError is confusing if the failing operation
   is a read. We could of course rename the error, but that would be
   a bigger breaking change.
2. The purpose of this exception is to protect people who accidentally
   try to write to mmap'ed memory that they don't have write permissions
   to. It was never intended to become a general memory access error
   exception, so it seems prudent to restrict it as much as possible.

To make this happen, there is some platform specific code here to
read the memory error register out of the signal context.
Decoding this register is shared code between the operating systems,
but the register itself is in an OS-specifc location in the signal
frame. I have implemented the retrieval code for all our CI'ed
platforms. Other users will get an appropriate `#warning` (similar
to other code in this file) and can fill in the necessary code
at their leisure. A new test in test/misc.jl will indicate whether
or not the check is correct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants