Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: set ts=8 sts=4 et sw=4 tw=99:
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifdef __APPLE__
9 #include "sharkctl.h"
10 #include <stddef.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <unistd.h>
15 #include "jsutil.h"
17 #define SHARK_MSG_ACQUIRE 0x29a
18 #define SHARK_MSG_RELEASE 0x29b
19 #define SHARK_MSG_STOP 0x29c
20 #define SHARK_MSG_START 0x29d
22 #define RECV_SIZEOF(ty) offsetof(ty, out)
24 // Private API in libSystem.dylib
25 extern "C" void bootstrap_look_up(mach_port_t special_port, const char *name,
26 mach_port_t *dest_port);
28 struct chud_client_acquire_msg {
29 mach_msg_header_t hdr;
30 uint32_t unk0; // always 0
31 uint32_t unk1; // always 1
32 uint32_t pid;
33 uint32_t out[2];
34 };
36 struct chud_client_start_msg {
37 mach_msg_header_t hdr;
38 uint32_t unk0; // always 1
39 uint32_t name0;
40 uint32_t arg2; // always 6
41 uint8_t unk1; // always 0
42 uint8_t unk2; // always 1
43 uint8_t unk3; // uninitialized
44 uint8_t unk4; // always 1
45 uint32_t unk5; // always 0
46 uint32_t unk6; // always 1
47 uint32_t name1; // same as name0
48 };
50 struct chud_client_stop_msg {
51 mach_msg_header_t hdr;
52 uint32_t out[5];
53 };
55 struct chud_client_release_msg {
56 mach_msg_header_t hdr;
57 uint32_t unk0; // always 0
58 uint32_t unk1; // always 1
59 uint32_t pid;
60 uint32_t out[2];
61 };
63 static mach_port_t
64 CreatePort(void)
65 {
66 mach_port_t bootstrap_port, shark_port = 0;
67 task_get_special_port(mach_task_self(), TASK_BOOTSTRAP_PORT,
68 &bootstrap_port);
69 bootstrap_look_up(bootstrap_port, "CHUD_IPC", &shark_port);
70 return shark_port;
71 }
73 static mach_msg_return_t
74 Connect(mach_port_t shark_port)
75 {
76 mach_port_t reply_port = mig_get_reply_port();
78 struct chud_client_acquire_msg msg;
79 msg.hdr.msgh_bits = 0x1513;
80 msg.hdr.msgh_size = sizeof(mach_msg_header_t);
81 msg.hdr.msgh_remote_port = shark_port;
82 msg.hdr.msgh_local_port = reply_port;
83 msg.hdr.msgh_reserved = 0;
84 msg.hdr.msgh_id = SHARK_MSG_ACQUIRE;
85 msg.unk0 = 0;
86 msg.unk1 = 1;
87 msg.pid = getpid();
89 JS_ASSERT(RECV_SIZEOF(struct chud_client_acquire_msg) == 0x24);
90 JS_ASSERT(sizeof(msg) == 0x2c);
91 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
92 RECV_SIZEOF(struct chud_client_acquire_msg),
93 sizeof(msg), reply_port, 0, 0);
94 mig_dealloc_reply_port(reply_port);
95 return result;
96 }
98 static mach_msg_return_t
99 Start(mach_port_t shark_port, uint32_t name)
100 {
101 mach_port_t reply_port = mig_get_reply_port();
103 struct chud_client_start_msg msg;
104 msg.hdr.msgh_bits = 0x80001513;
105 msg.hdr.msgh_size = sizeof(mach_msg_header_t);
106 msg.hdr.msgh_remote_port = shark_port;
107 msg.hdr.msgh_local_port = reply_port;
108 msg.hdr.msgh_reserved = 0;
109 msg.hdr.msgh_id = SHARK_MSG_START;
110 msg.unk0 = 1;
111 msg.name0 = name;
112 msg.arg2 = 6;
113 msg.unk1 = 0;
114 msg.unk2 = 1;
115 msg.unk3 = 0;
116 msg.unk4 = 1;
117 msg.unk5 = 0;
118 msg.unk6 = 1;
119 msg.name1 = name;
121 JS_ASSERT(sizeof(msg) == 0x34);
122 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
123 sizeof(msg), 0x30, reply_port, 0, 0);
124 mig_dealloc_reply_port(reply_port);
125 return result;
126 }
128 mach_msg_return_t
129 Stop(mach_port_t shark_port)
130 {
131 mach_port_t reply_port = mig_get_reply_port();
133 struct chud_client_stop_msg msg;
134 msg.hdr.msgh_bits = 0x1513;
135 msg.hdr.msgh_size = sizeof(mach_msg_header_t);
136 msg.hdr.msgh_remote_port = shark_port;
137 msg.hdr.msgh_local_port = reply_port;
138 msg.hdr.msgh_reserved = 0;
139 msg.hdr.msgh_id = SHARK_MSG_STOP;
141 JS_ASSERT(RECV_SIZEOF(struct chud_client_stop_msg) == 0x18);
142 JS_ASSERT(sizeof(msg) == 0x2c);
143 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
144 RECV_SIZEOF(struct chud_client_stop_msg),
145 sizeof(msg), reply_port, 0, 0);
146 mig_dealloc_reply_port(reply_port);
147 return result;
148 }
150 static mach_msg_return_t
151 Disconnect(mach_port_t shark_port)
152 {
153 mach_port_t reply_port = mig_get_reply_port();
155 struct chud_client_release_msg msg;
156 msg.hdr.msgh_bits = 0x1513;
157 msg.hdr.msgh_size = sizeof(mach_msg_header_t);
158 msg.hdr.msgh_remote_port = shark_port;
159 msg.hdr.msgh_local_port = reply_port;
160 msg.hdr.msgh_reserved = 0;
161 msg.hdr.msgh_id = SHARK_MSG_RELEASE;
162 msg.unk0 = 0;
163 msg.unk1 = 1;
164 msg.pid = getpid();
166 JS_ASSERT(RECV_SIZEOF(struct chud_client_release_msg) == 0x24);
167 JS_ASSERT(sizeof(msg) == 0x2c);
168 mach_msg_return_t result = mach_msg(&msg.hdr, MACH_SEND_MSG | MACH_RCV_MSG,
169 RECV_SIZEOF(struct chud_client_release_msg),
170 sizeof(msg), reply_port, 0, 0);
171 mig_dealloc_reply_port(reply_port);
172 return result;
173 }
175 static mach_port_t shark_port = 0;
176 static bool connected = false;
177 static bool running = false;
179 namespace Shark {
181 bool
182 Start()
183 {
184 if (!shark_port && !(shark_port = CreatePort()))
185 return false;
186 if (!connected && Connect(shark_port))
187 return false;
188 connected = true;
189 if (!running && ::Start(shark_port, 0xdeadbeef))
190 return false;
191 return running = true;
192 }
194 void
195 Stop()
196 {
197 if (!shark_port || !connected)
198 return;
199 ::Stop(shark_port);
200 running = false;
201 Disconnect(shark_port);
202 connected = false;
203 }
205 }
207 #endif