Blob Blame History Raw
From: Takashi Iwai <tiwai@suse.de>
Subject: kABI workaround for v4l2_fh
Patch-mainline: Never, kABI workaround
References: CVE-2019-9458 bsc#1168295

The patch
  patches.suse/media-v4l-event-Prevent-freeing-event-subscriptions-.patch
introduced a new field subscribe_lock into v4l2_fh object, and this
breaks kABI.  Unfortunately we cannot use a standard technique due to the
embedded nature of this object.

Convert to a global lock for avoiding the kABI breakage, as a cost of a
slight performance degration (which should be negligible).

Signed-off-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/media/v4l2-core/v4l2-event.c |   10 +++++-----
 drivers/media/v4l2-core/v4l2-fh.c    |    5 +++--
 include/media/v4l2-fh.h              |    5 ++---
 3 files changed, 10 insertions(+), 10 deletions(-)

--- a/drivers/media/v4l2-core/v4l2-event.c
+++ b/drivers/media/v4l2-core/v4l2-event.c
@@ -197,7 +197,7 @@ static void __v4l2_event_unsubscribe(str
 	struct v4l2_fh *fh = sev->fh;
 	unsigned int i;
 
-	lockdep_assert_held(&fh->subscribe_lock);
+	lockdep_assert_held(&v4l2_fh_subscribe_lock);
 	assert_spin_locked(&fh->vdev->fh_lock);
 
 	/* Remove any pending events for this subscription */
@@ -235,7 +235,7 @@ int v4l2_event_subscribe(struct v4l2_fh
 	sev->ops = ops;
 	sev->elems = elems;
 
-	mutex_lock(&fh->subscribe_lock);
+	mutex_lock(&v4l2_fh_subscribe_lock);
 
 	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 	found_ev = v4l2_event_subscribed(fh, sub->type, sub->id);
@@ -255,7 +255,7 @@ int v4l2_event_subscribe(struct v4l2_fh
 		}
 	}
 
-	mutex_unlock(&fh->subscribe_lock);
+	mutex_unlock(&v4l2_fh_subscribe_lock);
 
 	return ret;
 }
@@ -295,7 +295,7 @@ int v4l2_event_unsubscribe(struct v4l2_f
 		return 0;
 	}
 
-	mutex_lock(&fh->subscribe_lock);
+	mutex_lock(&v4l2_fh_subscribe_lock);
 
 	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 
@@ -308,7 +308,7 @@ int v4l2_event_unsubscribe(struct v4l2_f
 	if (sev && sev->ops && sev->ops->del)
 		sev->ops->del(sev);
 
-	mutex_unlock(&fh->subscribe_lock);
+	mutex_unlock(&v4l2_fh_subscribe_lock);
 
 	kfree(sev);
 
--- a/drivers/media/v4l2-core/v4l2-fh.c
+++ b/drivers/media/v4l2-core/v4l2-fh.c
@@ -26,6 +26,9 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mc.h>
 
+/* FIXME: converted to a global lock due to kABI compatibility */
+DEFINE_MUTEX(v4l2_fh_subscribe_lock);
+
 void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
 {
 	fh->vdev = vdev;
@@ -45,7 +48,6 @@ 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);
 
@@ -91,7 +93,6 @@ 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,8 +37,6 @@ 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
@@ -54,7 +52,6 @@ struct v4l2_fh {
 
 	/* Events */
 	wait_queue_head_t	wait;
-	struct mutex		subscribe_lock;
 	struct list_head	subscribed;
 	struct list_head	available;
 	unsigned int		navailable;
@@ -65,6 +62,8 @@ struct v4l2_fh {
 #endif
 };
 
+extern struct mutex v4l2_fh_subscribe_lock;
+
 /**
  * v4l2_fh_init - Initialise the file handle.
  *