public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
To: linux-kernel@vger.kernel.org
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
	stable@vger.kernel.org, Ian Abbott <abbotti@mev.co.uk>,
	Ben Hutchings <ben@decadent.org.uk>,
	Yijing Wang <wangyijing@huawei.com>
Subject: [PATCH 3.4 33/44] staging: comedi: fix a race between do_cmd_ioctl() and read/write
Date: Mon,  7 Jul 2014 17:07:23 -0700	[thread overview]
Message-ID: <20140707235859.631290823@linuxfoundation.org> (raw)
In-Reply-To: <20140707235858.652771077@linuxfoundation.org>

3.4-stable review patch.  If anyone has any objections, please let me know.

------------------

From: Ian Abbott <abbotti@mev.co.uk>

commit 4b18f08be01a7b3c7b6df497137b6e3cb28adaa3 upstream.

`do_cmd_ioctl()` is called with the comedi device's mutex locked to
process the `COMEDI_CMD` ioctl to set up comedi's asynchronous command
handling on a comedi subdevice.  `comedi_read()` and `comedi_write()`
are the `read` and `write` handlers for the comedi device, but do not
lock the mutex (for performance reasons, as some things can hold the
mutex for quite a long time).

There is a race condition if `comedi_read()` or `comedi_write()` is
running at the same time and for the same file object and comedi
subdevice as `do_cmd_ioctl()`.  `do_cmd_ioctl()` sets the subdevice's
`busy` pointer to the file object way before it sets the `SRF_RUNNING` flag
in the subdevice's `runflags` member.  `comedi_read() and
`comedi_write()` check the subdevice's `busy` pointer is pointing to the
current file object, then if the `SRF_RUNNING` flag is not set, will call
`do_become_nonbusy()` to shut down the asyncronous command.  Bad things
can happen if the asynchronous command is being shutdown and set up at
the same time.

To prevent the race, don't set the `busy` pointer until
after the `SRF_RUNNING` flag has been set.  Also, make sure the mutex is
held in `comedi_read()` and `comedi_write()` while calling
`do_become_nonbusy()` in order to avoid moving the race condition to a
point within that function.

Change some error handling `goto cleanup` statements in `do_cmd_ioctl()`
to simple `return -ERRFOO` statements as a result of changing when the
`busy` pointer is set.

Signed-off-by: Ian Abbott <abbotti@mev.co.uk>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: Yijing Wang <wangyijing@huawei.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

---
 drivers/staging/comedi/comedi_fops.c |   25 +++++++++++++++----------
 1 file changed, 15 insertions(+), 10 deletions(-)

--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1078,22 +1078,19 @@ static int do_cmd_ioctl(struct comedi_de
 		DPRINTK("subdevice busy\n");
 		return -EBUSY;
 	}
-	s->busy = file;
 
 	/* make sure channel/gain list isn't too long */
 	if (user_cmd.chanlist_len > s->len_chanlist) {
 		DPRINTK("channel/gain list too long %u > %d\n",
 			user_cmd.chanlist_len, s->len_chanlist);
-		ret = -EINVAL;
-		goto cleanup;
+		return -EINVAL;
 	}
 
 	/* make sure channel/gain list isn't too short */
 	if (user_cmd.chanlist_len < 1) {
 		DPRINTK("channel/gain list too short %u < 1\n",
 			user_cmd.chanlist_len);
-		ret = -EINVAL;
-		goto cleanup;
+		return -EINVAL;
 	}
 
 	async->cmd = user_cmd;
