1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/seccomp_support_detector.h"
#include <stdio.h>
#include <sys/utsname.h>
#include "base/message_loop/message_loop_proxy.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
#include "chrome/common/chrome_utility_messages.h"
#include "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
enum AndroidSeccompStatus {
DETECTION_FAILED, // The process crashed during detection.
NOT_SUPPORTED, // Kernel has no seccomp support.
SUPPORTED, // Kernel has seccomp support.
LAST_STATUS
};
// static
void SeccompSupportDetector::StartDetection() {
// This is instantiated here, and then ownership is maintained by the
// Closure objects when the object is being passed between threads. A
// reference is also taken by the UtilityProcessHost, which will release
// it when the process exits.
scoped_refptr<SeccompSupportDetector> detector(new SeccompSupportDetector());
BrowserThread::PostBlockingPoolTask(FROM_HERE,
base::Bind(&SeccompSupportDetector::DetectKernelVersion, detector));
}
SeccompSupportDetector::SeccompSupportDetector() : prctl_detected_(false) {
}
SeccompSupportDetector::~SeccompSupportDetector() {
}
void SeccompSupportDetector::DetectKernelVersion() {
DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
// This method will report the kernel major and minor versions by
// taking the lower 16 bits of each version number and combining
// the two into a 32-bit number.
utsname uts;
if (uname(&uts) == 0) {
int major, minor;
if (sscanf(uts.release, "%d.%d", &major, &minor) == 2) {
int version = ((major & 0xFFFF) << 16) | (minor & 0xFFFF);
UMA_HISTOGRAM_SPARSE_SLOWLY("Android.KernelVersion", version);
}
}
#if defined(USE_SECCOMP_BPF)
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&SeccompSupportDetector::DetectSeccomp, this));
#else
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&SeccompSupportDetector::OnDetectPrctl, this, false));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
base::Bind(&SeccompSupportDetector::OnDetectSyscall, this, false));
#endif
}
void SeccompSupportDetector::DetectSeccomp() {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
content::UtilityProcessHost* utility_process_host =
content::UtilityProcessHost::Create(
this, base::MessageLoopProxy::current());
utility_process_host->SetName(l10n_util::GetStringUTF16(
IDS_UTILITY_PROCESS_SECCOMP_DETECTOR_NAME));
utility_process_host->Send(new ChromeUtilityMsg_DetectSeccompSupport());
}
void SeccompSupportDetector::OnProcessCrashed(int exit_code) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
// The process crashed. Since prctl detection happens first, report which
// probe failed.
if (prctl_detected_) {
UMA_HISTOGRAM_ENUMERATION("Android.SeccompStatus.Syscall",
DETECTION_FAILED,
LAST_STATUS);
} else {
UMA_HISTOGRAM_ENUMERATION("Android.SeccompStatus.Prctl",
DETECTION_FAILED,
LAST_STATUS);
}
}
bool SeccompSupportDetector::OnMessageReceived(const IPC::Message& message) {
bool handled = false;
IPC_BEGIN_MESSAGE_MAP(SeccompSupportDetector, message)
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DetectSeccompSupport_ResultPrctl,
OnDetectPrctl)
IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_DetectSeccompSupport_ResultSyscall,
OnDetectSyscall)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
void SeccompSupportDetector::OnDetectPrctl(bool prctl_supported) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!prctl_detected_);
prctl_detected_ = true;
UMA_HISTOGRAM_ENUMERATION("Android.SeccompStatus.Prctl",
prctl_supported ? SUPPORTED : NOT_SUPPORTED,
LAST_STATUS);
}
void SeccompSupportDetector::OnDetectSyscall(bool syscall_supported) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(prctl_detected_);
UMA_HISTOGRAM_ENUMERATION("Android.SeccompStatus.Syscall",
syscall_supported ? SUPPORTED : NOT_SUPPORTED,
LAST_STATUS);
// The utility process will shutdown after this, and this object will
// be deleted when the UtilityProcessHost releases its reference.
}
|