OSDN Git Service

Merge "mksquashfsimage.sh: Make disable-4k-align a paramter" into nyc-dev
authorMohamad Ayyash <mkayyash@google.com>
Thu, 16 Jun 2016 16:24:33 +0000 (16:24 +0000)
committerAndroid (Google) Code Review <android-gerrit@google.com>
Thu, 16 Jun 2016 16:24:34 +0000 (16:24 +0000)
simpleperf/cmd_list.cpp
simpleperf/cmd_record.cpp
simpleperf/cmd_stat.cpp
simpleperf/environment.cpp
simpleperf/environment.h
simpleperf/gtest_main.cpp
simpleperf/utils.cpp
simpleperf/utils.h

index b6bf817..273a803 100644 (file)
@@ -22,6 +22,7 @@
 #include <android-base/logging.h>
 
 #include "command.h"
+#include "environment.h"
 #include "event_attr.h"
 #include "event_fd.h"
 #include "event_type.h"
@@ -30,9 +31,14 @@ static void PrintEventTypesOfType(uint32_t type, const std::string& type_name,
                                   const std::vector<EventType>& event_types) {
   printf("List of %s:\n", type_name.c_str());
   for (auto& event_type : event_types) {
-    if (event_type.type == type &&
-        IsEventAttrSupportedByKernel(CreateDefaultPerfEventAttr(event_type))) {
-      printf("  %s\n", event_type.name.c_str());
+    if (event_type.type == type) {
+      perf_event_attr attr = CreateDefaultPerfEventAttr(event_type);
+      // Exclude kernel to list supported events even when
+      // /proc/sys/kernel/perf_event_paranoid is 2.
+      attr.exclude_kernel = 1;
+      if (IsEventAttrSupportedByKernel(attr)) {
+        printf("  %s\n", event_type.name.c_str());
+      }
     }
   }
   printf("\n");
@@ -50,6 +56,10 @@ class ListCommand : public Command {
 };
 
 bool ListCommand::Run(const std::vector<std::string>& args) {
+  if (!CheckPerfEventLimit()) {
+    return false;
+  }
+
   static std::map<std::string, std::pair<int, std::string>> type_map = {
       {"hw", {PERF_TYPE_HARDWARE, "hardware events"}},
       {"sw", {PERF_TYPE_SOFTWARE, "software events"}},
index 910bc3e..ae025b0 100644 (file)
@@ -188,6 +188,10 @@ class RecordCommand : public Command {
 };
 
 bool RecordCommand::Run(const std::vector<std::string>& args) {
+  if (!CheckPerfEventLimit()) {
+    return false;
+  }
+
   // 1. Parse options, and use default measured event type if not given.
   std::vector<std::string> workload_args;
   if (!ParseOptions(args, &workload_args)) {
index 228b4ed..488e731 100644 (file)
@@ -101,6 +101,10 @@ class StatCommand : public Command {
 };
 
 bool StatCommand::Run(const std::vector<std::string>& args) {
+  if (!CheckPerfEventLimit()) {
+    return false;
+  }
+
   // 1. Parse options, and use default measured event types if not given.
   std::vector<std::string> workload_args;
   if (!ParseOptions(args, &workload_args)) {
index 996a5e4..5a8552a 100644 (file)
 #include <android-base/strings.h>
 #include <android-base/stringprintf.h>
 
+#if defined(__ANDROID__)
+#include <sys/system_properties.h>
+#endif
+
 #include "read_elf.h"
 #include "utils.h"
 
@@ -410,3 +414,66 @@ bool GetExecPath(std::string* exec_path) {
   *exec_path = path;
   return true;
 }
+
+/*
+ * perf event paranoia level:
+ *  -1 - not paranoid at all
+ *   0 - disallow raw tracepoint access for unpriv
+ *   1 - disallow cpu events for unpriv
+ *   2 - disallow kernel profiling for unpriv
+ *   3 - disallow user profiling for unpriv
+ */
+static bool ReadPerfEventParanoid(int* value) {
+  std::string s;
+  if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid", &s)) {
+    PLOG(ERROR) << "failed to read /proc/sys/kernel/perf_event_paranoid";
+    return false;
+  }
+  s = android::base::Trim(s);
+  if (!android::base::ParseInt(s.c_str(), value)) {
+    PLOG(ERROR) << "failed to parse /proc/sys/kernel/perf_event_paranoid: " << s;
+    return false;
+  }
+  return true;
+}
+
+static const char* GetLimitLevelDescription(int limit_level) {
+  switch (limit_level) {
+    case -1: return "unlimited";
+    case 0: return "disallowing raw tracepoint access for unpriv";
+    case 1: return "disallowing cpu events for unpriv";
+    case 2: return "disallowing kernel profiling for unpriv";
+    case 3: return "disallowing user profiling for unpriv";
+    default: return "unknown level";
+  }
+}
+
+bool CheckPerfEventLimit() {
+  // root is not limited by /proc/sys/kernel/perf_event_paranoid.
+  if (IsRoot()) {
+    return true;
+  }
+  int limit_level;
+  if (!ReadPerfEventParanoid(&limit_level)) {
+    return false;
+  }
+  if (limit_level <= 1) {
+    return true;
+  }
+#if defined(__ANDROID__)
+  // Try to enable perf_event_paranoid by setprop security.perf_harden=0.
+  if (__system_property_set("security.perf_harden", "0") == 0) {
+    sleep(1);
+    if (ReadPerfEventParanoid(&limit_level) && limit_level <= 1) {
+      return true;
+    }
+  }
+  LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level
+      << ", " << GetLimitLevelDescription(limit_level) << ".";
+  LOG(WARNING) << "Try using `adb shell setprop security.perf_harden 0` to allow profiling.";
+#else
+  LOG(WARNING) << "/proc/sys/kernel/perf_event_paranoid is " << limit_level
+      << ", " << GetLimitLevelDescription(limit_level) << ".";
+#endif
+  return true;
+}
index c405af8..6da632b 100644 (file)
@@ -79,5 +79,6 @@ struct KernelSymbol {
 
 bool ProcessKernelSymbols(const std::string& symbol_file,
                           std::function<bool(const KernelSymbol&)> callback);
+bool CheckPerfEventLimit();
 
 #endif  // SIMPLE_PERF_ENVIRONMENT_H_
index c9a066e..444a1c2 100644 (file)
 #include <android-base/test_utils.h>
 #include <ziparchive/zip_archive.h>
 
+#if defined(__ANDROID__)
+#include <sys/system_properties.h>
+#endif
+
 #include "get_test_data.h"
 #include "read_elf.h"
 #include "utils.h"
@@ -90,6 +94,44 @@ static bool ExtractTestDataFromElfSection() {
   }
   return true;
 }
+
+#if defined(__ANDROID__)
+class SavedPerfHardenProperty {
+ public:
+  SavedPerfHardenProperty() {
+    __system_property_get("security.perf_harden", prop_value_);
+    if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid",
+                                    &paranoid_value_)) {
+      PLOG(ERROR) << "failed to read /proc/sys/kernel/perf_event_paranoid";
+    }
+  }
+
+  ~SavedPerfHardenProperty() {
+    if (strlen(prop_value_) != 0) {
+      if (__system_property_set("security.perf_harden", prop_value_) != 0) {
+        PLOG(ERROR) << "failed to set security.perf_harden";
+        return;
+      }
+      // Sleep one second to wait for security.perf_harden changing
+      // /proc/sys/kernel/perf_event_paranoid.
+      sleep(1);
+      std::string paranoid_value;
+      if (!android::base::ReadFileToString("/proc/sys/kernel/perf_event_paranoid",
+                                           &paranoid_value)) {
+        PLOG(ERROR) << "failed to read /proc/sys/kernel/perf_event_paranoid";
+        return;
+      }
+      if (paranoid_value_ != paranoid_value) {
+        LOG(ERROR) << "failed to restore /proc/sys/kernel/perf_event_paranoid";
+      }
+    }
+  }
+
+ private:
+  char prop_value_[PROP_VALUE_MAX];
+  std::string paranoid_value_;
+};
+#endif  // defined(__ANDROID__)
 #endif  // defined(IN_CTS_TEST)
 
 int main(int argc, char** argv) {
@@ -126,6 +168,13 @@ int main(int argc, char** argv) {
       return 1;
     }
   }
+
+#if defined(__ANDROID__)
+  // A cts test PerfEventParanoidTest.java is testing if
+  // /proc/sys/kernel/perf_event_paranoid is 3, so restore perf_harden
+  // value after current test to not break that test.
+  SavedPerfHardenProperty saved_perf_harden;
+#endif
 #endif
   if (!::testing::GTEST_FLAG(list_tests) && testdata_dir.empty()) {
     printf("Usage: %s -t <testdata_dir>\n", argv[0]);
@@ -145,15 +194,3 @@ std::string GetTestData(const std::string& filename) {
 const std::string& GetTestDataDir() {
   return testdata_dir;
 }
-
-bool IsRoot() {
-  static int is_root = -1;
-  if (is_root == -1) {
-#if defined(__linux__)
-    is_root = (getuid() == 0) ? 1 : 0;
-#else
-    is_root = 0;
-#endif
-  }
-  return is_root == 1;
-}
index fb24d1e..d14d20c 100644 (file)
@@ -197,3 +197,15 @@ bool GetLogSeverity(const std::string& name, android::base::LogSeverity* severit
   }
   return false;
 }
+
+bool IsRoot() {
+  static int is_root = -1;
+  if (is_root == -1) {
+#if defined(__linux__)
+    is_root = (getuid() == 0) ? 1 : 0;
+#else
+    is_root = 0;
+#endif
+  }
+  return is_root == 1;
+}
index c65641c..420fcc9 100644 (file)
@@ -121,4 +121,5 @@ bool MkdirWithParents(const std::string& path);
 
 bool GetLogSeverity(const std::string& name, android::base::LogSeverity* severity);
 
+bool IsRoot();
 #endif  // SIMPLE_PERF_UTILS_H_