15f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 25f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// found in the LICENSE file. 45f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sandbox/mac/xpc_message_server.h" 65f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 75f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <bsm/libbsm.h> 85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 95f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <string> 105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/mac/mach_logging.h" 125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "base/strings/stringprintf.h" 135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sandbox/mac/dispatch_source_mach.h" 145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sandbox/mac/xpc.h" 155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace sandbox { 175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)XPCMessageServer::XPCMessageServer(MessageDemuxer* demuxer, 195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mach_port_t server_receive_right) 205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : demuxer_(demuxer), 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) server_port_(server_receive_right), 225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reply_message_(NULL) { 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)XPCMessageServer::~XPCMessageServer() { 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XPCMessageServer::Initialize() { 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Allocate a port for use as a new server port if one was not passed to the 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // constructor. 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!server_port_.is_valid()) { 325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mach_port_t port; 335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kern_return_t kr; 345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if ((kr = mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, 355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) &port)) != KERN_SUCCESS) { 365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) MACH_LOG(ERROR, kr) << "Failed to allocate new server port."; 375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) server_port_.reset(port); 405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::string label = base::StringPrintf( 435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) "org.chromium.sandbox.XPCMessageServer.%p", demuxer_); 445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispatch_source_.reset(new DispatchSourceMach( 455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) label.c_str(), server_port_.get(), ^{ ReceiveMessage(); })); 465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) dispatch_source_->Resume(); 475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)pid_t XPCMessageServer::GetMessageSenderPID(IPCMessage request) { 525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) audit_token_t token; 535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xpc_dictionary_get_audit_token(request.xpc, &token); 545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(rsesek): In the 10.7 SDK, there's audit_token_to_pid(). 555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) pid_t sender_pid; 565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) audit_token_to_au32(token, 575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) NULL, NULL, NULL, NULL, NULL, &sender_pid, NULL, NULL); 585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return sender_pid; 595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)IPCMessage XPCMessageServer::CreateReply(IPCMessage request) { 625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!reply_message_) 635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reply_message_ = xpc_dictionary_create_reply(request.xpc); 645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPCMessage reply; 665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reply.xpc = reply_message_; 675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return reply; 685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool XPCMessageServer::SendReply(IPCMessage reply) { 715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int rv = xpc_pipe_routine_reply(reply.xpc); 725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (rv) { 735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Failed to xpc_pipe_routine_reply(): " << rv; 745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return false; 755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return true; 775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void XPCMessageServer::ForwardMessage(IPCMessage request, 805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) mach_port_t destination) { 815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xpc_pipe_t pipe = xpc_pipe_create_from_port(destination, 0); 825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int rv = xpc_pipe_routine_forward(pipe, request.xpc); 835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (rv) { 845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Failed to xpc_pipe_routine_forward(): " << rv; 855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xpc_release(pipe); 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void XPCMessageServer::RejectMessage(IPCMessage request, int error_code) { 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPCMessage reply = CreateReply(request); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xpc_dictionary_set_int64(reply.xpc, "error", error_code); 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SendReply(reply); 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)mach_port_t XPCMessageServer::GetServerPort() const { 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return server_port_.get(); 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void XPCMessageServer::ReceiveMessage() { 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) IPCMessage request; 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int rv = xpc_pipe_receive(server_port_, &request.xpc); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (rv) { 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) LOG(ERROR) << "Failed to xpc_pipe_receive(): " << rv; 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return; 1055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) demuxer_->DemuxMessage(request); 1085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xpc_release(request.xpc); 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (reply_message_) { 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) xpc_release(reply_message_); 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) reply_message_ = NULL; 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace sandbox 117