blob: 6b92e9fa47ab04ecc570a01522478ed263e44e1f [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SANDBOX_MAC_LAUNCHD_INTERCEPTION_SERVER_H_
#define SANDBOX_MAC_LAUNCHD_INTERCEPTION_SERVER_H_
#include <dispatch/dispatch.h>
#include <mach/mach.h>
#include "base/mac/scoped_mach_port.h"
#include "base/mac/scoped_mach_vm.h"
#include "sandbox/mac/os_compatibility.h"
namespace sandbox {
class BootstrapSandbox;
// This class is used to run a Mach IPC message server. This server can
// hold the receive right for a bootstrap_port of a process, and it filters
// a subset of the launchd/bootstrap IPC call set for sandboxing. It permits
// or rejects requests based on the per-process policy specified in the
// BootstrapSandbox.
class LaunchdInterceptionServer {
public:
explicit LaunchdInterceptionServer(const BootstrapSandbox* sandbox);
~LaunchdInterceptionServer();
// Initializes the class and starts running the message server.
bool Initialize();
mach_port_t server_port() const { return server_port_.get(); }
private:
// Event handler for the |server_source_| that reads a message from the queue
// and processes it.
void ReceiveMessage();
// Decodes a message header and handles it by either servicing the request
// itself, forwarding the message on to the real launchd, or rejecting the
// message with an error.
void DemuxMessage(mach_msg_header_t* request, mach_msg_header_t* reply);
// Given a look_up2 request message, this looks up the appropriate sandbox
// policy for the service name then formulates and sends the reply message.
void HandleLookUp(mach_msg_header_t* request,
mach_msg_header_t* reply,
pid_t sender_pid);
// Given a swap_integer request message, this verifies that it is safe, and
// if so, forwards it on to launchd for servicing. If the request is unsafe,
// it replies with an error.
void HandleSwapInteger(mach_msg_header_t* request,
mach_msg_header_t* reply,
pid_t sender_pid);
// Sends a reply message.
void SendReply(mach_msg_header_t* reply);
// Forwards the original |request| on to real bootstrap server for handling.
void ForwardMessage(mach_msg_header_t* request, mach_msg_header_t* reply);
// Replies to the message with the specified |error_code| as a MIG
// error_reply RetCode.
void RejectMessage(mach_msg_header_t* request,
mach_msg_header_t* reply,
int error_code);
// The sandbox for which this message server is running.
const BootstrapSandbox* sandbox_;
// The Mach port on which the server is receiving requests.
base::mac::ScopedMachReceiveRight server_port_;
// The dispatch queue used to service the server_source_.
dispatch_queue_t server_queue_;
// A MACH_RECV dispatch source for the server_port_.
dispatch_source_t server_source_;
// Request and reply buffers used in ReceiveMessage.
base::mac::ScopedMachVM request_buffer_;
base::mac::ScopedMachVM reply_buffer_;
// Whether or not ForwardMessage() was called during ReceiveMessage().
bool did_forward_message_;
// The Mach port handed out in reply to denied look up requests. All denied
// requests share the same port, though nothing reads messages from it.
base::mac::ScopedMachReceiveRight sandbox_port_;
// The compatibility shim that handles differences in message header IDs and
// request/reply structures between different OS X versions.
const LaunchdCompatibilityShim compat_shim_;
};
} // namespace sandbox
#endif // SANDBOX_MAC_LAUNCHD_INTERCEPTION_SERVER_H_