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 16namespace sandbox { 17 18XPCMessageServer::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 25XPCMessageServer::~XPCMessageServer() { 26} 27 28bool 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 51pid_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 61IPCMessage 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 70bool 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 79void 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 89void 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 95mach_port_t XPCMessageServer::GetServerPort() const { 96 return server_port_.get(); 97} 98 99void 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 117