dyld::halt() EXC_CRASH exceptions arrive with a corpse task port despite not being EXC_CORPSE_NOTIFY
| Originator: | mark | ||
| Number: | rdar://29079442 | Date Originated: | 2016-11-02 |
| Status: | Closed | Resolved: | Behaves correctly |
| Product: | macOS | Product Version: | 10.12.1 16B2657 |
| Classification: | Other Bug | Reproducible: | Always |
I compare task ports received in my catch_mach_exception_raise_state_identity() handlers against known task ports to know which task an exception message corresponds to. In 10.12.1, the task ports received through this mechanism when dyld terminates are not proper task ports, but appear to be corpse tasks ports. A corpse task port has a different port name than the original task port from when it was a live task. Corpse task ports are expected when receiving EXC_CORPSE_NOTIFY exceptions, but I am seeing this behavior even when receiving EXC_CRASH exceptions. dyld switched to using the new abort_with_payload() mechanism from dyld::halt() in 10.12, but I did not experience this problem in 10.12. I only see it in 10.12.1. Steps to Reproduce: catch_dyld_crash.cc is a reduced testcase. It runs as a parent, which forks a child. The parent runs a Mach exception handler and waits for the child to crash. The child sets its task exception port for EXC_MASK_CRASH to the handler in the parent. The child then sets DYLD_INSERT_LIBRARIES to a nonexistent file and attempts to re-execute itself, triggering dyld to terminate via dyld::halt(). The EXC_CRASH exception message is delivered to the parent’s catch_exception_raise() function, with the |task| argument indicating which task crashed. $ clang++ -g catch_dyld_crash.cc -o catch_dyld_crash $ ./catch_dyld_crash Expected Results: Here’s 10.12 16A323. Previous OS versions are similar. $ ./catch_dyld_crash fork(): pid 655 child: pid 655 parent: child task 0xe03 dyld: could not load inserted library '/var/empty/NoDirectory/NoLibrary' because image not found catch_exception_raise(): task 0xe03 catch_exception_raise(): pid 655 waitpid(): pid 655, stat 0x6 passed $ Note “passed” at the bottom. Actual Results: Here’s 10.12.1 16B2657. It’s broken. $ ./catch_dyld_crash fork(): pid 3377 child: pid 3377 parent: child task 0xe03 dyld: could not load inserted library '/var/empty/NoDirectory/NoLibrary' because image not found catch_exception_raise(): task 0x1003 catch_exception_raise(): pid 3377 waitpid(): pid 3377, stat 0x6 FAILED: child task 0xe03 != exception task 0x1003 $ It says FAILED at the bottom, because the live child task (0xe03) doesn’t match the task received by the EXC_CRASH handler (0x1003). Version: 10.12.1 16B2657 Notes: https://crashpad.chromium.org/bug/137 Configuration: This bug occurs in 10.12.1 16B2657. It did not occur in 10.12 16A323 or previous OS versions. Attachments: 'catch_dyld_crash.cc' was successfully uploaded. (https://bugs.chromium.org/p/crashpad/issues/attachment?aid=257618)
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!
2017-03-17 21:51:45 UTC from Apple
Engineering has the following feedback for you:
It is not a corpse task port. Due to exec changes in 10.12.1, a new task and a new thread are created on exec which will have a new task port, hence after exec, the task port would not be same across exec, it will change, it its still a task port and not a corpse port.
Thank you for your feedback. Engineering has determined that this issue behaves as intended.
We are now closing this bug report.