OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "sandbox/mac/xpc_message_server.h" |
| 6 |
| 7 #include <bsm/libbsm.h> |
| 8 |
| 9 #include <string> |
| 10 |
| 11 #include "base/mac/mach_logging.h" |
| 12 #include "base/strings/stringprintf.h" |
| 13 #include "sandbox/mac/dispatch_source_mach.h" |
| 14 #include "sandbox/mac/xpc.h" |
| 15 |
| 16 namespace sandbox { |
| 17 |
| 18 XPCMessageServer::XPCMessageServer(MessageDemuxer* demuxer, |
| 19 mach_port_t server_receive_right) |
| 20 : demuxer_(demuxer), |
| 21 server_port_(server_receive_right), |
| 22 reply_message_(NULL) { |
| 23 } |
| 24 |
| 25 XPCMessageServer::~XPCMessageServer() { |
| 26 } |
| 27 |
| 28 bool XPCMessageServer::Initialize() { |
| 29 // Allocate a port for use as a new server port if one was not passed to the |
| 30 // constructor. |
| 31 if (!server_port_.is_valid()) { |
| 32 mach_port_t port; |
| 33 kern_return_t kr; |
| 34 if ((kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, |
| 35 &port)) != KERN_SUCCESS) { |
| 36 MACH_LOG(ERROR, kr) << "Failed to allocate new server port."; |
| 37 return false; |
| 38 } |
| 39 server_port_.reset(port); |
| 40 } |
| 41 |
| 42 std::string label = base::StringPrintf( |
| 43 "org.chromium.sandbox.XPCMessageServer.%p", demuxer_); |
| 44 dispatch_source_.reset(new DispatchSourceMach( |
| 45 label.c_str(), server_port_.get(), ^{ ReceiveMessage(); })); |
| 46 dispatch_source_->Resume(); |
| 47 |
| 48 return true; |
| 49 } |
| 50 |
| 51 pid_t XPCMessageServer::GetMessageSenderPID(IPCMessage request) { |
| 52 audit_token_t token; |
| 53 xpc_dictionary_get_audit_token(request.xpc, &token); |
| 54 // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). |
| 55 pid_t sender_pid; |
| 56 audit_token_to_au32(token, |
| 57 NULL, NULL, NULL, NULL, NULL, &sender_pid, NULL, NULL); |
| 58 return sender_pid; |
| 59 } |
| 60 |
| 61 IPCMessage XPCMessageServer::CreateReply(IPCMessage request) { |
| 62 if (!reply_message_) |
| 63 reply_message_ = xpc_dictionary_create_reply(request.xpc); |
| 64 |
| 65 IPCMessage reply; |
| 66 reply.xpc = reply_message_; |
| 67 return reply; |
| 68 } |
| 69 |
| 70 bool XPCMessageServer::SendReply(IPCMessage reply) { |
| 71 int rv = xpc_pipe_routine_reply(reply.xpc); |
| 72 if (rv) { |
| 73 LOG(ERROR) << "Failed to xpc_pipe_routine_reply(): " << rv; |
| 74 return false; |
| 75 } |
| 76 return true; |
| 77 } |
| 78 |
| 79 void XPCMessageServer::ForwardMessage(IPCMessage request, |
| 80 mach_port_t destination) { |
| 81 xpc_pipe_t pipe = xpc_pipe_create_from_port(destination, 0); |
| 82 int rv = xpc_pipe_routine_forward(pipe, request.xpc); |
| 83 if (rv) { |
| 84 LOG(ERROR) << "Failed to xpc_pipe_routine_forward(): " << rv; |
| 85 } |
| 86 xpc_release(pipe); |
| 87 } |
| 88 |
| 89 void XPCMessageServer::RejectMessage(IPCMessage request, int error_code) { |
| 90 IPCMessage reply = CreateReply(request); |
| 91 xpc_dictionary_set_int64(reply.xpc, "error", error_code); |
| 92 SendReply(reply); |
| 93 } |
| 94 |
| 95 mach_port_t XPCMessageServer::GetServerPort() const { |
| 96 return server_port_.get(); |
| 97 } |
| 98 |
| 99 void XPCMessageServer::ReceiveMessage() { |
| 100 IPCMessage request; |
| 101 int rv = xpc_pipe_receive(server_port_, &request.xpc); |
| 102 if (rv) { |
| 103 LOG(ERROR) << "Failed to xpc_pipe_receive(): " << rv; |
| 104 return; |
| 105 } |
| 106 |
| 107 demuxer_->DemuxMessage(request); |
| 108 |
| 109 xpc_release(request.xpc); |
| 110 if (reply_message_) { |
| 111 xpc_release(reply_message_); |
| 112 reply_message_ = NULL; |
| 113 } |
| 114 } |
| 115 |
| 116 } // namespace sandbox |
OLD | NEW |