From 54f1a7a72c69fd58be8199453c250dd077abde48 Mon Sep 17 00:00:00 2001
From: "ken@mvista.com" <ken@mvista.com>
Date: Mon, 7 Mar 2005 17:52:53 -0800
Subject: [PATCH] [PATCH] drivers/char/lp.c race fix

In lp_write(), copy_from_user() is called to copy data into a statically
allocated kernel buffer before down_interruptible() is called.  If a second
thread of execution comes in between the copy_from_user() and the
down_interruptible() calls, silent data corruption could result.

Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
---
 drivers/char/lp.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 92a54cb659d6..78a9e7d4bc25 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -314,12 +314,14 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
 	if (copy_size > LP_BUFFER_SIZE)
 		copy_size = LP_BUFFER_SIZE;
 
-	if (copy_from_user (kbuf, buf, copy_size))
-		return -EFAULT;
-
 	if (down_interruptible (&lp_table[minor].port_mutex))
 		return -EINTR;
 
+	if (copy_from_user (kbuf, buf, copy_size)) {
+		retv = -EFAULT;
+		goto out_unlock;
+	}
+
  	/* Claim Parport or sleep until it becomes available
  	 */
 	lp_claim_parport_or_block (&lp_table[minor]);
@@ -398,7 +400,7 @@ static ssize_t lp_write(struct file * file, const char __user * buf,
 		lp_table[minor].current_mode = IEEE1284_MODE_COMPAT;
 		lp_release_parport (&lp_table[minor]);
 	}
-
+out_unlock:
 	up (&lp_table[minor].port_mutex);
 
  	return retv;
-- 
2.30.9