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

Commit 0e2e4435 authored by Daniel Nicoara's avatar Daniel Nicoara Committed by android-build-merger
Browse files

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

am: 77e9eeba

Change-Id: I5b5703ab3b70755d3f8b8e2674c7c32ce0e1c05b
parents 18dcaf17 77e9eeba
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;
}
}