Backed out changeset 2450366cf7ca (bug 1891629) for causing win msix mochitest failures
[gecko.git] / widget / cocoa / nsSandboxViolationSink.mm
blob611e0387b194c259373efa7c53ca33a66daa7c64
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3  * License, v. 2.0. If a copy of the MPL was not distributed with this
4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsSandboxViolationSink.h"
8 #import <Foundation/NSObjCRuntime.h>
10 #include <unistd.h>
11 #include <time.h>
12 #include <asl.h>
13 #include <dispatch/dispatch.h>
14 #include <notify.h>
15 #include "mozilla/Preferences.h"
16 #include "mozilla/Sprintf.h"
18 int nsSandboxViolationSink::mNotifyToken = 0;
19 uint64_t nsSandboxViolationSink::mLastMsgReceived = 0;
21 void nsSandboxViolationSink::Start() {
22   if (mNotifyToken) {
23     return;
24   }
25   notify_register_dispatch(SANDBOX_VIOLATION_NOTIFICATION_NAME, &mNotifyToken,
26                            dispatch_queue_create(SANDBOX_VIOLATION_QUEUE_NAME,
27                                                  DISPATCH_QUEUE_SERIAL),
28                            ^(int token) {
29                              ViolationHandler();
30                            });
33 void nsSandboxViolationSink::Stop() {
34   if (!mNotifyToken) {
35     return;
36   }
37   notify_cancel(mNotifyToken);
38   mNotifyToken = 0;
41 // We need to query syslogd to find out what violations occurred, and whether
42 // they were "ours".  We can use the Apple System Log facility to do this.
43 // Besides calling notify_post("com.apple.sandbox.violation.*"), Apple's
44 // sandboxd also reports all sandbox violations (sent to it by the Sandbox
45 // kernel extension) to syslogd, which stores them and makes them viewable
46 // in the system console.  This is the database we query.
48 // ViolationHandler() is always called on its own secondary thread.  This
49 // makes it unlikely it will interfere with other browser activity.
51 void nsSandboxViolationSink::ViolationHandler() {
52   aslmsg query = asl_new(ASL_TYPE_QUERY);
54   asl_set_query(query, ASL_KEY_FACILITY, "com.apple.sandbox",
55                 ASL_QUERY_OP_EQUAL);
57   // Only get reports that were generated very recently.
58   char query_time[30] = {0};
59   SprintfLiteral(query_time, "%li", time(NULL) - 2);
60   asl_set_query(query, ASL_KEY_TIME, query_time,
61                 ASL_QUERY_OP_NUMERIC | ASL_QUERY_OP_GREATER_EQUAL);
63   // This code is easier to test if we don't just track "our" violations,
64   // which are (normally) few and far between.  For example (for the time
65   // being at least) four appleeventsd sandbox violations happen every time
66   // we start the browser in e10s mode.  But it makes sense to default to
67   // only tracking "our" violations.
68   if (mozilla::Preferences::GetBool(
69           "security.sandbox.mac.track.violations.oursonly", true)) {
70     // This makes each of our processes log its own violations.  It might
71     // be better to make the chrome process log all the other processes'
72     // violations.
73     char query_pid[20] = {0};
74     SprintfLiteral(query_pid, "%u", getpid());
75     asl_set_query(query, ASL_KEY_REF_PID, query_pid, ASL_QUERY_OP_EQUAL);
76   }
78   aslresponse response = asl_search(nullptr, query);
80   // Each time ViolationHandler() is called we grab as many messages as are
81   // available.  Otherwise we might not get them all.
82   if (response) {
83     while (true) {
84       aslmsg hit = nullptr;
85       aslmsg found = nullptr;
86       const char* id_str;
88       while ((hit = aslresponse_next(response))) {
89         // Record the message id to avoid logging the same violation more
90         // than once.
91         id_str = asl_get(hit, ASL_KEY_MSG_ID);
92         uint64_t id_val = atoll(id_str);
93         if (id_val <= mLastMsgReceived) {
94           continue;
95         }
96         mLastMsgReceived = id_val;
97         found = hit;
98         break;
99       }
100       if (!found) {
101         break;
102       }
104       const char* pid_str = asl_get(found, ASL_KEY_REF_PID);
105       const char* message_str = asl_get(found, ASL_KEY_MSG);
106       NSLog(@"nsSandboxViolationSink::ViolationHandler(): id %s, pid %s, "
107             @"message %s",
108             id_str, pid_str, message_str);
109     }
110     aslresponse_free(response);
111   }