ssl_key_logger_impl.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  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. #include "net/ssl/ssl_key_logger_impl.h"
  5. #include <stdio.h>
  6. #include <algorithm>
  7. #include <utility>
  8. #include "base/bind.h"
  9. #include "base/files/file_util.h"
  10. #include "base/files/scoped_file.h"
  11. #include "base/location.h"
  12. #include "base/logging.h"
  13. #include "base/memory/ref_counted.h"
  14. #include "base/sequence_checker.h"
  15. #include "base/synchronization/lock.h"
  16. #include "base/task/sequenced_task_runner.h"
  17. #include "base/task/task_traits.h"
  18. #include "base/task/thread_pool.h"
  19. #include "base/thread_annotations.h"
  20. namespace net {
  21. namespace {
  22. // Bound the number of outstanding writes to bound memory usage. Some
  23. // antiviruses point this at a pipe and then read too slowly. See
  24. // https://crbug.com/566951 and https://crbug.com/914880.
  25. static constexpr size_t kMaxOutstandingLines = 512;
  26. } // namespace
  27. // An object which performs the blocking file operations on a background
  28. // SequencedTaskRunner.
  29. class SSLKeyLoggerImpl::Core
  30. : public base::RefCountedThreadSafe<SSLKeyLoggerImpl::Core> {
  31. public:
  32. Core() {
  33. DETACH_FROM_SEQUENCE(sequence_checker_);
  34. // That the user explicitly asked for debugging information would suggest
  35. // waiting to flush these to disk, but some buggy antiviruses point this at
  36. // a pipe and hang, so we avoid blocking shutdown. If writing to a real
  37. // file, writes should complete quickly enough that this does not matter.
  38. task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
  39. {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN});
  40. }
  41. Core(const Core&) = delete;
  42. Core& operator=(const Core&) = delete;
  43. void SetFile(base::File file) {
  44. file_.reset(base::FileToFILE(std::move(file), "a"));
  45. if (!file_)
  46. DVLOG(1) << "Could not adopt file";
  47. }
  48. void OpenFile(const base::FilePath& path) {
  49. task_runner_->PostTask(FROM_HERE,
  50. base::BindOnce(&Core::OpenFileImpl, this, path));
  51. }
  52. void WriteLine(const std::string& line) {
  53. bool was_empty;
  54. {
  55. base::AutoLock lock(lock_);
  56. was_empty = buffer_.empty();
  57. if (buffer_.size() < kMaxOutstandingLines) {
  58. buffer_.push_back(line);
  59. } else {
  60. lines_dropped_ = true;
  61. }
  62. }
  63. if (was_empty) {
  64. task_runner_->PostTask(FROM_HERE, base::BindOnce(&Core::Flush, this));
  65. }
  66. }
  67. private:
  68. friend class base::RefCountedThreadSafe<Core>;
  69. ~Core() = default;
  70. void OpenFileImpl(const base::FilePath& path) {
  71. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  72. DCHECK(!file_);
  73. file_.reset(base::OpenFile(path, "a"));
  74. if (!file_)
  75. DVLOG(1) << "Could not open " << path.value();
  76. }
  77. void Flush() {
  78. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  79. bool lines_dropped = false;
  80. std::vector<std::string> buffer;
  81. {
  82. base::AutoLock lock(lock_);
  83. std::swap(lines_dropped, lines_dropped_);
  84. std::swap(buffer, buffer_);
  85. }
  86. if (file_) {
  87. for (const auto& line : buffer) {
  88. fprintf(file_.get(), "%s\n", line.c_str());
  89. }
  90. if (lines_dropped) {
  91. fprintf(file_.get(), "# Some lines were dropped due to slow writes.\n");
  92. }
  93. fflush(file_.get());
  94. }
  95. }
  96. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  97. base::ScopedFILE file_;
  98. SEQUENCE_CHECKER(sequence_checker_);
  99. base::Lock lock_;
  100. bool lines_dropped_ GUARDED_BY(lock_) = false;
  101. std::vector<std::string> buffer_ GUARDED_BY(lock_);
  102. };
  103. SSLKeyLoggerImpl::SSLKeyLoggerImpl(const base::FilePath& path)
  104. : core_(base::MakeRefCounted<Core>()) {
  105. core_->OpenFile(path);
  106. }
  107. SSLKeyLoggerImpl::SSLKeyLoggerImpl(base::File file)
  108. : core_(base::MakeRefCounted<Core>()) {
  109. core_->SetFile(std::move(file));
  110. }
  111. SSLKeyLoggerImpl::~SSLKeyLoggerImpl() = default;
  112. void SSLKeyLoggerImpl::WriteLine(const std::string& line) {
  113. core_->WriteLine(line);
  114. }
  115. } // namespace net