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>
10 #include "base/mac/mac_util.h"
17 // Verified from launchd-329.3.3 (10.6.8).
18 struct look_up2_request_10_6
{
19 mach_msg_header_t Head
;
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
;
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
;
45 // look_up2_reply_10_7 is the same as the 10_6 version.
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
;
62 // TODO(rsesek): Libc provides strnlen() starting in 10.7.
63 size_t strnlen(const char* str
, size_t maxlen
) {
65 for (; len
< maxlen
; ++len
, ++str
) {
72 uint64_t MachGetMessageID(const IPCMessage message
) {
73 return message
.mach
->msgh_id
;
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
);
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;
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
>;
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
>;
135 } // namespace sandbox