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