From e7ba7974a2030d6c07c423cafda5d32ef1c59481 Mon Sep 17 00:00:00 2001 From: Ernest Borowski Date: Fri, 26 Apr 2019 17:21:55 +0200 Subject: [PATCH] Manage callbacks lifetime to fix potential use after free Askuser notification has callbacks in: a) timer for delaying exit when home button is pressed b) transitions for changing popup message to next request Change-Id: I0326e625a7b91115b67096682e355fc0444faf3e Signed-off-by: Ernest Borowski --- src/notification-daemon/ui/PopupCheck.h | 63 +++++++++++++++++++++------------ src/notification-daemon/ui/Popupper.cpp | 18 ++++++++-- src/notification-daemon/ui/Popupper.h | 4 ++- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/notification-daemon/ui/PopupCheck.h b/src/notification-daemon/ui/PopupCheck.h index 7f7020b..e6a3dbc 100644 --- a/src/notification-daemon/ui/PopupCheck.h +++ b/src/notification-daemon/ui/PopupCheck.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 - 2018 Samsung Electronics Co. + * Copyright (c) 2017 - 2019 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,6 +22,7 @@ #pragma once +#include #include #include @@ -68,12 +69,14 @@ public: PopupCheck *popupCheck = static_cast(data); popupCheck->changePopupMessage(); popupCheck->resetPopupContentState(); + (void)popupCheck->m_transitOutPtr.release(); } static void enableButtonsAfterTransitionCallback(void* data, Elm_Transit*) { PopupCheck *popupCheck = static_cast(data); elm_object_disabled_set(popupCheck->m_denyButton, EINA_FALSE); elm_object_disabled_set(popupCheck->m_allowButton, EINA_FALSE); + (void)popupCheck->m_transitPtr.release(); } virtual Evas_Object* getAnimatedLayout() = 0; @@ -91,13 +94,12 @@ public: m_msg = msg; double animation_length_in_sec = 0.075 * 2; - Elm_Transit *transitOut = elm_transit_add();// fade out - Elm_Transit *transitBetween = elm_transit_add();// slightly delay for changing message - Elm_Transit *transit = elm_transit_add();// fade in - if (!transitOut || !transitBetween || !transit) { // just change text without transitions - elm_transit_del(transitOut); - elm_transit_del(transitBetween); - elm_transit_del(transit); + m_transitOutPtr.reset(elm_transit_add()); // fade out + m_transitBetweenPtr.reset(elm_transit_add()); // slightly delay for changing message + m_transitPtr.reset(elm_transit_add()); // fade in + if (!m_transitOutPtr || !m_transitBetweenPtr || !m_transitPtr) { + // just change text without transitions + ALOGE("Failed to initialize transition"); changePopupMessageCallback(this, NULL); return true; } @@ -105,30 +107,34 @@ public: elm_object_disabled_set(m_denyButton, EINA_TRUE); elm_object_disabled_set(m_allowButton, EINA_TRUE); - elm_transit_effect_wipe_add(transitOut, + elm_transit_effect_wipe_add(m_transitOutPtr.get(), ELM_TRANSIT_EFFECT_WIPE_TYPE_HIDE, ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT); - elm_transit_duration_set(transitOut, animation_length_in_sec); - elm_transit_tween_mode_set(transitOut, ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL); + elm_transit_duration_set(m_transitOutPtr.get(), animation_length_in_sec); + elm_transit_tween_mode_set(m_transitOutPtr.get(), ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL); - elm_transit_object_add(transitBetween, layout); - elm_transit_effect_translation_add(transitBetween, -10000, -10000, -10000, -10000); - elm_transit_duration_set(transitBetween, animation_length_in_sec); + elm_transit_object_add(m_transitBetweenPtr.get(), layout); + elm_transit_effect_translation_add(m_transitBetweenPtr.get(), -10000, -10000, -10000, -10000); + elm_transit_duration_set(m_transitBetweenPtr.get(), animation_length_in_sec); - elm_transit_object_add(transit, layout); - elm_transit_effect_wipe_add(transit, + elm_transit_object_add(m_transitPtr.get(), layout); + elm_transit_effect_wipe_add(m_transitPtr.get(), ELM_TRANSIT_EFFECT_WIPE_TYPE_SHOW, ELM_TRANSIT_EFFECT_WIPE_DIR_LEFT); - elm_transit_tween_mode_set(transit, ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL); - elm_transit_duration_set(transit, animation_length_in_sec); + elm_transit_tween_mode_set(m_transitPtr.get(), ELM_TRANSIT_TWEEN_MODE_SINUSOIDAL); + elm_transit_duration_set(m_transitPtr.get(), animation_length_in_sec); - elm_transit_chain_transit_add(transitOut, transitBetween); - elm_transit_chain_transit_add(transitBetween, transit); - elm_transit_del_cb_set(transitOut, changePopupMessageCallback, this); - elm_transit_del_cb_set(transit, enableButtonsAfterTransitionCallback, this); - elm_transit_go(transitOut); + elm_transit_chain_transit_add(m_transitOutPtr.get(), m_transitBetweenPtr.get()); + elm_transit_chain_transit_add(m_transitBetweenPtr.get(), m_transitPtr.get()); + elm_transit_del_cb_set(m_transitOutPtr.get(), changePopupMessageCallback, this); + elm_transit_del_cb_set(m_transitPtr.get(), enableButtonsAfterTransitionCallback, this); + elm_transit_del_cb_set(m_transitBetweenPtr.get(), [] (void* data, Elm_Transit*) { + PopupCheck *popupCheck = static_cast(data); + (void)popupCheck->m_transitBetweenPtr.release(); + }, this); + elm_transit_go(m_transitOutPtr.get()); return true; } @@ -138,6 +144,17 @@ public: protected: Evas_Object *m_checkBox = nullptr; + struct transitionPtrDeleter { + void operator () (Elm_Transit* et) { + if (et) { + elm_transit_del_cb_set(et, nullptr, nullptr); + elm_transit_del(et); + } + } + }; + std::unique_ptr m_transitPtr; + std::unique_ptr m_transitOutPtr; + std::unique_ptr m_transitBetweenPtr; }; } /* namespace Notification */ diff --git a/src/notification-daemon/ui/Popupper.cpp b/src/notification-daemon/ui/Popupper.cpp index 56b77ff..6f7c31f 100644 --- a/src/notification-daemon/ui/Popupper.cpp +++ b/src/notification-daemon/ui/Popupper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 - 2018 Samsung Electronics Co. + * Copyright (c) 2017 - 2019 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -136,9 +136,11 @@ Eina_Bool Popupper::hwKeyClickedCb(void *data, int type, void *event) ALOGD("Respond as deny once."); if (!strcmp("XF86Back", ev->key)) delay = 0; - ecore_timer_add(delay, + runner->closeDelayTimer(false); + runner->m_ecoreDelayExitPtr = ecore_timer_add(delay, [](void *data) -> Eina_Bool { Popupper *runner = static_cast(data); + runner->m_ecoreDelayExitPtr = nullptr; runner->respondToRest(NResponseType::None); return ECORE_CALLBACK_CANCEL; }, @@ -148,7 +150,17 @@ Eina_Bool Popupper::hwKeyClickedCb(void *data, int type, void *event) } Popupper::~Popupper() -{} +{ + closeDelayTimer(); +} + +void Popupper::closeDelayTimer(bool sendRequestResponses) { + if (m_ecoreDelayExitPtr) { + ecore_timer_del(m_ecoreDelayExitPtr); + if (sendRequestResponses) + respondToRest(NResponseType::None); + } +} void Popupper::initialize() { diff --git a/src/notification-daemon/ui/Popupper.h b/src/notification-daemon/ui/Popupper.h index f9cb337..fbce729 100644 --- a/src/notification-daemon/ui/Popupper.h +++ b/src/notification-daemon/ui/Popupper.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017 - 2018 Samsung Electronics Co. + * Copyright (c) 2017 - 2019 Samsung Electronics Co. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -63,11 +63,13 @@ private: static Eina_Bool hwKeyClickedCb(void *data, int type, void *event); void buttonAnswer(IAnswerable::Button button); + void closeDelayTimer(bool sendRequestResponses = true); void respondToRest(NResponseType response); void show(); PopupHandler m_popupResponseHandler; + Ecore_Timer *m_ecoreDelayExitPtr = nullptr; Evas_Object *m_win = nullptr; std::unique_ptr m_elementPtr; std::unique_ptr m_answerablePtr; -- 2.7.4