crash-reporter: fix pstore detection

The current Enable logic looks for an existing crash rather than the
crash dir itself, so when we boot up clean we get a warning that we
do not support kernel crashes.

BUG=chromium:417350
TEST=`FEATURES=test emerge-link crash-reporter` passes
TEST=`cbuildbot amd64-generic-full` passes
TEST=booted VM and checked syslogs

Change-Id: I076a37889ea10ed30ae522eba007619b001ec787
Reviewed-on: https://chromium-review.googlesource.com/219751
Tested-by: Mike Frysinger <vapier@chromium.org>
Reviewed-by: Luigi Semenzato <semenzato@chromium.org>
Commit-Queue: Mike Frysinger <vapier@chromium.org>
diff --git a/crash-reporter/kernel_collector.cc b/crash-reporter/kernel_collector.cc
index 6ba529f..cd684ff 100644
--- a/crash-reporter/kernel_collector.cc
+++ b/crash-reporter/kernel_collector.cc
@@ -5,6 +5,7 @@
 #include "crash-reporter/kernel_collector.h"
 
 #include <map>
+#include <sys/stat.h>
 
 #include <base/files/file_util.h>
 #include <base/logging.h>
@@ -17,6 +18,7 @@
 namespace {
 
 const char kDefaultKernelStackSignature[] = "kernel-UnspecifiedStackSignature";
+const char kDumpParentPath[] = "/dev";
 const char kDumpPath[] = "/dev/pstore";
 const char kDumpFormat[] = "dmesg-ramoops-%zu";
 const char kKernelExecName[] = "kernel";
@@ -235,6 +237,27 @@
   *kernel_dump = result.str();
 }
 
+bool KernelCollector::DumpDirMounted() {
+  struct stat st_parent;
+  if (stat(kDumpParentPath, &st_parent)) {
+    PLOG(WARNING) << "Could not stat " << kDumpParentPath;
+    return false;
+  }
+
+  struct stat st_dump;
+  if (stat(kDumpPath, &st_dump)) {
+    PLOG(WARNING) << "Could not stat " << kDumpPath;
+    return false;
+  }
+
+  if (st_parent.st_dev == st_dump.st_dev) {
+    LOG(WARNING) << "Dump dir " << kDumpPath << " not mounted";
+    return false;
+  }
+
+  return true;
+}
+
 bool KernelCollector::Enable() {
   if (arch_ == kArchUnknown || arch_ >= kArchCount ||
       kPCRegex[arch_] == nullptr) {
@@ -242,9 +265,7 @@
     return false;
   }
 
-  FilePath ramoops_record;
-  GetRamoopsRecordPath(&ramoops_record, 0);
-  if (!base::PathExists(ramoops_record)) {
+  if (!DumpDirMounted()) {
     LOG(WARNING) << "Kernel does not support crash dumping";
     return false;
   }
diff --git a/crash-reporter/kernel_collector.h b/crash-reporter/kernel_collector.h
index 3899fb0..c8aedfe 100644
--- a/crash-reporter/kernel_collector.h
+++ b/crash-reporter/kernel_collector.h
@@ -62,6 +62,8 @@
   FRIEND_TEST(KernelCollectorTest, StripSensitiveDataSample);
   FRIEND_TEST(KernelCollectorTest, CollectOK);
 
+  virtual bool DumpDirMounted();
+
   bool LoadPreservedDump(std::string *contents);
   void StripSensitiveData(std::string *kernel_dump);
 
diff --git a/crash-reporter/kernel_collector_test.cc b/crash-reporter/kernel_collector_test.cc
index 654ed9d..d920fc6 100644
--- a/crash-reporter/kernel_collector_test.cc
+++ b/crash-reporter/kernel_collector_test.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "crash-reporter/kernel_collector.h"
+#include "crash-reporter/kernel_collector_test.h"
 
 #include <unistd.h>
 
@@ -43,7 +43,7 @@
   const FilePath &kcrash_file() const { return test_kcrash_; }
   const FilePath &test_crash_directory() const { return test_crash_directory_; }
 
-  KernelCollector collector_;
+  KernelCollectorMock collector_;
 
  private:
   void SetUp() override {
@@ -99,6 +99,7 @@
 
 TEST_F(KernelCollectorTest, EnableOK) {
   WriteStringToFile(kcrash_file(), "");
+  EXPECT_CALL(collector_, DumpDirMounted()).WillOnce(::testing::Return(true));
   ASSERT_TRUE(collector_.Enable());
   ASSERT_TRUE(collector_.is_enabled());
   ASSERT_TRUE(FindLog("Enabling kernel crash handling"));
diff --git a/crash-reporter/kernel_collector_test.h b/crash-reporter/kernel_collector_test.h
new file mode 100644
index 0000000..3219324
--- /dev/null
+++ b/crash-reporter/kernel_collector_test.h
@@ -0,0 +1,18 @@
+// Copyright 2014 The Chromium OS Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
+#define CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_
+
+#include "crash-reporter/kernel_collector.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+class KernelCollectorMock : public KernelCollector {
+ public:
+  MOCK_METHOD0(DumpDirMounted, bool());
+};
+
+#endif  // CRASH_REPORTER_KERNEL_COLLECTOR_TEST_H_