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