From 97f26ff6049a7fff5460cebe392ad1d699dc434c Mon Sep 17 00:00:00 2001
From: Mike Isely <isely@pobox.com>
Date: Mon, 7 Apr 2008 02:22:43 -0300
Subject: [PATCH] V4L/DVB (7712): pvrusb2: Close connect/disconnect race

If a disconnect happens before initialization is completed, the
pvrusb2 driver can accidentally touch dangling pointers.  The whole
initialization function must be protected by the big_lock, and once
inside that lock, the initialization function should abort if it is
discovered that a disconnect has already taken place.

Signed-off-by: Mike Isely <isely@pobox.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
---
 drivers/media/video/pvrusb2/pvrusb2-hdw.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/media/video/pvrusb2/pvrusb2-hdw.c b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
index 4f6bb58ca5fc8..f907a56c587d1 100644
--- a/drivers/media/video/pvrusb2/pvrusb2-hdw.c
+++ b/drivers/media/video/pvrusb2/pvrusb2-hdw.c
@@ -1854,10 +1854,19 @@ int pvr2_hdw_initialize(struct pvr2_hdw *hdw,
 			void *callback_data)
 {
 	LOCK_TAKE(hdw->big_lock); do {
+		if (hdw->flag_disconnected) {
+			/* Handle a race here: If we're already
+			   disconnected by this point, then give up.  If we
+			   get past this then we'll remain connected for
+			   the duration of initialization since the entire
+			   initialization sequence is now protected by the
+			   big_lock. */
+			break;
+		}
 		hdw->state_data = callback_data;
 		hdw->state_func = callback_func;
+		pvr2_hdw_setup(hdw);
 	} while (0); LOCK_GIVE(hdw->big_lock);
-	pvr2_hdw_setup(hdw);
 	return hdw->flag_init_ok;
 }
 
-- 
2.30.2