1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "sandbox/mac/xpc_message_server.h"
7 #include <bsm/libbsm.h>
11 #include "base/mac/mach_logging.h"
12 #include "base/strings/stringprintf.h"
13 #include "sandbox/mac/xpc.h"
15 #if defined(MAC_OS_X_VERSION_10_7) && \
16 MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
17 // Redeclare methods that only exist on 10.7+ to suppress
18 // -Wpartial-availability warnings.
20 XPC_EXPORT XPC_MALLOC XPC_RETURNS_RETAINED XPC_WARN_RESULT XPC_NONNULL_ALL
22 xpc_dictionary_create_reply(xpc_object_t original
);
28 XPCMessageServer::XPCMessageServer(MessageDemuxer
* demuxer
,
29 mach_port_t server_receive_right
)
31 server_port_(server_receive_right
),
32 reply_message_(NULL
) {
35 XPCMessageServer::~XPCMessageServer() {
38 bool XPCMessageServer::Initialize() {
39 // Allocate a port for use as a new server port if one was not passed to the
41 if (!server_port_
.is_valid()) {
44 if ((kr
= mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE
,
45 &port
)) != KERN_SUCCESS
) {
46 MACH_LOG(ERROR
, kr
) << "Failed to allocate new server port.";
49 server_port_
.reset(port
);
52 std::string label
= base::StringPrintf(
53 "org.chromium.sandbox.XPCMessageServer.%p", demuxer_
);
54 dispatch_source_
.reset(new base::DispatchSourceMach(
55 label
.c_str(), server_port_
.get(), ^{ ReceiveMessage(); }));
56 dispatch_source_
->Resume();
61 pid_t
XPCMessageServer::GetMessageSenderPID(IPCMessage request
) {
63 xpc_dictionary_get_audit_token(request
.xpc
, &token
);
64 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid().
66 audit_token_to_au32(token
,
67 NULL
, NULL
, NULL
, NULL
, NULL
, &sender_pid
, NULL
, NULL
);
71 IPCMessage
XPCMessageServer::CreateReply(IPCMessage request
) {
73 reply_message_
= xpc_dictionary_create_reply(request
.xpc
);
76 reply
.xpc
= reply_message_
;
80 bool XPCMessageServer::SendReply(IPCMessage reply
) {
81 int rv
= xpc_pipe_routine_reply(reply
.xpc
);
83 LOG(ERROR
) << "Failed to xpc_pipe_routine_reply(): " << rv
;
89 void XPCMessageServer::ForwardMessage(IPCMessage request
,
90 mach_port_t destination
) {
91 xpc_pipe_t pipe
= xpc_pipe_create_from_port(destination
, 0);
92 int rv
= xpc_pipe_routine_forward(pipe
, request
.xpc
);
94 LOG(ERROR
) << "Failed to xpc_pipe_routine_forward(): " << rv
;
99 void XPCMessageServer::RejectMessage(IPCMessage request
, int error_code
) {
100 IPCMessage reply
= CreateReply(request
);
101 xpc_dictionary_set_int64(reply
.xpc
, "error", error_code
);
105 mach_port_t
XPCMessageServer::GetServerPort() const {
106 return server_port_
.get();
109 void XPCMessageServer::ReceiveMessage() {
111 int rv
= xpc_pipe_receive(server_port_
, &request
.xpc
);
113 LOG(ERROR
) << "Failed to xpc_pipe_receive(): " << rv
;
117 demuxer_
->DemuxMessage(request
);
119 xpc_release(request
.xpc
);
120 if (reply_message_
) {
121 xpc_release(reply_message_
);
122 reply_message_
= NULL
;
126 } // namespace sandbox