Pass Mach message trailers to server handler functions.

TEST=util_test ChildPortServer.*:ExcServerVariants.*:MachMessageUtil.*
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/755313004
This commit is contained in:
Mark Mentovai 2014-12-01 16:06:56 -05:00
Родитель de5a6cdd6f
Коммит 0437bc53b6
17 изменённых файлов: 206 добавлений и 46 удалений

Просмотреть файл

@ -89,6 +89,7 @@ class TestSimulateCrashMac final : public MachMultiprocess,
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_complex_request) override {
*destroy_complex_request = true;

Просмотреть файл

@ -81,6 +81,7 @@ class TestMachOImageAnnotationsReader final : public MachMultiprocess,
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_complex_request) override {
*destroy_complex_request = true;

Просмотреть файл

@ -70,6 +70,7 @@ class ExceptionServer : public UniversalMachExcServer {
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_complex_request) override {
*destroy_complex_request = true;
++*exceptions_handled_;

Просмотреть файл

@ -247,6 +247,7 @@ kern_return_t ChildPortHandshake::HandleChildPortCheckIn(
const child_port_token_t token,
mach_port_t port,
mach_msg_type_name_t right_type,
const mach_msg_trailer_t* trailer,
bool* destroy_complex_request) {
DCHECK_EQ(child_port_, kMachPortNull);

Просмотреть файл

@ -136,6 +136,7 @@ class ChildPortHandshake : public ChildPortServer::Interface {
child_port_token_t token,
mach_port_t port,
mach_msg_type_name_t right_type,
const mach_msg_trailer_t* trailer,
bool* destroy_complex_request) override;
//! \brief Runs the client.

Просмотреть файл

@ -72,6 +72,9 @@ bool ChildPortServer::MachMessageServerFunction(
bool* destroy_complex_request) {
PrepareMIGReplyFromRequest(in_header, out_header);
const mach_msg_trailer_t* in_trailer =
MachMessageTrailerFromHeader(in_header);
switch (in_header->msgh_id) {
case kMachMessageIDChildPortCheckIn: {
// child_port_check_in(), handle_child_port_check_in().
@ -90,6 +93,7 @@ bool ChildPortServer::MachMessageServerFunction(
in_request->token,
in_request->port.name,
in_request->port.disposition,
in_trailer,
destroy_complex_request);
return true;
}

Просмотреть файл

@ -35,6 +35,7 @@ class ChildPortServer : public MachMessageServer::Interface {
//! This behaves equivalently to a `handle_child_port_check_in()` function
//! used with `child_port_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.
@ -43,6 +44,7 @@ class ChildPortServer : public MachMessageServer::Interface {
const child_port_token_t token,
mach_port_t port,
mach_msg_type_name_t right_type,
const mach_msg_trailer_t* trailer,
bool* destroy_complex_request) = 0;
protected:

Просмотреть файл

@ -48,7 +48,7 @@ struct __attribute__((packed, aligned(4))) ChildPortCheckInRequest {
memset(this, 0xa5, sizeof(*this));
Head.msgh_bits =
MACH_MSGH_BITS(0, MACH_MSG_TYPE_PORT_SEND) | MACH_MSGH_BITS_COMPLEX;
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = MACH_PORT_NULL;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 10011;
@ -65,6 +65,7 @@ struct __attribute__((packed, aligned(4))) ChildPortCheckInRequest {
mach_msg_port_descriptor_t port;
NDR_record_t NDR;
child_port_token_t token;
mach_msg_trailer_t trailer;
};
struct MIGReply : public mig_reply_error_t {
@ -87,11 +88,12 @@ struct MIGReply : public mig_reply_error_t {
class MockChildPortServerInterface : public ChildPortServer::Interface {
public:
MOCK_METHOD5(HandleChildPortCheckIn,
MOCK_METHOD6(HandleChildPortCheckIn,
kern_return_t(child_port_server_t server,
const child_port_token_t token,
mach_port_t port,
mach_msg_type_name_t right_type,
const mach_msg_trailer_t* trailer,
bool* destroy_complex_request));
};
@ -100,7 +102,7 @@ TEST(ChildPortServer, MockChildPortCheckIn) {
ChildPortServer server(&server_interface);
ChildPortCheckInRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
MIGReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -110,6 +112,7 @@ TEST(ChildPortServer, MockChildPortCheckIn) {
kCheckInToken,
kCheckInPort,
kCheckInPortRightType,
Eq(&request.trailer),
Pointee(Eq(false))))
.WillOnce(Return(MIG_NO_REPLY))
.RetiresOnSaturation();

Просмотреть файл

@ -60,6 +60,7 @@ class TestExcClientVariants : public UniversalMachExcServer,
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_complex_request) override {
*destroy_complex_request = true;

Просмотреть файл

@ -196,6 +196,9 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header,
bool* destroy_complex_request) {
PrepareMIGReplyFromRequest(in_header, out_header);
const mach_msg_trailer_t* in_trailer =
MachMessageTrailerFromHeader(in_header);
switch (in_header->msgh_id) {
case kMachMessageIDExceptionRaise: {
// exception_raise(), catch_exception_raise().
@ -216,6 +219,7 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header,
in_request->exception,
in_request->code,
in_request->codeCnt,
in_trailer,
destroy_complex_request);
if (out_reply->RetCode != KERN_SUCCESS) {
return true;
@ -253,7 +257,8 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header,
in_request_1->old_state,
in_request_1->old_stateCnt,
out_reply->new_state,
&out_reply->new_stateCnt);
&out_reply->new_stateCnt,
in_trailer);
if (out_reply->RetCode != KERN_SUCCESS) {
return true;
}
@ -296,6 +301,7 @@ bool ExcServer::MachMessageServerFunction(const mach_msg_header_t* in_header,
in_request_1->old_stateCnt,
out_reply->new_state,
&out_reply->new_stateCnt,
in_trailer,
destroy_complex_request);
if (out_reply->RetCode != KERN_SUCCESS) {
return true;
@ -331,6 +337,9 @@ bool MachExcServer::MachMessageServerFunction(
bool* destroy_complex_request) {
PrepareMIGReplyFromRequest(in_header, out_header);
const mach_msg_trailer_t* in_trailer =
MachMessageTrailerFromHeader(in_header);
switch (in_header->msgh_id) {
case kMachMessageIDMachExceptionRaise: {
// mach_exception_raise(), catch_mach_exception_raise().
@ -351,6 +360,7 @@ bool MachExcServer::MachMessageServerFunction(
in_request->exception,
in_request->code,
in_request->codeCnt,
in_trailer,
destroy_complex_request);
if (out_reply->RetCode != KERN_SUCCESS) {
return true;
@ -388,7 +398,8 @@ bool MachExcServer::MachMessageServerFunction(
in_request_1->old_state,
in_request_1->old_stateCnt,
out_reply->new_state,
&out_reply->new_stateCnt);
&out_reply->new_stateCnt,
in_trailer);
if (out_reply->RetCode != KERN_SUCCESS) {
return true;
}
@ -431,6 +442,7 @@ bool MachExcServer::MachMessageServerFunction(
in_request_1->old_stateCnt,
out_reply->new_state,
&out_reply->new_stateCnt,
in_trailer,
destroy_complex_request);
if (out_reply->RetCode != KERN_SUCCESS) {
return true;
@ -469,6 +481,7 @@ kern_return_t SimplifiedExcServer::CatchExceptionRaise(
exception_type_t exception,
const exception_data_type_t* code,
mach_msg_type_number_t code_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) {
thread_state_flavor_t flavor = THREAD_STATE_NONE;
mach_msg_type_number_t new_state_count = 0;
@ -484,6 +497,7 @@ kern_return_t SimplifiedExcServer::CatchExceptionRaise(
0,
nullptr,
&new_state_count,
trailer,
destroy_request);
}
@ -496,7 +510,8 @@ kern_return_t SimplifiedExcServer::CatchExceptionRaiseState(
const natural_t* old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count) {
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer) {
bool destroy_complex_request = false;
return interface_->CatchException(EXCEPTION_STATE,
exception_port,
@ -510,6 +525,7 @@ kern_return_t SimplifiedExcServer::CatchExceptionRaiseState(
old_state_count,
new_state,
new_state_count,
trailer,
&destroy_complex_request);
}
@ -525,6 +541,7 @@ kern_return_t SimplifiedExcServer::CatchExceptionRaiseStateIdentity(
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) {
return interface_->CatchException(EXCEPTION_STATE_IDENTITY,
exception_port,
@ -538,6 +555,7 @@ kern_return_t SimplifiedExcServer::CatchExceptionRaiseStateIdentity(
old_state_count,
new_state,
new_state_count,
trailer,
destroy_request);
}
@ -555,6 +573,7 @@ kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaise(
exception_type_t exception,
const mach_exception_data_type_t* code,
mach_msg_type_number_t code_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) {
thread_state_flavor_t flavor = THREAD_STATE_NONE;
mach_msg_type_number_t new_state_count = 0;
@ -571,6 +590,7 @@ kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaise(
0,
nullptr,
&new_state_count,
trailer,
destroy_request);
}
@ -583,7 +603,8 @@ kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseState(
const natural_t* old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count) {
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer) {
bool destroy_complex_request = false;
return interface_->CatchMachException(EXCEPTION_STATE | MACH_EXCEPTION_CODES,
exception_port,
@ -597,6 +618,7 @@ kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseState(
old_state_count,
new_state,
new_state_count,
trailer,
&destroy_complex_request);
}
@ -612,6 +634,7 @@ kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseStateIdentity(
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) {
return interface_->CatchMachException(
EXCEPTION_STATE_IDENTITY | MACH_EXCEPTION_CODES,
@ -626,6 +649,7 @@ kern_return_t SimplifiedMachExcServer::CatchMachExceptionRaiseStateIdentity(
old_state_count,
new_state,
new_state_count,
trailer,
destroy_request);
}
@ -686,6 +710,7 @@ kern_return_t UniversalMachExcServer::CatchException(
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_complex_request) {
std::vector<mach_exception_data_type_t> mach_codes;
mach_codes.reserve(code_count);
@ -705,6 +730,7 @@ kern_return_t UniversalMachExcServer::CatchException(
old_state_count,
new_state,
new_state_count,
trailer,
destroy_complex_request);
}

Просмотреть файл

@ -42,6 +42,7 @@ class ExcServer : public MachMessageServer::Interface {
//! This behaves equivalently to a `catch_exception_raise()` function used
//! with `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.
@ -52,6 +53,7 @@ class ExcServer : public MachMessageServer::Interface {
exception_type_t exception,
const exception_data_type_t* code,
mach_msg_type_number_t code_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) = 0;
//! \brief Handles exceptions raised by `exception_raise_state()`.
@ -63,6 +65,8 @@ class ExcServer : public MachMessageServer::Interface {
//! CatchExceptionRaise() and CatchExceptionRaiseStateIdentity(), the
//! request message is not complex (it does not carry the \a thread or \a
//! task port rights) and thus there is nothing to destroy.
//!
//! \param[in] trailer The trailer received with the request message.
virtual kern_return_t CatchExceptionRaiseState(
exception_handler_t exception_port,
exception_type_t exception,
@ -72,13 +76,15 @@ class ExcServer : public MachMessageServer::Interface {
const natural_t* old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count) = 0;
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer) = 0;
//! \brief Handles exceptions raised by `exception_raise_state_identity()`.
//!
//! This behaves equivalently to a `catch_exception_raise_state_identity()`
//! function used with `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.
@ -94,6 +100,7 @@ class ExcServer : public MachMessageServer::Interface {
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;
protected:
@ -132,6 +139,7 @@ class MachExcServer : public MachMessageServer::Interface {
//! This behaves equivalently to a `catch_mach_exception_raise()` 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.
@ -142,6 +150,7 @@ class MachExcServer : public MachMessageServer::Interface {
exception_type_t exception,
const mach_exception_data_type_t* code,
mach_msg_type_number_t code_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) = 0;
//! \brief Handles exceptions raised by `mach_exception_raise_state()`.
@ -153,6 +162,8 @@ class MachExcServer : public MachMessageServer::Interface {
//! CatchMachExceptionRaise() and CatchMachExceptionRaiseStateIdentity(),
//! the request message is not complex (it does not carry the \a thread or
//! \a task port rights) and thus there is nothing to destroy.
//!
//! \param[in] trailer The trailer received with the request message.
virtual kern_return_t CatchMachExceptionRaiseState(
exception_handler_t exception_port,
exception_type_t exception,
@ -162,7 +173,8 @@ class MachExcServer : public MachMessageServer::Interface {
const natural_t* old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count) = 0;
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer) = 0;
//! \brief Handles exceptions raised by
//! `mach_exception_raise_state_identity()`.
@ -171,6 +183,7 @@ class MachExcServer : public MachMessageServer::Interface {
//! `catch_mach_exception_raise_state_identity()` 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.
@ -186,6 +199,7 @@ class MachExcServer : public MachMessageServer::Interface {
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;
protected:
@ -248,6 +262,7 @@ class SimplifiedExcServer : public ExcServer, public ExcServer::Interface {
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_complex_request) = 0;
protected:
@ -267,6 +282,7 @@ class SimplifiedExcServer : public ExcServer, public ExcServer::Interface {
exception_type_t exception,
const exception_data_type_t* code,
mach_msg_type_number_t code_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) override;
kern_return_t CatchExceptionRaiseState(
exception_handler_t exception_port,
@ -277,7 +293,8 @@ class SimplifiedExcServer : public ExcServer, public ExcServer::Interface {
const natural_t* old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count) override;
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer) override;
kern_return_t CatchExceptionRaiseStateIdentity(
exception_handler_t exception_port,
thread_t thread,
@ -290,6 +307,7 @@ class SimplifiedExcServer : public ExcServer, public ExcServer::Interface {
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) override;
private:
@ -344,6 +362,7 @@ class SimplifiedMachExcServer : public MachExcServer,
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_complex_request) = 0;
protected:
@ -363,6 +382,7 @@ class SimplifiedMachExcServer : public MachExcServer,
exception_type_t exception,
const mach_exception_data_type_t* code,
mach_msg_type_number_t code_count,
const mach_msg_trailer_t* trailer,
bool* destroy_request) override;
kern_return_t CatchMachExceptionRaiseState(
exception_handler_t exception_port,
@ -373,7 +393,8 @@ class SimplifiedMachExcServer : public MachExcServer,
const natural_t* old_state,
mach_msg_type_number_t old_state_count,
thread_state_t new_state,
mach_msg_type_number_t* new_state_count) override;
mach_msg_type_number_t* new_state_count,
const mach_msg_trailer_t* trailer) override;
kern_return_t CatchMachExceptionRaiseStateIdentity(
exception_handler_t exception_port,
thread_t thread,
@ -386,6 +407,7 @@ class SimplifiedMachExcServer : public MachExcServer,
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) override;
private:
@ -440,6 +462,7 @@ class UniversalMachExcServer
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_complex_request) override;
private:

Просмотреть файл

@ -23,6 +23,7 @@
#include "gtest/gtest.h"
#include "util/mach/exception_behaviors.h"
#include "util/mach/mach_extensions.h"
#include "util/mach/mach_message_util.h"
#include "util/test/mac/mach_errors.h"
#include "util/test/mac/mach_multiprocess.h"
@ -82,7 +83,7 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseRequest {
Head.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, MACH_MSG_TYPE_PORT_SEND) |
MACH_MSGH_BITS_COMPLEX;
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = kClientRemotePort;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 2401;
@ -104,6 +105,7 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseRequest {
exception_type_t exception;
mach_msg_type_number_t codeCnt;
integer_t code[2];
mach_msg_trailer_t trailer;
};
struct __attribute__((packed, aligned(4))) ExceptionRaiseReply {
@ -149,7 +151,7 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseStateRequest {
memset(this, 0xa5, sizeof(*this));
Head.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, MACH_MSG_TYPE_PORT_SEND);
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = kClientRemotePort;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 2402;
@ -166,6 +168,12 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseStateRequest {
Head.msgh_size += sizeof(old_state[0]) * old_stateCnt - sizeof(old_state);
}
// Because the message size has been adjusted, the trailer may not appear in
// its home member variable. This computes the actual address of the trailer.
const mach_msg_trailer_t* Trailer() const {
return MachMessageTrailerFromHeader(&Head);
}
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
@ -174,6 +182,7 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseStateRequest {
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[THREAD_STATE_MAX];
mach_msg_trailer_t trailer;
};
struct __attribute__((packed, aligned(4))) ExceptionRaiseStateReply {
@ -232,7 +241,7 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseStateIdentityRequest {
Head.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, MACH_MSG_TYPE_PORT_SEND) |
MACH_MSGH_BITS_COMPLEX;
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = kClientRemotePort;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 2403;
@ -252,6 +261,12 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseStateIdentityRequest {
Head.msgh_size += sizeof(old_state[0]) * old_stateCnt - sizeof(old_state);
}
// Because the message size has been adjusted, the trailer may not appear in
// its home member variable. This computes the actual address of the trailer.
const mach_msg_trailer_t* Trailer() const {
return MachMessageTrailerFromHeader(&Head);
}
mach_msg_header_t Head;
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
@ -263,6 +278,7 @@ struct __attribute__((packed, aligned(4))) ExceptionRaiseStateIdentityRequest {
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[THREAD_STATE_MAX];
mach_msg_trailer_t trailer;
};
// The reply messages for exception_raise_state and
@ -275,7 +291,7 @@ struct __attribute__((packed, aligned(4))) MachExceptionRaiseRequest {
Head.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, MACH_MSG_TYPE_PORT_SEND) |
MACH_MSGH_BITS_COMPLEX;
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = kClientRemotePort;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 2405;
@ -297,6 +313,7 @@ struct __attribute__((packed, aligned(4))) MachExceptionRaiseRequest {
exception_type_t exception;
mach_msg_type_number_t codeCnt;
int64_t code[2];
mach_msg_trailer_t trailer;
};
// The reply messages for exception_raise and mach_exception_raise are
@ -308,7 +325,7 @@ struct __attribute__((packed, aligned(4))) MachExceptionRaiseStateRequest {
memset(this, 0xa5, sizeof(*this));
Head.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, MACH_MSG_TYPE_PORT_SEND);
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = kClientRemotePort;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 2406;
@ -325,6 +342,12 @@ struct __attribute__((packed, aligned(4))) MachExceptionRaiseStateRequest {
Head.msgh_size += sizeof(old_state[0]) * old_stateCnt - sizeof(old_state);
}
// Because the message size has been adjusted, the trailer may not appear in
// its home member variable. This computes the actual address of the trailer.
const mach_msg_trailer_t* Trailer() const {
return MachMessageTrailerFromHeader(&Head);
}
mach_msg_header_t Head;
NDR_record_t NDR;
exception_type_t exception;
@ -333,6 +356,7 @@ struct __attribute__((packed, aligned(4))) MachExceptionRaiseStateRequest {
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[THREAD_STATE_MAX];
mach_msg_trailer_t trailer;
};
// The reply messages for exception_raise_state and mach_exception_raise_state
@ -346,7 +370,7 @@ struct __attribute__((packed,
Head.msgh_bits =
MACH_MSGH_BITS(MACH_MSG_TYPE_PORT_SEND_ONCE, MACH_MSG_TYPE_PORT_SEND) |
MACH_MSGH_BITS_COMPLEX;
Head.msgh_size = sizeof(*this);
Head.msgh_size = sizeof(*this) - sizeof(trailer);
Head.msgh_remote_port = kClientRemotePort;
Head.msgh_local_port = kServerLocalPort;
Head.msgh_id = 2407;
@ -366,6 +390,12 @@ struct __attribute__((packed,
Head.msgh_size += sizeof(old_state[0]) * old_stateCnt - sizeof(old_state);
}
// Because the message size has been adjusted, the trailer may not appear in
// its home member variable. This computes the actual address of the trailer.
const mach_msg_trailer_t* Trailer() const {
return MachMessageTrailerFromHeader(&Head);
}
mach_msg_header_t Head;
mach_msg_body_t msgh_body;
mach_msg_port_descriptor_t thread;
@ -377,6 +407,7 @@ struct __attribute__((packed,
int flavor;
mach_msg_type_number_t old_stateCnt;
natural_t old_state[THREAD_STATE_MAX];
mach_msg_trailer_t trailer;
};
// The reply messages for exception_raise_state_identity and
@ -449,6 +480,7 @@ class MockUniversalMachExcServer : public UniversalMachExcServer {
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_complex_request) override {
*destroy_complex_request = true;
const ConstExceptionCodes exception_codes = {code, code_count};
@ -462,19 +494,21 @@ class MockUniversalMachExcServer : public UniversalMachExcServer {
&exception_codes,
flavor,
&old_thread_state,
&new_thread_state);
&new_thread_state,
trailer);
}
MOCK_METHOD9(MockCatchMachException,
kern_return_t(exception_behavior_t behavior,
exception_handler_t exception_port,
thread_t thread,
task_t task,
exception_type_t exception,
const ConstExceptionCodes* exception_codes,
thread_state_flavor_t* flavor,
const ConstThreadState* old_thread_state,
ThreadState* new_thread_state));
MOCK_METHOD10(MockCatchMachException,
kern_return_t(exception_behavior_t behavior,
exception_handler_t exception_port,
thread_t thread,
task_t task,
exception_type_t exception,
const ConstExceptionCodes* exception_codes,
thread_state_flavor_t* flavor,
const ConstThreadState* old_thread_state,
ThreadState* new_thread_state,
const mach_msg_trailer_t* trailer));
};
// Matcher for ConstExceptionCodes, testing that it carries 2 codes matching
@ -548,7 +582,7 @@ TEST(ExcServerVariants, MockExceptionRaise) {
MockUniversalMachExcServer server;
ExceptionRaiseRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
ExceptionRaiseReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -565,7 +599,8 @@ TEST(ExcServerVariants, MockExceptionRaise) {
kTestExceptonCodes[1]),
Pointee(Eq(THREAD_STATE_NONE)),
IsThreadStateCount(0u),
IsThreadStateCount(0u)))
IsThreadStateCount(0u),
Eq(&request.trailer)))
.WillOnce(Return(KERN_SUCCESS))
.RetiresOnSaturation();
@ -585,7 +620,7 @@ TEST(ExcServerVariants, MockExceptionRaiseState) {
MockUniversalMachExcServer server;
ExceptionRaiseStateRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
ExceptionRaiseStateReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -603,7 +638,8 @@ TEST(ExcServerVariants, MockExceptionRaiseState) {
AreExceptionCodes(kTestExceptonCodes[0], kTestExceptonCodes[1]),
Pointee(Eq(kThreadStateFlavor)),
IsThreadStateCount(kThreadStateFlavorCount),
IsThreadStateCount(arraysize(reply.new_state))))
IsThreadStateCount(arraysize(reply.new_state)),
Eq(request.Trailer())))
.WillOnce(Return(KERN_SUCCESS))
.RetiresOnSaturation();
@ -626,7 +662,7 @@ TEST(ExcServerVariants, MockExceptionRaiseStateIdentity) {
MockUniversalMachExcServer server;
ExceptionRaiseStateIdentityRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
ExceptionRaiseStateIdentityReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -644,7 +680,8 @@ TEST(ExcServerVariants, MockExceptionRaiseStateIdentity) {
AreExceptionCodes(kTestExceptonCodes[0], kTestExceptonCodes[1]),
Pointee(Eq(kThreadStateFlavor)),
IsThreadStateCount(kThreadStateFlavorCount),
IsThreadStateCount(arraysize(reply.new_state))))
IsThreadStateCount(arraysize(reply.new_state)),
Eq(request.Trailer())))
.WillOnce(Return(KERN_SUCCESS))
.RetiresOnSaturation();
@ -664,7 +701,7 @@ TEST(ExcServerVariants, MockMachExceptionRaise) {
MockUniversalMachExcServer server;
MachExceptionRaiseRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
MachExceptionRaiseReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -683,7 +720,8 @@ TEST(ExcServerVariants, MockMachExceptionRaise) {
kTestMachExceptionCodes[1]),
Pointee(Eq(THREAD_STATE_NONE)),
IsThreadStateCount(0u),
IsThreadStateCount(0u)))
IsThreadStateCount(0u),
Eq(&request.trailer)))
.WillOnce(Return(KERN_SUCCESS))
.RetiresOnSaturation();
@ -703,7 +741,7 @@ TEST(ExcServerVariants, MockMachExceptionRaiseState) {
MockUniversalMachExcServer server;
MachExceptionRaiseStateRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
MachExceptionRaiseStateReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -722,7 +760,8 @@ TEST(ExcServerVariants, MockMachExceptionRaiseState) {
kTestMachExceptionCodes[1]),
Pointee(Eq(kThreadStateFlavor)),
IsThreadStateCount(kThreadStateFlavorCount),
IsThreadStateCount(arraysize(reply.new_state))))
IsThreadStateCount(arraysize(reply.new_state)),
Eq(request.Trailer())))
.WillOnce(Return(KERN_SUCCESS))
.RetiresOnSaturation();
@ -745,7 +784,7 @@ TEST(ExcServerVariants, MockMachExceptionRaiseStateIdentity) {
MockUniversalMachExcServer server;
MachExceptionRaiseStateIdentityRequest request;
EXPECT_LE(sizeof(request), server.MachMessageServerRequestSize());
EXPECT_LE(request.Head.msgh_size, server.MachMessageServerRequestSize());
MachExceptionRaiseStateIdentityReply reply;
EXPECT_LE(sizeof(reply), server.MachMessageServerReplySize());
@ -764,7 +803,8 @@ TEST(ExcServerVariants, MockMachExceptionRaiseStateIdentity) {
kTestMachExceptionCodes[1]),
Pointee(Eq(kThreadStateFlavor)),
IsThreadStateCount(kThreadStateFlavorCount),
IsThreadStateCount(arraysize(reply.new_state))))
IsThreadStateCount(arraysize(reply.new_state)),
Eq(request.Trailer())))
.WillOnce(Return(KERN_SUCCESS))
.RetiresOnSaturation();
@ -871,6 +911,7 @@ class TestExcServerVariants : public UniversalMachExcServer,
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_complex_request) override {
*destroy_complex_request = true;
@ -917,6 +958,11 @@ class TestExcServerVariants : public UniversalMachExcServer,
EXPECT_EQ(nullptr, new_state);
}
EXPECT_EQ(implicit_cast<mach_msg_trailer_type_t>(MACH_MSG_TRAILER_FORMAT_0),
trailer->msgh_trailer_type);
EXPECT_EQ(REQUESTED_TRAILER_SIZE(kMachMessageOptions),
trailer->msgh_trailer_size);
return ExcServerSuccessfulReturnValue(behavior, false);
}
@ -927,7 +973,7 @@ class TestExcServerVariants : public UniversalMachExcServer,
kern_return_t kr =
MachMessageServer::Run(this,
LocalPort(),
MACH_MSG_OPTION_NONE,
kMachMessageOptions,
MachMessageServer::kOneShot,
MachMessageServer::kBlocking,
MachMessageServer::kReceiveLargeError,
@ -954,6 +1000,9 @@ class TestExcServerVariants : public UniversalMachExcServer,
mach_msg_type_number_t state_count_;
bool handled_;
static const mach_msg_option_t kMachMessageOptions =
MACH_RCV_TRAILER_TYPE(MACH_MSG_TRAILER_FORMAT_0);
DISALLOW_COPY_AND_ASSIGN(TestExcServerVariants);
};

Просмотреть файл

@ -154,6 +154,7 @@ class TestExceptionPorts : public UniversalMachExcServer,
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_complex_request) override {
*destroy_complex_request = true;

Просмотреть файл

@ -111,7 +111,8 @@ mach_msg_return_t MachMessageServer::Run(Interface* interface,
mach_msg_size_t trailer_alloc = REQUESTED_TRAILER_SIZE(options);
mach_msg_size_t max_request_size = interface->MachMessageServerRequestSize();
mach_msg_size_t request_alloc = round_page(max_request_size + trailer_alloc);
mach_msg_size_t request_alloc =
round_page(round_msg(max_request_size) + trailer_alloc);
// mach_msg_server() and mach_msg_server_once() invert this condition, but
// their interpretation is incorrect. When it is desirable to retry a receive
@ -120,9 +121,10 @@ mach_msg_return_t MachMessageServer::Run(Interface* interface,
// the initial receive attempt. On the other hand, when this behavior is not
// requested, there is no reason to attempt receiving messages any larger than
// expected.
mach_msg_size_t request_size = (receive_large == kReceiveLargeResize)
? max_request_size + trailer_alloc
: request_alloc;
mach_msg_size_t request_size =
(receive_large == kReceiveLargeResize)
? round_msg(max_request_size) + trailer_alloc
: request_alloc;
mach_msg_size_t max_reply_size = interface->MachMessageServerReplySize();
@ -186,7 +188,7 @@ mach_msg_return_t MachMessageServer::Run(Interface* interface,
} else if (kr == MACH_RCV_TOO_LARGE &&
receive_large == kReceiveLargeResize) {
this_request_size =
round_page(request_header->msgh_size + trailer_alloc);
round_page(round_msg(request_header->msgh_size) + trailer_alloc);
this_request_alloc = this_request_size;
} else {
return kr;

Просмотреть файл

@ -34,4 +34,11 @@ void SetMIGReplyError(mach_msg_header_t* out_header, kern_return_t error) {
reinterpret_cast<mig_reply_error_t*>(out_header)->RetCode = error;
}
const mach_msg_trailer_t* MachMessageTrailerFromHeader(
const mach_msg_header_t* header) {
vm_address_t header_address = reinterpret_cast<vm_address_t>(header);
vm_address_t trailer_address = header_address + round_msg(header->msgh_size);
return reinterpret_cast<const mach_msg_trailer_t*>(trailer_address);
}
} // namespace crashpad

Просмотреть файл

@ -48,6 +48,20 @@ void PrepareMIGReplyFromRequest(const mach_msg_header_t* in_header,
//! \sa PrepareMIGReplyFromRequest()
void SetMIGReplyError(mach_msg_header_t* out_header, kern_return_t error);
//! \brief Returns a Mach message trailer for a message that has been received.
//!
//! This function must only be called on Mach messages that have been received
//! via the Mach messaging interface, such as `mach_msg()`. Messages constructed
//! for sending do not contain trailers.
//!
//! \param[in] header A pointer to a received Mach message.
//!
//! \return A pointer to the trailer following the received Mach messages body.
//! The contents of the trailer depend on the options provided to
//! `mach_msg()` or a similar function when the message was received.
const mach_msg_trailer_t* MachMessageTrailerFromHeader(
const mach_msg_header_t* header);
} // namespace crashpad
#endif // CRASHPAD_UTIL_MACH_MACH_MESSAGE_UTIL_H_

Просмотреть файл

@ -63,6 +63,29 @@ TEST(MachMessageUtil, PrepareMIGReplyFromRequest_SetMIGReplyError) {
EXPECT_EQ(MIG_BAD_ID, reply.RetCode);
}
TEST(MachMessageUtil, MachMessageTrailerFromHeader) {
mach_msg_empty_t empty;
empty.send.header.msgh_size = sizeof(mach_msg_empty_send_t);
EXPECT_EQ(&empty.rcv.trailer,
MachMessageTrailerFromHeader(&empty.rcv.header));
struct TestSendMessage : public mach_msg_header_t {
uint8_t data[126];
};
struct TestReceiveMessage : public TestSendMessage {
mach_msg_trailer_t trailer;
};
union TestMessage {
TestSendMessage send;
TestReceiveMessage receive;
};
TestMessage test;
test.send.msgh_size = sizeof(TestSendMessage);
EXPECT_EQ(&test.receive.trailer,
MachMessageTrailerFromHeader(&test.receive));
}
} // namespace
} // namespace test
} // namespace crashpad