• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
XPCMessageServer(MessageDemuxer * demuxer,mach_port_t server_receive_right)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 
~XPCMessageServer()25 XPCMessageServer::~XPCMessageServer() {
26 }
27 
Initialize()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 
GetMessageSenderPID(IPCMessage request)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 
CreateReply(IPCMessage request)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 
SendReply(IPCMessage reply)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 
ForwardMessage(IPCMessage request,mach_port_t destination)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 
RejectMessage(IPCMessage request,int error_code)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 
GetServerPort() const95 mach_port_t XPCMessageServer::GetServerPort() const {
96   return server_port_.get();
97 }
98 
ReceiveMessage()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
117