From: Sudeep Holla <sudeep.holla@arm.com> To: Sebastian Reichel <sebastian.reichel@collabora.co.uk>, linux-pm@vger.kernel.org, linux-arm-kernel@lists.infradead.org Cc: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>, Liviu Dudau <liviu.dudau@arm.com>, Sebastian Reichel <sre@kernel.org>, Sudeep Holla <sudeep.holla@arm.com> Subject: [PATCH] power: vexpress: fix corruption in notifier registration Date: Mon, 18 Jun 2018 12:40:07 +0100 [thread overview] Message-ID: <1529322007-4637-1-git-send-email-sudeep.holla@arm.com> (raw) Vexpress platforms provide two different restart handlers: SYS_REBOOT that restart the entire system, while DB_RESET only restarts the daughter board containing the CPU. DB_RESET is overridden by SYS_REBOOT if it exists. notifier_chain_register used in register_restart_handler by design allows notifier to be registered once only, however vexpress restart notifier can get registered twice. When this happen it corrupts list of notifiers, as result some notifiers can be not called on proper event, traverse on list can be cycled forever, and second unregister can access already freed memory. So far, since this was the only restart handler in the system, no issue was observed even if the same notifier was registered twice. However commit 6c5c0d48b686 ("watchdog: sp805: add restart handler") added support for SP805 restart handlers and since the system under test contains two vexpress restart and two SP805 watchdog instances, it was observed that during the boot traversing the restart handler list looped forever as there's a cycle in that list resulting in boot hang. This patch fixes the issues by ensuring that the notifier is installed only once. Cc: Sebastian Reichel <sre@kernel.org> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> --- drivers/power/reset/vexpress-poweroff.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 102f95a09460..cdc68eb06a91 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -35,6 +35,7 @@ static void vexpress_reset_do(struct device *dev, const char *what) } static struct device *vexpress_power_off_device; +static atomic_t vexpress_restart_nb_refcnt = ATOMIC_INIT(0); static void vexpress_power_off(void) { @@ -96,13 +97,16 @@ static const struct of_device_id vexpress_reset_of_match[] = { static int _vexpress_register_restart_handler(struct device *dev) { - int err; + int err = 0; vexpress_restart_device = dev; - err = register_restart_handler(&vexpress_restart_nb); - if (err) { - dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return err; + if (atomic_inc_return(&vexpress_restart_nb_refcnt) == 1) { + err = register_restart_handler(&vexpress_restart_nb); + if (err) { + dev_err(dev, "cannot register restart handler (err=%d)\n", err); + atomic_dec(&vexpress_restart_nb_refcnt); + return err; + } } device_create_file(dev, &dev_attr_active); -- 2.7.4
WARNING: multiple messages have this Message-ID (diff)
From: sudeep.holla@arm.com (Sudeep Holla) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] power: vexpress: fix corruption in notifier registration Date: Mon, 18 Jun 2018 12:40:07 +0100 [thread overview] Message-ID: <1529322007-4637-1-git-send-email-sudeep.holla@arm.com> (raw) Vexpress platforms provide two different restart handlers: SYS_REBOOT that restart the entire system, while DB_RESET only restarts the daughter board containing the CPU. DB_RESET is overridden by SYS_REBOOT if it exists. notifier_chain_register used in register_restart_handler by design allows notifier to be registered once only, however vexpress restart notifier can get registered twice. When this happen it corrupts list of notifiers, as result some notifiers can be not called on proper event, traverse on list can be cycled forever, and second unregister can access already freed memory. So far, since this was the only restart handler in the system, no issue was observed even if the same notifier was registered twice. However commit 6c5c0d48b686 ("watchdog: sp805: add restart handler") added support for SP805 restart handlers and since the system under test contains two vexpress restart and two SP805 watchdog instances, it was observed that during the boot traversing the restart handler list looped forever as there's a cycle in that list resulting in boot hang. This patch fixes the issues by ensuring that the notifier is installed only once. Cc: Sebastian Reichel <sre@kernel.org> Signed-off-by: Sudeep Holla <sudeep.holla@arm.com> --- drivers/power/reset/vexpress-poweroff.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/power/reset/vexpress-poweroff.c b/drivers/power/reset/vexpress-poweroff.c index 102f95a09460..cdc68eb06a91 100644 --- a/drivers/power/reset/vexpress-poweroff.c +++ b/drivers/power/reset/vexpress-poweroff.c @@ -35,6 +35,7 @@ static void vexpress_reset_do(struct device *dev, const char *what) } static struct device *vexpress_power_off_device; +static atomic_t vexpress_restart_nb_refcnt = ATOMIC_INIT(0); static void vexpress_power_off(void) { @@ -96,13 +97,16 @@ static const struct of_device_id vexpress_reset_of_match[] = { static int _vexpress_register_restart_handler(struct device *dev) { - int err; + int err = 0; vexpress_restart_device = dev; - err = register_restart_handler(&vexpress_restart_nb); - if (err) { - dev_err(dev, "cannot register restart handler (err=%d)\n", err); - return err; + if (atomic_inc_return(&vexpress_restart_nb_refcnt) == 1) { + err = register_restart_handler(&vexpress_restart_nb); + if (err) { + dev_err(dev, "cannot register restart handler (err=%d)\n", err); + atomic_dec(&vexpress_restart_nb_refcnt); + return err; + } } device_create_file(dev, &dev_attr_active); -- 2.7.4
next reply other threads:[~2018-06-18 11:40 UTC|newest] Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top 2018-06-18 11:40 Sudeep Holla [this message] 2018-06-18 11:40 ` [PATCH] power: vexpress: fix corruption in notifier registration Sudeep Holla 2018-06-18 14:56 ` Lorenzo Pieralisi 2018-06-18 14:56 ` Lorenzo Pieralisi 2018-06-18 15:51 ` Sudeep Holla 2018-06-18 15:51 ` Sudeep Holla 2018-06-18 15:54 ` [PATCH v2] " Sudeep Holla 2018-06-18 15:54 ` Sudeep Holla 2018-06-22 12:47 ` Sudeep Holla 2018-06-22 12:47 ` Sudeep Holla 2018-07-06 11:34 ` Sudeep Holla 2018-07-06 11:34 ` Sudeep Holla 2018-07-06 14:33 ` Sebastian Reichel 2018-07-06 14:33 ` Sebastian Reichel
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=1529322007-4637-1-git-send-email-sudeep.holla@arm.com \ --to=sudeep.holla@arm.com \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=linux-pm@vger.kernel.org \ --cc=liviu.dudau@arm.com \ --cc=lorenzo.pieralisi@arm.com \ --cc=sebastian.reichel@collabora.co.uk \ --cc=sre@kernel.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.