REGRESSION(r230748) [WinCairo] 'JSC::JIT::appendCallWithSlowPathReturnType': function...
[WebKit-https.git] / Source / WebKit / Shared / mac / ChildProcessMac.mm
1 /*
2  * Copyright (C) 2012-2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27
28 #if PLATFORM(MAC)
29 #import "ChildProcess.h"
30
31 #import "CodeSigning.h"
32 #import "QuarantineSPI.h"
33 #import "SandboxInitializationParameters.h"
34 #import <WebCore/FileSystem.h>
35 #import <WebCore/SystemVersion.h>
36 #import <mach/mach.h>
37 #import <mach/task.h>
38 #import <pwd.h>
39 #import <stdlib.h>
40 #import <sysexits.h>
41 #import <wtf/Scope.h>
42 #import <wtf/spi/darwin/SandboxSPI.h>
43
44 #if USE(APPLE_INTERNAL_SDK)
45 #include <HIServices/ProcessesPriv.h>
46 #endif
47
48 typedef bool (^LSServerConnectionAllowedBlock) ( CFDictionaryRef optionsRef );
49 extern "C" void _LSSetApplicationLaunchServicesServerConnectionStatus(uint64_t flags, LSServerConnectionAllowedBlock block);
50 extern "C" CFDictionaryRef _LSApplicationCheckIn(int sessionID, CFDictionaryRef applicationInfo);
51
52 extern "C" OSStatus SetApplicationIsDaemon(Boolean isDaemon);
53
54 using namespace WebCore;
55
56 namespace WebKit {
57
58 static void initializeTimerCoalescingPolicy()
59 {
60     // Set task_latency and task_throughput QOS tiers as appropriate for a visible application.
61     struct task_qos_policy qosinfo = { LATENCY_QOS_TIER_0, THROUGHPUT_QOS_TIER_0 };
62     kern_return_t kr = task_policy_set(mach_task_self(), TASK_BASE_QOS_POLICY, (task_policy_t)&qosinfo, TASK_QOS_POLICY_COUNT);
63     ASSERT_UNUSED(kr, kr == KERN_SUCCESS);
64 }
65
66 void ChildProcess::setApplicationIsDaemon()
67 {
68     OSStatus error = SetApplicationIsDaemon(true);
69     ASSERT_UNUSED(error, error == noErr);
70
71     launchServicesCheckIn();
72 }
73
74 void ChildProcess::launchServicesCheckIn()
75 {
76     _LSSetApplicationLaunchServicesServerConnectionStatus(0, 0);
77     RetainPtr<CFDictionaryRef> unused = _LSApplicationCheckIn(-2, CFBundleGetInfoDictionary(CFBundleGetMainBundle()));
78 }
79
80 void ChildProcess::platformInitialize()
81 {
82     initializeTimerCoalescingPolicy();
83     [[NSFileManager defaultManager] changeCurrentDirectoryPath:[[NSBundle mainBundle] bundlePath]];
84 }
85
86 static OSStatus enableSandboxStyleFileQuarantine()
87 {
88     int error;
89     qtn_proc_t quarantineProperties = qtn_proc_alloc();
90     auto quarantinePropertiesDeleter = makeScopeExit([quarantineProperties]() {
91         qtn_proc_free(quarantineProperties);
92     });
93
94     if ((error = qtn_proc_init_with_self(quarantineProperties)))
95         return error;
96
97     if ((error = qtn_proc_set_flags(quarantineProperties, QTN_FLAG_SANDBOX)))
98         return error;
99
100     // QTN_FLAG_SANDBOX is silently ignored if security.mac.qtn.sandbox_enforce sysctl is 0.
101     // In that case, quarantine falls back to advisory QTN_FLAG_DOWNLOAD.
102     return qtn_proc_apply_to_self(quarantineProperties);
103 }
104
105 void ChildProcess::initializeSandbox(const ChildProcessInitializationParameters& parameters, SandboxInitializationParameters& sandboxParameters)
106 {
107     NSBundle *webkit2Bundle = [NSBundle bundleForClass:NSClassFromString(@"WKView")];
108     String defaultProfilePath = [webkit2Bundle pathForResource:[[NSBundle mainBundle] bundleIdentifier] ofType:@"sb"];
109
110     if (sandboxParameters.userDirectorySuffix().isNull()) {
111         auto userDirectorySuffix = parameters.extraInitializationData.find("user-directory-suffix");
112         if (userDirectorySuffix != parameters.extraInitializationData.end())
113             sandboxParameters.setUserDirectorySuffix([makeString(userDirectorySuffix->value, '/', String([[NSBundle mainBundle] bundleIdentifier])) fileSystemRepresentation]);
114         else {
115             String clientIdentifier = codeSigningIdentifier(parameters.connectionIdentifier.xpcConnection.get());
116             if (clientIdentifier.isNull())
117                 clientIdentifier = parameters.clientIdentifier;
118             String defaultUserDirectorySuffix = makeString(String([[NSBundle mainBundle] bundleIdentifier]), '+', clientIdentifier);
119             sandboxParameters.setUserDirectorySuffix(defaultUserDirectorySuffix);
120         }
121     }
122
123     Vector<String> osVersionParts;
124     String osSystemMarketingVersion = systemMarketingVersion();
125     osSystemMarketingVersion.split('.', false, osVersionParts);
126     if (osVersionParts.size() < 2) {
127         WTFLogAlways("%s: Couldn't find OS Version\n", getprogname());
128         exit(EX_NOPERM);
129     }
130     String osVersion = osVersionParts[0] + '.' + osVersionParts[1];
131     sandboxParameters.addParameter("_OS_VERSION", osVersion.utf8().data());
132
133     // Use private temporary and cache directories.
134     setenv("DIRHELPER_USER_DIR_SUFFIX", FileSystem::fileSystemRepresentation(sandboxParameters.userDirectorySuffix()).data(), 1);
135     char temporaryDirectory[PATH_MAX];
136     if (!confstr(_CS_DARWIN_USER_TEMP_DIR, temporaryDirectory, sizeof(temporaryDirectory))) {
137         WTFLogAlways("%s: couldn't retrieve private temporary directory path: %d\n", getprogname(), errno);
138         exit(EX_NOPERM);
139     }
140     setenv("TMPDIR", temporaryDirectory, 1);
141
142     sandboxParameters.addPathParameter("WEBKIT2_FRAMEWORK_DIR", [[webkit2Bundle bundlePath] stringByDeletingLastPathComponent]);
143     sandboxParameters.addConfDirectoryParameter("DARWIN_USER_TEMP_DIR", _CS_DARWIN_USER_TEMP_DIR);
144     sandboxParameters.addConfDirectoryParameter("DARWIN_USER_CACHE_DIR", _CS_DARWIN_USER_CACHE_DIR);
145
146     char buffer[4096];
147     int bufferSize = sizeof(buffer);
148     struct passwd pwd;
149     struct passwd* result = 0;
150     if (getpwuid_r(getuid(), &pwd, buffer, bufferSize, &result) || !result) {
151         WTFLogAlways("%s: Couldn't find home directory\n", getprogname());
152         exit(EX_NOPERM);
153     }
154
155     sandboxParameters.addPathParameter("HOME_DIR", pwd.pw_dir);
156
157     String path = String::fromUTF8(pwd.pw_dir);
158     path.append("/Library");
159
160     sandboxParameters.addPathParameter("HOME_LIBRARY_DIR", FileSystem::fileSystemRepresentation(path).data());
161
162     path.append("/Preferences");
163
164     sandboxParameters.addPathParameter("HOME_LIBRARY_PREFERENCES_DIR", FileSystem::fileSystemRepresentation(path).data());
165
166     switch (sandboxParameters.mode()) {
167     case SandboxInitializationParameters::UseDefaultSandboxProfilePath:
168     case SandboxInitializationParameters::UseOverrideSandboxProfilePath: {
169         String sandboxProfilePath = sandboxParameters.mode() == SandboxInitializationParameters::UseDefaultSandboxProfilePath ? defaultProfilePath : sandboxParameters.overrideSandboxProfilePath();
170         if (!sandboxProfilePath.isEmpty()) {
171             CString profilePath = FileSystem::fileSystemRepresentation(sandboxProfilePath);
172             char* errorBuf;
173             if (sandbox_init_with_parameters(profilePath.data(), SANDBOX_NAMED_EXTERNAL, sandboxParameters.namedParameterArray(), &errorBuf)) {
174                 WTFLogAlways("%s: Couldn't initialize sandbox profile [%s], error '%s'\n", getprogname(), profilePath.data(), errorBuf);
175                 for (size_t i = 0, count = sandboxParameters.count(); i != count; ++i)
176                     WTFLogAlways("%s=%s\n", sandboxParameters.name(i), sandboxParameters.value(i));
177                 exit(EX_NOPERM);
178             }
179         }
180
181         break;
182     }
183     case SandboxInitializationParameters::UseSandboxProfile: {
184         char* errorBuf;
185         if (sandbox_init_with_parameters(sandboxParameters.sandboxProfile().utf8().data(), 0, sandboxParameters.namedParameterArray(), &errorBuf)) {
186             WTFLogAlways("%s: Couldn't initialize sandbox profile, error '%s'\n", getprogname(), errorBuf);
187             for (size_t i = 0, count = sandboxParameters.count(); i != count; ++i)
188                 WTFLogAlways("%s=%s\n", sandboxParameters.name(i), sandboxParameters.value(i));
189             exit(EX_NOPERM);
190         }
191
192         break;
193     }
194     }
195
196     // This will override LSFileQuarantineEnabled from Info.plist unless sandbox quarantine is globally disabled.
197     OSStatus error = enableSandboxStyleFileQuarantine();
198     if (error) {
199         WTFLogAlways("%s: Couldn't enable sandbox style file quarantine: %ld\n", getprogname(), static_cast<long>(error));
200         exit(EX_NOPERM);
201     }
202 }
203
204 #if USE(APPKIT)
205 void ChildProcess::stopNSAppRunLoop()
206 {
207     ASSERT([NSApp isRunning]);
208     [NSApp stop:nil];
209
210     NSEvent *event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined location:NSMakePoint(0, 0) modifierFlags:0 timestamp:0.0 windowNumber:0 context:nil subtype:0 data1:0 data2:0];
211     [NSApp postEvent:event atStart:true];
212 }
213 #endif
214
215 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101400
216 void ChildProcess::stopNSRunLoop()
217 {
218     ASSERT([NSRunLoop mainRunLoop]);
219     [[NSRunLoop mainRunLoop] performBlock:^{
220         exit(0);
221     }];
222 }
223 #endif
224
225 void ChildProcess::setQOS(int latencyQOS, int throughputQOS)
226 {
227     if (!latencyQOS && !throughputQOS)
228         return;
229
230     struct task_qos_policy qosinfo = {
231         latencyQOS ? LATENCY_QOS_TIER_0 + latencyQOS - 1 : LATENCY_QOS_TIER_UNSPECIFIED,
232         throughputQOS ? THROUGHPUT_QOS_TIER_0 + throughputQOS - 1 : THROUGHPUT_QOS_TIER_UNSPECIFIED
233     };
234
235     task_policy_set(mach_task_self(), TASK_OVERRIDE_QOS_POLICY, (task_policy_t)&qosinfo, TASK_QOS_POLICY_COUNT);
236 }
237
238 } // namespace WebKit
239
240 #endif