ios: Build four more Mach message and exception utilities

This enables the following code in util/mach on iOS:
 - exception_behaviors.{cc,h}
 - exception_ports.{cc,h}
 - mach_message.{cc,h}
 - mach_message_server.{cc,h}

Only the ExceptionBehaviors and MachMessage tests are built, because the
other two are tested by multiprocess tests that won’t run on iOS.

The AuditPIDFromMachMessageTrailer function from mach_message.h is
excluded on iOS because it relies on <bsm/libbsm.h>, which is broken on
iOS: it depends on <bsm/audit_record.h>, which is missing from the SDK.
Additionally, the BSM function that Crashpad uses, audit_token_to_au32,
is marked as unavailable on iOS. Crashpad uses it on macOS to
authenticate Mach messages sent by other processes, but this is moot on
iOS.

Bug: crashpad:31
Change-Id: I5ebc4b80543989b9cd0b85b82eb4b3ff98c44e6c
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2155086
Reviewed-by: Justin Cohen <justincohen@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Mark Mentovai 2020-04-17 17:45:18 -04:00 committed by Commit Bot
parent 8dbbaff2e1
commit 4cb79941fc
4 changed files with 116 additions and 103 deletions

View File

@ -254,8 +254,16 @@ static_library("util") {
sources += [
"mac/xattr.cc",
"mac/xattr.h",
"mach/exception_behaviors.cc",
"mach/exception_behaviors.h",
"mach/exception_ports.cc",
"mach/exception_ports.h",
"mach/mach_extensions.cc",
"mach/mach_extensions.h",
"mach/mach_message.cc",
"mach/mach_message.h",
"mach/mach_message_server.cc",
"mach/mach_message_server.h",
"misc/clock_mac.cc",
"misc/paths_mac.cc",
"synchronization/semaphore_mac.cc",
@ -284,16 +292,8 @@ static_library("util") {
"mach/exc_client_variants.h",
"mach/exc_server_variants.cc",
"mach/exc_server_variants.h",
"mach/exception_behaviors.cc",
"mach/exception_behaviors.h",
"mach/exception_ports.cc",
"mach/exception_ports.h",
"mach/exception_types.cc",
"mach/exception_types.h",
"mach/mach_message.cc",
"mach/mach_message.h",
"mach/mach_message_server.cc",
"mach/mach_message_server.h",
"mach/notify_server.cc",
"mach/notify_server.h",
"mach/scoped_task_suspend.cc",
@ -518,9 +518,7 @@ static_library("util") {
if (crashpad_is_mac || crashpad_is_ios) {
include_dirs += [ "$root_build_dir/gen" ]
deps += [
":mig_output",
]
deps += [ ":mig_output" ]
}
if (crashpad_is_mac) {
@ -530,9 +528,7 @@ static_library("util") {
"Foundation.framework",
"IOKit.framework",
]
deps += [
"../third_party/apple_cf:apple_cf",
]
deps += [ "../third_party/apple_cf:apple_cf" ]
}
if (crashpad_is_win) {
@ -674,7 +670,9 @@ source_set("util_test") {
if (crashpad_is_mac || crashpad_is_ios) {
sources += [
"mac/xattr_test.cc",
"mach/exception_behaviors_test.cc",
"mach/mach_extensions_test.cc",
"mach/mach_message_test.cc",
]
}
@ -689,11 +687,9 @@ source_set("util_test") {
"mach/composite_mach_message_server_test.cc",
"mach/exc_client_variants_test.cc",
"mach/exc_server_variants_test.cc",
"mach/exception_behaviors_test.cc",
"mach/exception_ports_test.cc",
"mach/exception_types_test.cc",
"mach/mach_message_server_test.cc",
"mach/mach_message_test.cc",
"mach/notify_server_test.cc",
"mach/scoped_task_suspend_test.cc",
"mach/symbolic_constants_mach_test.cc",

View File

@ -15,7 +15,6 @@
#include "util/mach/mach_message.h"
#include <AvailabilityMacros.h>
#include <bsm/libbsm.h>
#include <limits>
@ -24,6 +23,10 @@
#include "util/misc/clock.h"
#include "util/misc/implicit_cast.h"
#if !defined(OS_IOS)
#include <bsm/libbsm.h>
#endif // !OS_IOS
namespace crashpad {
namespace {
@ -217,38 +220,6 @@ const mach_msg_trailer_t* MachMessageTrailerFromHeader(
return reinterpret_cast<const mach_msg_trailer_t*>(trailer_address);
}
pid_t AuditPIDFromMachMessageTrailer(const mach_msg_trailer_t* trailer) {
if (trailer->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0) {
LOG(ERROR) << "unexpected msgh_trailer_type " << trailer->msgh_trailer_type;
return -1;
}
if (trailer->msgh_trailer_size <
REQUESTED_TRAILER_SIZE(kMachMessageReceiveAuditTrailer)) {
LOG(ERROR) << "small msgh_trailer_size " << trailer->msgh_trailer_size;
return -1;
}
const mach_msg_audit_trailer_t* audit_trailer =
reinterpret_cast<const mach_msg_audit_trailer_t*>(trailer);
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
pid_t audit_pid;
audit_token_to_au32(audit_trailer->msgh_audit,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&audit_pid,
nullptr,
nullptr);
#else
pid_t audit_pid = audit_token_to_pid(audit_trailer->msgh_audit);
#endif
return audit_pid;
}
bool MachMessageDestroyReceivedPort(mach_port_t port,
mach_msg_type_name_t port_right_type) {
// This implements a subset of 10.10.5
@ -282,4 +253,40 @@ bool MachMessageDestroyReceivedPort(mach_port_t port,
}
}
#if !defined(OS_IOS)
pid_t AuditPIDFromMachMessageTrailer(const mach_msg_trailer_t* trailer) {
if (trailer->msgh_trailer_type != MACH_MSG_TRAILER_FORMAT_0) {
LOG(ERROR) << "unexpected msgh_trailer_type " << trailer->msgh_trailer_type;
return -1;
}
if (trailer->msgh_trailer_size <
REQUESTED_TRAILER_SIZE(kMachMessageReceiveAuditTrailer)) {
LOG(ERROR) << "small msgh_trailer_size " << trailer->msgh_trailer_size;
return -1;
}
const mach_msg_audit_trailer_t* audit_trailer =
reinterpret_cast<const mach_msg_audit_trailer_t*>(trailer);
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
pid_t audit_pid;
audit_token_to_au32(audit_trailer->msgh_audit,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr,
&audit_pid,
nullptr,
nullptr);
#else
pid_t audit_pid = audit_token_to_pid(audit_trailer->msgh_audit);
#endif
return audit_pid;
}
#endif // !OS_IOS
} // namespace crashpad

View File

@ -19,6 +19,8 @@
#include <stdint.h>
#include <sys/types.h>
#include "build/build_config.h"
namespace crashpad {
//! \brief A Mach message option specifying that an audit trailer should be
@ -166,6 +168,23 @@ void SetMIGReplyError(mach_msg_header_t* out_header, kern_return_t error);
const mach_msg_trailer_t* MachMessageTrailerFromHeader(
const mach_msg_header_t* header);
//! \brief Destroys or deallocates a Mach port received in a Mach message.
//!
//! This function disposes of port rights received in a Mach message. Receive
//! rights will be destroyed with `mach_port_mod_refs()`. Send and send-once
//! rights will be deallocated with `mach_port_deallocate()`.
//!
//! \param[in] port The port to destroy or deallocate.
//! \param[in] port_right_type The right type held for \a port:
//! `MACH_MSG_TYPE_PORT_RECEIVE`, `MACH_MSG_TYPE_PORT_SEND`, or
//! `MACH_MSG_TYPE_PORT_SEND_ONCE`.
//!
//! \return `true` on success, or `false` on failure with a message logged.
bool MachMessageDestroyReceivedPort(mach_port_t port,
mach_msg_type_name_t port_right_type);
#if !defined(OS_IOS) || DOXYGEN
//! \brief Returns the process ID of a Mach messages sender from its audit
//! trailer.
//!
@ -182,20 +201,7 @@ const mach_msg_trailer_t* MachMessageTrailerFromHeader(
//! audit information.
pid_t AuditPIDFromMachMessageTrailer(const mach_msg_trailer_t* trailer);
//! \brief Destroys or deallocates a Mach port received in a Mach message.
//!
//! This function disposes of port rights received in a Mach message. Receive
//! rights will be destroyed with `mach_port_mod_refs()`. Send and send-once
//! rights will be deallocated with `mach_port_deallocate()`.
//!
//! \param[in] port The port to destroy or deallocate.
//! \param[in] port_right_type The right type held for \a port:
//! `MACH_MSG_TYPE_PORT_RECEIVE`, `MACH_MSG_TYPE_PORT_SEND`, or
//! `MACH_MSG_TYPE_PORT_SEND_ONCE`.
//!
//! \return `true` on success, or `false` on failure with a message logged.
bool MachMessageDestroyReceivedPort(mach_port_t port,
mach_msg_type_name_t port_right_type);
#endif // !OS_IOS
} // namespace crashpad

View File

@ -109,46 +109,6 @@ TEST(MachMessage, MachMessageTrailerFromHeader) {
EXPECT_EQ(MachMessageTrailerFromHeader(&test.receive), &test.receive.trailer);
}
TEST(MachMessage, AuditPIDFromMachMessageTrailer) {
base::mac::ScopedMachReceiveRight port(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
ASSERT_NE(port, kMachPortNull);
mach_msg_empty_send_t send = {};
send.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND_ONCE, 0);
send.header.msgh_size = sizeof(send);
send.header.msgh_remote_port = port.get();
mach_msg_return_t mr =
MachMessageWithDeadline(&send.header,
MACH_SEND_MSG,
0,
MACH_PORT_NULL,
kMachMessageDeadlineNonblocking,
MACH_PORT_NULL,
false);
ASSERT_EQ(mr, MACH_MSG_SUCCESS)
<< MachErrorMessage(mr, "MachMessageWithDeadline send");
struct EmptyReceiveMessageWithAuditTrailer : public mach_msg_empty_send_t {
union {
mach_msg_trailer_t trailer;
mach_msg_audit_trailer_t audit_trailer;
};
};
EmptyReceiveMessageWithAuditTrailer receive;
mr = MachMessageWithDeadline(&receive.header,
MACH_RCV_MSG | kMachMessageReceiveAuditTrailer,
sizeof(receive),
port.get(),
kMachMessageDeadlineNonblocking,
MACH_PORT_NULL,
false);
ASSERT_EQ(mr, MACH_MSG_SUCCESS)
<< MachErrorMessage(mr, "MachMessageWithDeadline receive");
EXPECT_EQ(AuditPIDFromMachMessageTrailer(&receive.trailer), getpid());
}
TEST(MachMessage, MachMessageDestroyReceivedPort) {
mach_port_t port = NewMachPort(MACH_PORT_RIGHT_RECEIVE);
ASSERT_NE(port, kMachPortNull);
@ -198,6 +158,50 @@ TEST(MachMessage, MachMessageDestroyReceivedPort) {
EXPECT_TRUE(MachMessageDestroyReceivedPort(port, MACH_MSG_TYPE_PORT_SEND));
}
#if !defined(OS_IOS)
TEST(MachMessage, AuditPIDFromMachMessageTrailer) {
base::mac::ScopedMachReceiveRight port(NewMachPort(MACH_PORT_RIGHT_RECEIVE));
ASSERT_NE(port, kMachPortNull);
mach_msg_empty_send_t send = {};
send.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND_ONCE, 0);
send.header.msgh_size = sizeof(send);
send.header.msgh_remote_port = port.get();
mach_msg_return_t mr =
MachMessageWithDeadline(&send.header,
MACH_SEND_MSG,
0,
MACH_PORT_NULL,
kMachMessageDeadlineNonblocking,
MACH_PORT_NULL,
false);
ASSERT_EQ(mr, MACH_MSG_SUCCESS)
<< MachErrorMessage(mr, "MachMessageWithDeadline send");
struct EmptyReceiveMessageWithAuditTrailer : public mach_msg_empty_send_t {
union {
mach_msg_trailer_t trailer;
mach_msg_audit_trailer_t audit_trailer;
};
};
EmptyReceiveMessageWithAuditTrailer receive;
mr = MachMessageWithDeadline(&receive.header,
MACH_RCV_MSG | kMachMessageReceiveAuditTrailer,
sizeof(receive),
port.get(),
kMachMessageDeadlineNonblocking,
MACH_PORT_NULL,
false);
ASSERT_EQ(mr, MACH_MSG_SUCCESS)
<< MachErrorMessage(mr, "MachMessageWithDeadline receive");
EXPECT_EQ(AuditPIDFromMachMessageTrailer(&receive.trailer), getpid());
}
#endif // !OS_IOS
} // namespace
} // namespace test
} // namespace crashpad