Use EXCEPTION_STATE_IDENTITY_PROTECTED on iOS. [crashpad/crashpad : main]

13 views
Skip to first unread message

Justin Cohen (Gerrit)

unread,
Dec 2, 2025, 12:47:19 PM12/2/25
to Mark Mentovai, Crashpad LUCI CQ, crashp...@chromium.org
Attention needed from Mark Mentovai

Justin Cohen added 1 comment

Patchset-level comments
File-level comment, Patchset 9 (Latest):
Justin Cohen . resolved

This is need for using Blink on iOS. I'm not sure why PROTECTED is required by Apple for Blink on iOS, or even if the in-process design for iOS makes sense for Blink on iOS.

If it does, this appears to work, but my big open questions are:

  • (1) when to use EXCEPTION_STATE_IDENTITY_PROTECTED vs EXCEPTION_STATE_IDENTITY [perhaps as a flag passed to Crashpad, or maybe it's fine to use on anyone > iOS18]
  • (2) Why the PROTECTED API doesn't pass the task and thread like the non-PROTECTED version, and if it's OK to simply recover it to match the old API, like I do in this CL (util/mach/exc_server_variants.cc::469-513)
  • (3) Perhaps more minor, but the difference between ExcTraits and MachExcTraits each having their own kMachMessageIDExceptionRaiseStateIdentityProtected const (with the ExcTraits version unused)

Consider this is a first draft in what perhaps should be a conversation. Let me know if doing this over CL comments is OK, or if you'd prefer to chat.

Thanks!

Open in Gerrit

Related details

Attention is currently required from:
  • Mark Mentovai
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: crashpad/crashpad
Gerrit-Branch: main
Gerrit-Change-Id: I228784ed765a6b996473ed07e2c0f34f14f93d37
Gerrit-Change-Number: 7204428
Gerrit-PatchSet: 9
Gerrit-Owner: Justin Cohen <justi...@chromium.org>
Gerrit-Reviewer: Justin Cohen <justi...@chromium.org>
Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
Gerrit-Attention: Mark Mentovai <ma...@chromium.org>
Gerrit-Comment-Date: Tue, 02 Dec 2025 17:47:16 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
unsatisfied_requirement
open
diffy

Mark Mentovai (Gerrit)

unread,
Jan 29, 2026, 9:30:54 AM (9 days ago) Jan 29
to Justin Cohen, Code Review Nudger, Crashpad LUCI CQ, crashp...@chromium.org
Attention needed from Justin Cohen

Mark Mentovai added 11 comments

Commit Message
Line 17, Patchset 10 (Latest):- 1 The `in_request` uses a `task_id_token_t` instead of providing a
send right to the excepting task's port. The handler uses
`task_identity_token_get_task_port()` to retrieve the task port from
this token.
- 2 Instead of a `in_request->thread.name` (thread port), the handler
receives a `in_request->thread_id`. This ID is used to find the
corresponding thread port by iterating through the task's threads.
Mark Mentovai . unresolved

This list doesn’t need to be numbered.

File client/crash_handler_ios.cc
Line 154, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
if (__builtin_available(iOS 18, *)) {
// It seems like EXCEPTION_STATE_IDENTITY_PROTECTED works everywhere, but I
// wonder if this would be safer as an optional flag passed to Crashpad?
state_identity = EXCEPTION_STATE_IDENTITY_PROTECTED;
}
#endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
// __IPHONE_18_0
Mark Mentovai . unresolved

For iOS (including simulator), I think it’s probably safe to use this unconditionally.

That only applies to this file, though. I’ll talk about the other files when I get there.

File util/mach/exc_server_variants.cc
Line 18, Patchset 10 (Latest):#include <mach/task.h>
Mark Mentovai . unresolved

Not necessary, because `"util/mach/exc_server/variants.h"` already brings in all of `<mach/mach.h>`.

Line 87, Patchset 10 (Latest): // Unused
Mark Mentovai . unresolved

Unused?

I think there are lots of things in this file that are potentially unused. Why call this one out?

Line 106, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
using ExceptionRaiseStateIdentityProtectedRequest =
__Request__mach_exception_raise_state_identity_protected_t;
#endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
// __IPHONE_18_0
Mark Mentovai . unresolved

Typedefs are safe to do unconditionally, as long as we’re sure that the types exist. We always `mig` our own recent copy of `<mach/mach_exc.defs>`, so these types should always exist. These sorts of things can be unconditional.

Line 148, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
static kern_return_t MIGCheckRequestExceptionRaiseStateIdentityProtected(
const ExceptionRaiseStateIdentityProtectedRequest* in_request,
const ExceptionRaiseStateIdentityProtectedRequest** in_request_1) {
return __MIG_check__Request__mach_exception_raise_state_identity_protected_t(
const_cast<ExceptionRaiseStateIdentityProtectedRequest*>(in_request),
const_cast<ExceptionRaiseStateIdentityProtectedRequest**>(
in_request_1));
}
#endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
// __IPHONE_18_0
Mark Mentovai . unresolved

Same for functions like this that operate on types that you know you have access to, even if the function may not be used.

Line 251, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
//! \brief Handles exceptions raised by
//! `mach_exception_raise_state_identity_protected()`.
//!
//! This behaves equivalently to a
//! `catch_mach_exception_raise_state_identity_protected()` function used
//! with `mach_exc_server()`.
//!
//! \param[in] trailer The trailer received with the request message.
//! \param[out] destroy_request `true` if the request message is to be
//! destroyed even when this method returns success. See
//! MachMessageServer::Interface.
virtual kern_return_t CatchExceptionRaiseStateIdentityProtected(
exception_handler_t exception_port,
thread_t thread,
task_t task,
exception_type_t exception,
const typename Traits::ExceptionCode* code,
mach_msg_type_number_t code_count,
thread_state_flavor_t* flavor,
ConstThreadState old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) = 0;
#endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
// __IPHONE_18_0
Mark Mentovai . unresolved

Here’s where things get trickier. We may not want to define a new pure virtual interface and force other downstream things to have to implement it yet.

But: your enabling condition is more complex than it needs to be. Don’t we always build with an iOS SDK ≥ 18?

This should wind up matching whatever condition applies to the other (_ios) file, so if you drop the `#if` from that file altogether and it winds up applying to all _ios builds (device and simulator) without regard to SDK version, then this should match.

Exception to all of this: if everything gets funneled through the “Simplified” interface which you’ve taken care of implementing already, then there won’t be anything for anyone else to need to implement, and you can make this unconditional. I would prefer that, but only if it doesn’t mean any extra (unused, untested) code.

Line 304, Patchset 10 (Latest): Traits::kMachMessageIDExceptionRaiseStateIdentityProtected,
Mark Mentovai . unresolved

You would want the same condition to wrap this.

Line 450, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
Mark Mentovai . unresolved

And this.

Line 713, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
Mark Mentovai . unresolved

And this.

File util/mach/exc_server_variants_test.cc
Line 228, Patchset 10 (Latest):#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0
Mark Mentovai . unresolved

And then this file would just need to see its conditions tweaked to match what’s done in the others.

Open in Gerrit

Related details

Attention is currently required from:
  • Justin Cohen
Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: crashpad/crashpad
    Gerrit-Branch: main
    Gerrit-Change-Id: I228784ed765a6b996473ed07e2c0f34f14f93d37
    Gerrit-Change-Number: 7204428
    Gerrit-PatchSet: 10
    Gerrit-Owner: Justin Cohen <justi...@chromium.org>
    Gerrit-Reviewer: Justin Cohen <justi...@chromium.org>
    Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Justin Cohen <justi...@chromium.org>
    Gerrit-Comment-Date: Thu, 29 Jan 2026 14:30:50 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy

    Justin Cohen (Gerrit)

    unread,
    Jan 29, 2026, 3:17:59 PM (9 days ago) Jan 29
    to Code Review Nudger, Mark Mentovai, Crashpad LUCI CQ, crashp...@chromium.org
    Attention needed from Mark Mentovai

    Justin Cohen added 7 comments

    Patchset-level comments
    File-level comment, Patchset 14 (Latest):
    Justin Cohen . unresolved

    I think if we are only supporting Xcode 16+ everywhere then this doesn't need a conditional anywhere. WDYT? I intentionally left many of the comments unresolved since they are all the same thing -- in case this isn't what you preferred.

    PTAL

    Commit Message
    Line 17, Patchset 10:- 1 The `in_request` uses a `task_id_token_t` instead of providing a

    send right to the excepting task's port. The handler uses
    `task_identity_token_get_task_port()` to retrieve the task port from
    this token.
    - 2 Instead of a `in_request->thread.name` (thread port), the handler
    receives a `in_request->thread_id`. This ID is used to find the
    corresponding thread port by iterating through the task's threads.
    Mark Mentovai . resolved

    This list doesn’t need to be numbered.

    Justin Cohen

    Done

    File client/crash_handler_ios.cc
    Line 154, Patchset 10:#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0

    if (__builtin_available(iOS 18, *)) {
    // It seems like EXCEPTION_STATE_IDENTITY_PROTECTED works everywhere, but I
    // wonder if this would be safer as an optional flag passed to Crashpad?
    state_identity = EXCEPTION_STATE_IDENTITY_PROTECTED;
    }
    #endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
    // __IPHONE_18_0
    Mark Mentovai . resolved

    For iOS (including simulator), I think it’s probably safe to use this unconditionally.

    That only applies to this file, though. I’ll talk about the other files when I get there.

    Justin Cohen

    Done

    File util/mach/exc_server_variants.cc
    Line 18, Patchset 10:#include <mach/task.h>
    Mark Mentovai . resolved

    Not necessary, because `"util/mach/exc_server/variants.h"` already brings in all of `<mach/mach.h>`.

    Justin Cohen

    Done

    Line 87, Patchset 10: // Unused
    Mark Mentovai . resolved

    Unused?

    I think there are lots of things in this file that are potentially unused. Why call this one out?

    Justin Cohen

    removed

    Line 106, Patchset 10:#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0

    using ExceptionRaiseStateIdentityProtectedRequest =
    __Request__mach_exception_raise_state_identity_protected_t;
    #endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
    // __IPHONE_18_0
    Mark Mentovai . resolved

    Typedefs are safe to do unconditionally, as long as we’re sure that the types exist. We always `mig` our own recent copy of `<mach/mach_exc.defs>`, so these types should always exist. These sorts of things can be unconditional.

    Justin Cohen

    Done

    Line 148, Patchset 10:#if defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_18_0

    static kern_return_t MIGCheckRequestExceptionRaiseStateIdentityProtected(
    const ExceptionRaiseStateIdentityProtectedRequest* in_request,
    const ExceptionRaiseStateIdentityProtectedRequest** in_request_1) {
    return __MIG_check__Request__mach_exception_raise_state_identity_protected_t(
    const_cast<ExceptionRaiseStateIdentityProtectedRequest*>(in_request),
    const_cast<ExceptionRaiseStateIdentityProtectedRequest**>(
    in_request_1));
    }
    #endif // defined(__IPHONE_18_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >=
    // __IPHONE_18_0
    Mark Mentovai . resolved

    Same for functions like this that operate on types that you know you have access to, even if the function may not be used.

    Justin Cohen

    Done

    Open in Gerrit

    Related details

    Attention is currently required from:
    • Mark Mentovai
    Submit Requirements:
    • requirement satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedNo-Unresolved-Comments
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: crashpad/crashpad
    Gerrit-Branch: main
    Gerrit-Change-Id: I228784ed765a6b996473ed07e2c0f34f14f93d37
    Gerrit-Change-Number: 7204428
    Gerrit-PatchSet: 14
    Gerrit-Owner: Justin Cohen <justi...@chromium.org>
    Gerrit-Reviewer: Justin Cohen <justi...@chromium.org>
    Gerrit-Reviewer: Mark Mentovai <ma...@chromium.org>
    Gerrit-CC: Code Review Nudger <android-build...@prod.google.com>
    Gerrit-Attention: Mark Mentovai <ma...@chromium.org>
    Gerrit-Comment-Date: Thu, 29 Jan 2026 20:17:56 +0000
    Gerrit-HasComments: Yes
    Gerrit-Has-Labels: No
    Comment-In-Reply-To: Mark Mentovai <ma...@chromium.org>
    satisfied_requirement
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages