From: Greg Kroah-Hartman Date: Wed, 3 Oct 2018 16:37:59 +0000 (-0700) Subject: 4.14-stable patches X-Git-Tag: v4.18.12~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5ac9b6e29e781356f4f08bb5eb2a55850d483c48;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch --- diff --git a/queue-4.14/media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch b/queue-4.14/media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch new file mode 100644 index 00000000000..d0df81d23de --- /dev/null +++ b/queue-4.14/media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch @@ -0,0 +1,169 @@ +From ad608fbcf166fec809e402d548761768f602702c Mon Sep 17 00:00:00 2001 +From: Sakari Ailus +Date: Tue, 11 Sep 2018 05:32:37 -0400 +Subject: media: v4l: event: Prevent freeing event subscriptions while accessed + +From: Sakari Ailus + +commit ad608fbcf166fec809e402d548761768f602702c upstream. + +The event subscriptions are added to the subscribed event list while +holding a spinlock, but that lock is subsequently released while still +accessing the subscription object. This makes it possible to unsubscribe +the event --- and freeing the subscription object's memory --- while +the subscription object is simultaneously accessed. + +Prevent this by adding a mutex to serialise the event subscription and +unsubscription. This also gives a guarantee to the callback ops that the +add op has returned before the del op is called. + +This change also results in making the elems field less special: +subscriptions are only added to the event list once they are fully +initialised. + +Signed-off-by: Sakari Ailus +Reviewed-by: Hans Verkuil +Reviewed-by: Laurent Pinchart +Cc: stable@vger.kernel.org # for 4.14 and up +Fixes: c3b5b0241f62 ("V4L/DVB: V4L: Events: Add backend") +Signed-off-by: Mauro Carvalho Chehab +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/media/v4l2-core/v4l2-event.c | 38 ++++++++++++++++++----------------- + drivers/media/v4l2-core/v4l2-fh.c | 2 + + include/media/v4l2-fh.h | 4 +++ + 3 files changed, 26 insertions(+), 18 deletions(-) + +--- a/drivers/media/v4l2-core/v4l2-event.c ++++ b/drivers/media/v4l2-core/v4l2-event.c +@@ -115,14 +115,6 @@ static void __v4l2_event_queue_fh(struct + if (sev == NULL) + return; + +- /* +- * If the event has been added to the fh->subscribed list, but its +- * add op has not completed yet elems will be 0, treat this as +- * not being subscribed. +- */ +- if (!sev->elems) +- return; +- + /* Increase event sequence number on fh. */ + fh->sequence++; + +@@ -208,6 +200,7 @@ int v4l2_event_subscribe(struct v4l2_fh + struct v4l2_subscribed_event *sev, *found_ev; + unsigned long flags; + unsigned i; ++ int ret = 0; + + if (sub->type == V4L2_EVENT_ALL) + return -EINVAL; +@@ -226,31 +219,36 @@ int v4l2_event_subscribe(struct v4l2_fh + sev->flags = sub->flags; + sev->fh = fh; + sev->ops = ops; ++ sev->elems = elems; ++ ++ mutex_lock(&fh->subscribe_lock); + + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + found_ev = v4l2_event_subscribed(fh, sub->type, sub->id); +- if (!found_ev) +- list_add(&sev->list, &fh->subscribed); + spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); + + if (found_ev) { ++ /* Already listening */ + kvfree(sev); +- return 0; /* Already listening */ ++ goto out_unlock; + } + + if (sev->ops && sev->ops->add) { +- int ret = sev->ops->add(sev, elems); ++ ret = sev->ops->add(sev, elems); + if (ret) { +- sev->ops = NULL; +- v4l2_event_unsubscribe(fh, sub); +- return ret; ++ kvfree(sev); ++ goto out_unlock; + } + } + +- /* Mark as ready for use */ +- sev->elems = elems; ++ spin_lock_irqsave(&fh->vdev->fh_lock, flags); ++ list_add(&sev->list, &fh->subscribed); ++ spin_unlock_irqrestore(&fh->vdev->fh_lock, flags); ++ ++out_unlock: ++ mutex_unlock(&fh->subscribe_lock); + +- return 0; ++ return ret; + } + EXPORT_SYMBOL_GPL(v4l2_event_subscribe); + +@@ -289,6 +287,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + return 0; + } + ++ mutex_lock(&fh->subscribe_lock); ++ + spin_lock_irqsave(&fh->vdev->fh_lock, flags); + + sev = v4l2_event_subscribed(fh, sub->type, sub->id); +@@ -306,6 +306,8 @@ int v4l2_event_unsubscribe(struct v4l2_f + if (sev && sev->ops && sev->ops->del) + sev->ops->del(sev); + ++ mutex_unlock(&fh->subscribe_lock); ++ + kvfree(sev); + + return 0; +--- a/drivers/media/v4l2-core/v4l2-fh.c ++++ b/drivers/media/v4l2-core/v4l2-fh.c +@@ -45,6 +45,7 @@ void v4l2_fh_init(struct v4l2_fh *fh, st + INIT_LIST_HEAD(&fh->available); + INIT_LIST_HEAD(&fh->subscribed); + fh->sequence = -1; ++ mutex_init(&fh->subscribe_lock); + } + EXPORT_SYMBOL_GPL(v4l2_fh_init); + +@@ -90,6 +91,7 @@ void v4l2_fh_exit(struct v4l2_fh *fh) + return; + v4l_disable_media_source(fh->vdev); + v4l2_event_unsubscribe_all(fh); ++ mutex_destroy(&fh->subscribe_lock); + fh->vdev = NULL; + } + EXPORT_SYMBOL_GPL(v4l2_fh_exit); +--- a/include/media/v4l2-fh.h ++++ b/include/media/v4l2-fh.h +@@ -37,10 +37,13 @@ struct v4l2_ctrl_handler; + * @prio: priority of the file handler, as defined by &enum v4l2_priority + * + * @wait: event' s wait queue ++ * @subscribe_lock: serialise changes to the subscribed list; guarantee that ++ * the add and del event callbacks are orderly called + * @subscribed: list of subscribed events + * @available: list of events waiting to be dequeued + * @navailable: number of available events at @available list + * @sequence: event sequence number ++ * + * @m2m_ctx: pointer to &struct v4l2_m2m_ctx + */ + struct v4l2_fh { +@@ -51,6 +54,7 @@ struct v4l2_fh { + + /* Events */ + wait_queue_head_t wait; ++ struct mutex subscribe_lock; + struct list_head subscribed; + struct list_head available; + unsigned int navailable; diff --git a/queue-4.14/series b/queue-4.14/series index 0131c94aea8..fdbf9441459 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -136,3 +136,4 @@ arm-arm64-smccc-1.1-handle-function-result-as-parameters.patch i2c-i801-allow-acpi-aml-access-i-o-ports-not-reserved-for-smbus.patch x86-pti-fix-section-mismatch-warning-error.patch arm64-kvm-sanitize-pstate.m-when-being-set-from-userspace.patch +media-v4l-event-prevent-freeing-event-subscriptions-while-accessed.patch