Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 77e9eeba authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Fix potential access to invalid memory during shutdown" into oc-dr1-dev

parents 0a9bae53 4fa10733
Loading
Loading
Loading
Loading
+36 −9
Original line number Original line Diff line number Diff line
@@ -6,7 +6,9 @@
#include <binder/IServiceManager.h>
#include <binder/IServiceManager.h>
#include <private/android/AHardwareBufferHelpers.h>
#include <private/android/AHardwareBufferHelpers.h>


#include <functional>
#include <memory>
#include <memory>
#include <mutex>


struct DvrHwcFrame {
struct DvrHwcFrame {
  android::dvr::ComposerView::Frame frame;
  android::dvr::ComposerView::Frame frame;
@@ -16,10 +18,15 @@ namespace {


class HwcCallback : public android::dvr::BnVrComposerCallback {
class HwcCallback : public android::dvr::BnVrComposerCallback {
 public:
 public:
  explicit HwcCallback(DvrHwcOnFrameCallback callback,
  using CallbackFunction = std::function<int(DvrHwcFrame*)>;
                       void* client_state);

  explicit HwcCallback(const CallbackFunction& callback);
  ~HwcCallback() override;
  ~HwcCallback() override;


  // Reset the callback. This needs to be done early to avoid use after free
  // accesses from binder thread callbacks.
  void Shutdown();

  std::unique_ptr<DvrHwcFrame> DequeueFrame();
  std::unique_ptr<DvrHwcFrame> DequeueFrame();


 private:
 private:
@@ -28,26 +35,41 @@ class HwcCallback : public android::dvr::BnVrComposerCallback {
      const android::dvr::ParcelableComposerFrame& frame,
      const android::dvr::ParcelableComposerFrame& frame,
      android::dvr::ParcelableUniqueFd* fence) override;
      android::dvr::ParcelableUniqueFd* fence) override;


  DvrHwcOnFrameCallback callback_;
  // Protects the |callback_| from uses from multiple threads. During shutdown
  void* client_state_;
  // there may be in-flight frame update events. In those cases the callback
  // access needs to be protected otherwise binder threads may access an invalid
  // callback.
  std::mutex mutex_;
  CallbackFunction callback_;


  HwcCallback(const HwcCallback&) = delete;
  HwcCallback(const HwcCallback&) = delete;
  void operator=(const HwcCallback&) = delete;
  void operator=(const HwcCallback&) = delete;
};
};


HwcCallback::HwcCallback(DvrHwcOnFrameCallback callback, void* client_state)
HwcCallback::HwcCallback(const CallbackFunction& callback)
    : callback_(callback), client_state_(client_state) {}
    : callback_(callback) {}


HwcCallback::~HwcCallback() {}
HwcCallback::~HwcCallback() {}


void HwcCallback::Shutdown() {
  std::lock_guard<std::mutex> guard(mutex_);
  callback_ = nullptr;
}

android::binder::Status HwcCallback::onNewFrame(
android::binder::Status HwcCallback::onNewFrame(
    const android::dvr::ParcelableComposerFrame& frame,
    const android::dvr::ParcelableComposerFrame& frame,
    android::dvr::ParcelableUniqueFd* fence) {
    android::dvr::ParcelableUniqueFd* fence) {
  std::lock_guard<std::mutex> guard(mutex_);

  if (!callback_) {
    fence->set_fence(android::base::unique_fd());
    return android::binder::Status::ok();
  }

  std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame());
  std::unique_ptr<DvrHwcFrame> dvr_frame(new DvrHwcFrame());
  dvr_frame->frame = frame.frame();
  dvr_frame->frame = frame.frame();


  fence->set_fence(android::base::unique_fd(callback_(client_state_,
  fence->set_fence(android::base::unique_fd(callback_(dvr_frame.release())));
                                                      dvr_frame.release())));
  return android::binder::Status::ok();
  return android::binder::Status::ok();
}
}


@@ -67,7 +89,8 @@ DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) {
  if (!client->composer.get())
  if (!client->composer.get())
    return nullptr;
    return nullptr;


  client->callback = new HwcCallback(callback, data);
  client->callback = new HwcCallback(std::bind(callback, data,
                                               std::placeholders::_1));
  android::binder::Status status = client->composer->registerObserver(
  android::binder::Status status = client->composer->registerObserver(
      client->callback);
      client->callback);
  if (!status.isOk())
  if (!status.isOk())
@@ -77,6 +100,10 @@ DvrHwcClient* dvrHwcClientCreate(DvrHwcOnFrameCallback callback, void* data) {
}
}


void dvrHwcClientDestroy(DvrHwcClient* client) {
void dvrHwcClientDestroy(DvrHwcClient* client) {
  // NOTE: Deleting DvrHwcClient* isn't enough since DvrHwcClient::callback is a
  // shared pointer that could be referenced from a binder thread. But the
  // client callback isn't valid past this calls so that needs to be reset.
  client->callback->Shutdown();
  delete client;
  delete client;
}
}