diff options
author | Vaibhav Jain <vaibhav@linux.ibm.com> | 2018-09-11 20:50:52 +0530 |
---|---|---|
committer | Stewart Smith <stewart@linux.ibm.com> | 2018-09-17 21:39:02 -0500 |
commit | 5f728c53d42c664234b45a33218ba522a6e8f216 (patch) | |
tree | e33325981f67886413195a5be22962bb809688b0 /core/opal.c | |
parent | 9d5b516f287096df429d4637a4f2dc8b7f933721 (diff) | |
download | skiboot-5f728c53d42c664234b45a33218ba522a6e8f216.zip skiboot-5f728c53d42c664234b45a33218ba522a6e8f216.tar.gz skiboot-5f728c53d42c664234b45a33218ba522a6e8f216.tar.bz2 |
opal: use for_each_safe to iterate over opal_syncers
Presently a fault will happen in opal_sync_host_reboot if a callback
tries to remove itself from the opal_syncers list by calling
opal_del_host_sync_notifier.
This happens as iteration over opal_syncers is done using the
list_for_each() which doesn't preserve list_node->next. So when
the current opal_syncers callback removes itself from the list, current
node contents are lost and current_node->next pointer is rendered
invalid.
To fix this we simply switch from list_for_each() to
list_for_each_safe() which keeps the current_node->next cached hence
even if the current node is freed, iteration over subsequent nodes can
still continue.
Signed-off-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Reviewed-by: Vasant Hegde <hegdevasant@linux.vnet.ibm.com>
Signed-off-by: Stewart Smith <stewart@linux.ibm.com>
Diffstat (limited to 'core/opal.c')
-rw-r--r-- | core/opal.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/core/opal.c b/core/opal.c index 7ffca9c..63a0851 100644 --- a/core/opal.c +++ b/core/opal.c @@ -692,10 +692,10 @@ void opal_del_host_sync_notifier(bool (*notify)(void *data)) */ static int64_t opal_sync_host_reboot(void) { - struct opal_sync_entry *ent; + struct opal_sync_entry *ent, *nxt; bool ret = true; - list_for_each(&opal_syncers, ent, link) + list_for_each_safe(&opal_syncers, ent, nxt, link) ret &= ent->notify(ent->data); if (ret) |