Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / sandbox / mac / os_compatibility.cc
blob6624f3a19be760740d8e1840287868e094b2a181
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.
5 #include "sandbox/mac/os_compatibility.h"
7 #include <servers/bootstrap.h>
8 #include <unistd.h>
10 #include "base/mac/mac_util.h"
12 namespace sandbox {
14 namespace {
16 #pragma pack(push, 4)
17 // Verified from launchd-329.3.3 (10.6.8).
18 struct look_up2_request_10_6 {
19 mach_msg_header_t Head;
20 NDR_record_t NDR;
21 name_t servicename;
22 pid_t targetpid;
23 uint64_t flags;
26 struct look_up2_reply_10_6 {
27 mach_msg_header_t Head;
28 mach_msg_body_t msgh_body;
29 mach_msg_port_descriptor_t service_port;
32 // Verified from:
33 // launchd-392.39 (10.7.5)
34 // launchd-442.26.2 (10.8.5)
35 // launchd-842.1.4 (10.9.0)
36 struct look_up2_request_10_7 {
37 mach_msg_header_t Head;
38 NDR_record_t NDR;
39 name_t servicename;
40 pid_t targetpid;
41 uuid_t instanceid;
42 uint64_t flags;
45 // look_up2_reply_10_7 is the same as the 10_6 version.
47 // Verified from:
48 // launchd-329.3.3 (10.6.8)
49 // launchd-392.39 (10.7.5)
50 // launchd-442.26.2 (10.8.5)
51 // launchd-842.1.4 (10.9.0)
52 typedef int vproc_gsk_t; // Defined as an enum in liblaunch/vproc_priv.h.
53 struct swap_integer_request_10_6 {
54 mach_msg_header_t Head;
55 NDR_record_t NDR;
56 vproc_gsk_t inkey;
57 vproc_gsk_t outkey;
58 int64_t inval;
60 #pragma pack(pop)
62 // TODO(rsesek): Libc provides strnlen() starting in 10.7.
63 size_t strnlen(const char* str, size_t maxlen) {
64 size_t len = 0;
65 for (; len < maxlen; ++len, ++str) {
66 if (*str == '\0')
67 break;
69 return len;
72 uint64_t MachGetMessageID(const IPCMessage message) {
73 return message.mach->msgh_id;
76 template <typename R>
77 std::string LaunchdLookUp2GetRequestName(const IPCMessage message) {
78 mach_msg_header_t* header = message.mach;
79 DCHECK_EQ(sizeof(R), header->msgh_size);
80 const R* request = reinterpret_cast<const R*>(header);
81 // Make sure the name is properly NUL-terminated.
82 const size_t name_length =
83 strnlen(request->servicename, BOOTSTRAP_MAX_NAME_LEN);
84 std::string name = std::string(request->servicename, name_length);
85 return name;
88 template <typename R>
89 void LaunchdLookUp2FillReply(IPCMessage message, mach_port_t port) {
90 R* reply = reinterpret_cast<R*>(message.mach);
91 reply->Head.msgh_size = sizeof(R);
92 reply->Head.msgh_bits =
93 MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_MOVE_SEND_ONCE) |
94 MACH_MSGH_BITS_COMPLEX;
95 reply->msgh_body.msgh_descriptor_count = 1;
96 reply->service_port.name = port;
97 reply->service_port.disposition = MACH_MSG_TYPE_COPY_SEND;
98 reply->service_port.type = MACH_MSG_PORT_DESCRIPTOR;
101 template <typename R>
102 bool LaunchdSwapIntegerIsGetOnly(const IPCMessage message) {
103 const R* request = reinterpret_cast<const R*>(message.mach);
104 return request->inkey == 0 && request->inval == 0 && request->outkey != 0;
107 } // namespace
109 const LaunchdCompatibilityShim GetLaunchdCompatibilityShim() {
110 LaunchdCompatibilityShim shim = {
111 .ipc_message_get_id = &MachGetMessageID,
112 .msg_id_look_up2 = 404,
113 .msg_id_swap_integer = 416,
114 .look_up2_fill_reply = &LaunchdLookUp2FillReply<look_up2_reply_10_6>,
115 .swap_integer_is_get_only =
116 &LaunchdSwapIntegerIsGetOnly<swap_integer_request_10_6>,
119 if (base::mac::IsOSSnowLeopard()) {
120 shim.look_up2_get_request_name =
121 &LaunchdLookUp2GetRequestName<look_up2_request_10_6>;
122 } else if (base::mac::IsOSLionOrLater() &&
123 !base::mac::IsOSYosemiteOrLater()) {
124 shim.look_up2_get_request_name =
125 &LaunchdLookUp2GetRequestName<look_up2_request_10_7>;
126 } else {
127 DLOG(ERROR) << "Unknown OS, using launchd compatibility shim from 10.7.";
128 shim.look_up2_get_request_name =
129 &LaunchdLookUp2GetRequestName<look_up2_request_10_7>;
132 return shim;
135 } // namespace sandbox