@@ -1103,8 +1100,7 @@ static int do_cmd_ioctl(struct comedi_de
 	    kmalloc(async->cmd.chanlist_len * sizeof(int), GFP_KERNEL);
 	if (!async->cmd.chanlist) {
 		DPRINTK("allocation failed\n");
-		ret = -ENOMEM;
-		goto cleanup;
+		return -ENOMEM;
 	}
 
 	if (copy_from_user(async->cmd.chanlist, user_cmd.chanlist,
@@ -1156,6 +1152,9 @@ static int do_cmd_ioctl(struct comedi_de
 
 	comedi_set_subdevice_runflags(s, ~0, SRF_USER | SRF_RUNNING);
 
+	/* set s->busy _after_ setting SRF_RUNNING flag to avoid race with
+	 * comedi_read() or comedi_write() */
+	s->busy = file;
 	ret = s->do_cmd(dev, s);
 	if (ret == 0)
 		return 0;
@@ -1658,6 +1657,7 @@ static ssize_t comedi_write(struct file
 
 		if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
 			if (count == 0) {
+				mutex_lock(&dev->mutex);
 				if (comedi_get_subdevice_runflags(s) &
 					SRF_ERROR) {
 					retval = -EPIPE;
@@ -1665,6 +1665,7 @@ static ssize_t comedi_write(struct file
 					retval = 0;
 				}
 				do_become_nonbusy(dev, s);
+				mutex_unlock(&dev->mutex);
 			}
 			break;
 		}
@@ -1779,6 +1780,7 @@ static ssize_t comedi_read(struct file *
 
 		if (n == 0) {
 			if (!(comedi_get_subdevice_runflags(s) & SRF_RUNNING)) {
+				mutex_lock(&dev->mutex);
 				do_become_nonbusy(dev, s);
 				if (comedi_get_subdevice_runflags(s) &
 				    SRF_ERROR) {
@@ -1786,6 +1788,7 @@ static ssize_t comedi_read(struct file *
 				} else {
 					retval = 0;
 				}
+				mutex_unlock(&dev->mutex);
 				break;
 			}
 			if (file->f_flags & O_NONBLOCK) {
@@ -1823,9 +1826,11 @@ static ssize_t comedi_read(struct file *
 		buf += n;
 		break;		/* makes device work like a pipe */
 	}
-	if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING)) &&
-	    async->buf_read_count - async->buf_write_count == 0) {
-		do_become_nonbusy(dev, s);
+	if (!(comedi_get_subdevice_runflags(s) & (SRF_ERROR | SRF_RUNNING))) {
+		mutex_lock(&dev->mutex);
+		if (async->buf_read_count - async->buf_write_count == 0)
+			do_become_nonbusy(dev, s);
+		mutex_unlock(&dev->mutex);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&async->wait_head, &wait);



  parent reply	other threads:[~2014-07-08  0:09 UTC|newest]

Thread overview: 45+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-08  0:06 [PATCH 3.4 00/44] 3.4.98-stable review Greg Kroah-Hartman
2014-07-08  0:06 ` [PATCH 3.4 01/44] ibmvscsi: Abort init sequence during error recovery Greg Kroah-Hartman
2014-07-08  0:06 ` [PATCH 3.4 02/44] xhci: correct burst count field for isoc transfers on 1.0 xhci hosts Greg Kroah-Hartman
2014-07-08  0:06 ` [PATCH 3.4 03/44] xhci: Fix runtime suspended xhci from blocking system suspend Greg Kroah-Hartman
2014-07-08  0:06 ` [PATCH 3.4 05/44] USB: option: add device ID for SpeedUp SU9800 usb 3g modem Greg Kroah-Hartman
2014-07-08  0:06 ` [PATCH 3.4 07/44] USB: ftdi_sio: fix null deref at port probe Greg Kroah-Hartman
2014-07-08  0:06 ` [PATCH 3.4 09/44] rt2x00: disable TKIP on USB Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 10/44] rt2x00: fix rfkill regression on rt2500pci Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 11/44] mtd: pxa3xx_nand: make the driver work on big-endian systems Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 12/44] drm/radeon: only apply hdmi bpc pll flags when encoder mode is hdmi Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 13/44] drm/radeon: fix typo in radeon_connector_is_dp12_capable() Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 14/44] drm/radeon/atom: fix dithering on certain panels Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 15/44] drm/vmwgfx: Fix incorrect write to read-only register v2: Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 16/44] Bluetooth: Fix SSP acceptor just-works confirmation without MITM Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 17/44] Bluetooth: Remove unused hci_le_ltk_reply() Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 18/44] mac80211: dont check netdev state for debugfs read/write Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 19/44] ARM: OMAP2+: Fix parser-bug in platform muxing code Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 21/44] CIFS: fix mount failure with broken pathnames when smb3 mount with mapchars option Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 22/44] KVM: x86: Increase the number of fixed MTRR regs to 10 Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 23/44] KVM: x86: preserve the high 32-bits of the PAT register Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 24/44] nfsd: fix rare symlink decoding bug Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 25/44] tools: ffs-test: fix header values endianess Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 26/44] md: flush writes before starting a recovery Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 27/44] sym53c8xx_2: Set DID_REQUEUE return code when aborting squeue Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 28/44] acpi/video_detect: blacklist samsung x360 Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 29/44] ACPI / video: Add "Asus UL30VT" to ACPI video detect blacklist Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 30/44] ACPI / video: Add "Asus UL30A" " Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 31/44] ACPI video: ignore BIOS initial backlight value for HP 1000 Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 32/44] staging: comedi: das08: Correct AI encoding for das08jr-16-ao Greg Kroah-Hartman
2014-07-08  0:07 ` Greg Kroah-Hartman [this message]
2014-07-08  0:07 ` [PATCH 3.4 34/44] staging: wlags49_h2: buffer overflow setting station name Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 35/44] Staging: bcm: Create and initialize new device id in InterfaceInit Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 36/44] Staging: bcm: Add two products and remove an existing product Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 37/44] powerpc: Fix emulation of illegal instructions on PowerNV platform Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 38/44] powerpc/smp: Section mismatch from smp_release_cpus to __initdata spinning_secondaries Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 39/44] powerpc: Dont Oops when accessing /proc/powerpc/lparcfg without hypervisor Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 40/44] powerpc: Restore registers on error exit from csum_partial_copy_generic() Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 41/44] powerpc/pseries/lparcfg: Fix possible overflow are more than 1026 Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 42/44] powerpc/pseries: Duplicate dtl entries sometimes sent to userspace Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 43/44] ACPI video: ignore BIOS backlight value for HP dm4 Greg Kroah-Hartman
2014-07-08  0:07 ` [PATCH 3.4 44/44] powerpc/sysfs: Disable writing to PURR in guest mode Greg Kroah-Hartman
2014-07-08 13:14 ` [PATCH 3.4 00/44] 3.4.98-stable review Guenter Roeck
2014-07-08 22:14   ` Greg Kroah-Hartman
2014-07-08 19:30 ` Shuah Khan
2014-07-08 22:14   ` Greg Kroah-Hartman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20140707235859.631290823@linuxfoundation.org \
    --to=gregkh@linuxfoundation.org \
    --cc=abbotti@mev.co.uk \
    --cc=ben@decadent.org.uk \
    --cc=linux-kernel@vger.kernel.org \
    --cc=stable@vger.kernel.org \
    --cc=wangyijing@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox