stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 2.6.32 00/55] 2.6.32.71-longterm review
       [not found] <148ee355b419e9976ca727513a1405c8@local>
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 01/55] usb: serial: visor: fix crash on detecting device without write_urbs Willy Tarreau
                   ` (53 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable

This is the start of the longterm review cycle for the 2.6.32.71 release.
All patches will be posted as a response to this one. If anyone has any
issue with these being applied, please let me know. If anyone is a
maintainer of the proper subsystem, and wants to add a Signed-off-by: line
to the patch, please respond with it. If anyone thinks some important
patches are missing and should be added prior to the release, please
report them quickly with their respective mainline commit IDs.

Responses should be made by Thu Mar 10 16:29:59 CET 2016.
Anything received after that time might be too late. If someone
wants a bit more time for a deeper review, please let me know.

NOTE: this is the very last 2.6.32 release, there will be no more after.
      In theory there is no reason to deploy this release unless you're
      still in the process of validating a new kernel. Kernel 3.2 is an
      excellent upgrade which still has more than two extra years to
      live.

This release candidate was tested on the following platforms :

         ARCH  |         CONFIGURATION
       --------+-----------------------------------
               |  allmodconfig     other-config
        x86_64 |    build:OK         boot:OK
          i386 |    build:OK            -
         armv5 |      -             build:OK

The whole patch series can be found in one patch at :
     https://kernel.org/pub/linux/kernel/v2.6/longterm-review/patch-2.6.32.71-rc1.gz

The shortlog and diffstat are appended below.

Thanks,
Willy

===============

 arch/sparc/kernel/sys_sparc_64.c                |   2 +-
 arch/x86/include/asm/mmu_context.h              |  32 +++-
 arch/x86/mm/pageattr.c                          |   4 +-
 arch/x86/mm/tlb.c                               |  28 ++-
 drivers/ata/ahci.c                              |   4 +-
 drivers/char/tty_io.c                           |  24 ++-
 drivers/infiniband/hw/cxgb3/iwch_cm.c           |   8 +-
 drivers/media/dvb/frontends/tda1004x.c          |   9 +
 drivers/media/video/saa7134/saa7134-alsa.c      |   5 +-
 drivers/media/video/usbvision/usbvision-video.c |   7 +
 drivers/net/pppol2tp.c                          |   3 +-
 drivers/pci/pcie/aer/aerdrv.c                   |   3 +-
 drivers/pci/pcie/aer/aerdrv.h                   |   1 -
 drivers/pci/pcie/aer/aerdrv_core.c              |   2 -
 drivers/scsi/device_handler/scsi_dh_rdac.c      |   4 +-
 drivers/scsi/sd.c                               |   7 +-
 drivers/usb/serial/visor.c                      |  11 +-
 fs/aio.c                                        |  30 ++-
 fs/locks.c                                      |  51 +++---
 fs/ocfs2/dlm/dlmmaster.c                        |  26 +--
 fs/ocfs2/dlm/dlmrecovery.c                      |   1 +
 fs/pipe.c                                       |   5 +-
 fs/read_write.c                                 |  62 ++++---
 fs/udf/inode.c                                  |  15 ++
 fs/udf/misc.c                                   |  13 +-
 fs/udf/super.c                                  |   6 +-
 fs/udf/udfdecl.h                                |   8 +-
 fs/udf/unicode.c                                |  21 ++-
 include/linux/fs.h                              |   1 +
 include/sound/rawmidi.h                         |   4 +
 net/rfkill/core.c                               |  16 +-
 net/sctp/sm_sideeffect.c                        |  34 ++--
 net/sctp/socket.c                               |   9 +-
 net/unix/af_unix.c                              |   1 +
 sound/core/control.c                            |   2 +
 sound/core/hrtimer.c                            |   3 +-
 sound/core/oss/pcm_oss.c                        |  21 ++-
 sound/core/pcm_compat.c                         |  13 +-
 sound/core/rawmidi.c                            | 134 ++++++++++----
 sound/core/seq/oss/seq_oss_init.c               |   2 +-
 sound/core/seq/oss/seq_oss_synth.c              |   2 +-
 sound/core/seq/seq_clientmgr.c                  |   5 +-
 sound/core/seq/seq_compat.c                     |   9 +-
 sound/core/seq/seq_ports.c                      | 233 +++++++++++++-----------
 sound/core/seq/seq_queue.c                      |   2 +
 sound/core/seq/seq_timer.c                      |  87 +++++++--
 sound/core/seq/seq_virmidi.c                    |  23 ++-
 sound/core/timer.c                              | 118 ++++++++----
 sound/drivers/dummy.c                           |   2 +-
 sound/usb/usbmidi.c                             |   1 -
 50 files changed, 740 insertions(+), 374 deletions(-)
--

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 01/55] usb: serial: visor: fix crash on detecting device without write_urbs
       [not found] <148ee355b419e9976ca727513a1405c8@local>
  2016-03-04 15:30 ` [PATCH 2.6.32 00/55] 2.6.32.71-longterm review Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 02/55] usbvision fix overflow of interfaces array Willy Tarreau
                   ` (52 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Ralf Spenneberg, Vladis Dronov, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Vladis Dronov <vdronov@redhat.com>

commit cb3232138e37129e88240a98a1d2aba2187ff57c upstream.

The visor driver crashes in clie_5_attach() when a specially crafted USB
device without bulk-out endpoint is detected. This fix adds a check that
the device has proper configuration expected by the driver.

Reported-by: Ralf Spenneberg <ralf@spenneberg.net>
Signed-off-by: Vladis Dronov <vdronov@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/usb/serial/visor.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 9af8c2f..e9229c5 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -921,8 +921,10 @@ static int clie_5_attach(struct usb_serial *serial)
 	 */
 
 	/* some sanity check */
-	if (serial->num_ports < 2)
-		return -1;
+	if (serial->num_bulk_out < 2) {
+		dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
+		return -ENODEV;
+	}
 
 	/* port 0 now uses the modified endpoint Address */
 	serial->port[0]->bulk_out_endpointAddress =
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 02/55] usbvision fix overflow of interfaces array
       [not found] <148ee355b419e9976ca727513a1405c8@local>
  2016-03-04 15:30 ` [PATCH 2.6.32 00/55] 2.6.32.71-longterm review Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 01/55] usb: serial: visor: fix crash on detecting device without write_urbs Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 03/55] USB: visor: fix null-deref at probe Willy Tarreau
                   ` (51 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Oliver Neukum, Vladis Dronov, Hans Verkuil, Mauro Carvalho Chehab,
	Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Oliver Neukum <oneukum@suse.com>

commit 588afcc1c0e45358159090d95bf7b246fb67565f upstream.

This fixes the crash reported in:
http://seclists.org/bugtraq/2015/Oct/35
The interface number needs a sanity check.

Signed-off-by: Oliver Neukum <oneukum@suse.com>
Cc: Vladis Dronov <vdronov@redhat.com>
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
[bwh: Backported to 2.6.32: adjust filename, context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/media/video/usbvision/usbvision-video.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/media/video/usbvision/usbvision-video.c b/drivers/media/video/usbvision/usbvision-video.c
index a2a50d6..1ebe22b1 100644
--- a/drivers/media/video/usbvision/usbvision-video.c
+++ b/drivers/media/video/usbvision/usbvision-video.c
@@ -1651,6 +1651,13 @@ static int __devinit usbvision_probe(struct usb_interface *intf,
 	printk(KERN_INFO "%s: %s found\n", __func__,
 				usbvision_device_data[model].ModelString);
 
+	/*
+	 * this is a security check.
+	 * an exploit using an incorrect bInterfaceNumber is known
+	 */
+	if (ifnum >= USB_MAXINTERFACES || !dev->actconfig->interface[ifnum])
+		return -ENODEV;
+
 	if (usbvision_device_data[model].Interface >= 0) {
 		interface = &dev->actconfig->interface[usbvision_device_data[model].Interface]->altsetting[0];
 	} else {
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 03/55] USB: visor: fix null-deref at probe
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (2 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 02/55] usbvision fix overflow of interfaces array Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 04/55] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event Willy Tarreau
                   ` (50 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Johan Hovold, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Johan Hovold <johan@kernel.org>

commit cac9b50b0d75a1d50d6c056ff65c005f3224c8e0 upstream.

Fix null-pointer dereference at probe should a (malicious) Treo device
lack the expected endpoints.

Specifically, the Treo port-setup hack was dereferencing the bulk-in and
interrupt-in urbs without first making sure they had been allocated by
core.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/usb/serial/visor.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index e9229c5..741d834 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -878,6 +878,11 @@ static int treo_attach(struct usb_serial *serial)
 
 	dbg("%s", __func__);
 
+	if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
+		dev_err(&serial->interface->dev, "missing endpoints\n");
+		return -ENODEV;
+	}
+
 	/*
 	* It appears that Treos and Kyoceras want to use the
 	* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 04/55] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (3 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 03/55] USB: visor: fix null-deref at probe Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 05/55] sctp: translate network order to host order when users get a hmacid Willy Tarreau
                   ` (49 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Karl Heiss, David S. Miller, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Karl Heiss <kheiss@gmail.com>

commit 635682a14427d241bab7bbdeebb48a7d7b91638e upstream.

A case can occur when sctp_accept() is called by the user during
a heartbeat timeout event after the 4-way handshake.  Since
sctp_assoc_migrate() changes both assoc->base.sk and assoc->ep, the
bh_sock_lock in sctp_generate_heartbeat_event() will be taken with
the listening socket but released with the new association socket.
The result is a deadlock on any future attempts to take the listening
socket lock.

Note that this race can occur with other SCTP timeouts that take
the bh_lock_sock() in the event sctp_accept() is called.

 BUG: soft lockup - CPU#9 stuck for 67s! [swapper:0]
 ...
 RIP: 0010:[<ffffffff8152d48e>]  [<ffffffff8152d48e>] _spin_lock+0x1e/0x30
 RSP: 0018:ffff880028323b20  EFLAGS: 00000206
 RAX: 0000000000000002 RBX: ffff880028323b20 RCX: 0000000000000000
 RDX: 0000000000000000 RSI: ffff880028323be0 RDI: ffff8804632c4b48
 RBP: ffffffff8100bb93 R08: 0000000000000000 R09: 0000000000000000
 R10: ffff880610662280 R11: 0000000000000100 R12: ffff880028323aa0
 R13: ffff8804383c3880 R14: ffff880028323a90 R15: ffffffff81534225
 FS:  0000000000000000(0000) GS:ffff880028320000(0000) knlGS:0000000000000000
 CS:  0010 DS: 0018 ES: 0018 CR0: 000000008005003b
 CR2: 00000000006df528 CR3: 0000000001a85000 CR4: 00000000000006e0
 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
 DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
 Process swapper (pid: 0, threadinfo ffff880616b70000, task ffff880616b6cab0)
 Stack:
 ffff880028323c40 ffffffffa01c2582 ffff880614cfb020 0000000000000000
 <d> 0100000000000000 00000014383a6c44 ffff8804383c3880 ffff880614e93c00
 <d> ffff880614e93c00 0000000000000000 ffff8804632c4b00 ffff8804383c38b8
 Call Trace:
 <IRQ>
 [<ffffffffa01c2582>] ? sctp_rcv+0x492/0xa10 [sctp]
 [<ffffffff8148c559>] ? nf_iterate+0x69/0xb0
 [<ffffffff814974a0>] ? ip_local_deliver_finish+0x0/0x2d0
 [<ffffffff8148c716>] ? nf_hook_slow+0x76/0x120
 [<ffffffff814974a0>] ? ip_local_deliver_finish+0x0/0x2d0
 [<ffffffff8149757d>] ? ip_local_deliver_finish+0xdd/0x2d0
 [<ffffffff81497808>] ? ip_local_deliver+0x98/0xa0
 [<ffffffff81496ccd>] ? ip_rcv_finish+0x12d/0x440
 [<ffffffff81497255>] ? ip_rcv+0x275/0x350
 [<ffffffff8145cfeb>] ? __netif_receive_skb+0x4ab/0x750
 ...

With lockdep debugging:

 =====================================
 [ BUG: bad unlock balance detected! ]
 -------------------------------------
 CslRx/12087 is trying to release lock (slock-AF_INET) at:
 [<ffffffffa01bcae0>] sctp_generate_timeout_event+0x40/0xe0 [sctp]
 but there are no more locks to release!

 other info that might help us debug this:
 2 locks held by CslRx/12087:
 #0:  (&asoc->timers[i]){+.-...}, at: [<ffffffff8108ce1f>] run_timer_softirq+0x16f/0x3e0
 #1:  (slock-AF_INET){+.-...}, at: [<ffffffffa01bcac3>] sctp_generate_timeout_event+0x23/0xe0 [sctp]

Ensure the socket taken is also the same one that is released by
saving a copy of the socket before entering the timeout event
critical section.

Signed-off-by: Karl Heiss <kheiss@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 2.6.32:
 - Net namespaces are not used
 - Keep using sctp_bh_{,un}lock_sock()
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 net/sctp/sm_sideeffect.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 9005d83..d12123a64 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -247,11 +247,12 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
 	int error;
 	struct sctp_transport *transport = (struct sctp_transport *) peer;
 	struct sctp_association *asoc = transport->asoc;
+	struct sock *sk = asoc->base.sk;
 
 	/* Check whether a task is in the sock.  */
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
 
 		/* Try again later.  */
@@ -274,10 +275,10 @@ void sctp_generate_t3_rtx_event(unsigned long peer)
 			   transport, GFP_ATOMIC);
 
 	if (error)
-		asoc->base.sk->sk_err = -error;
+		sk->sk_err = -error;
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_transport_put(transport);
 }
 
@@ -287,10 +288,11 @@ out_unlock:
 static void sctp_generate_timeout_event(struct sctp_association *asoc,
 					sctp_event_timeout_t timeout_type)
 {
+	struct sock *sk = asoc->base.sk;
 	int error = 0;
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy: timer %d\n",
 				  __func__,
 				  timeout_type);
@@ -314,10 +316,10 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc,
 			   (void *)timeout_type, GFP_ATOMIC);
 
 	if (error)
-		asoc->base.sk->sk_err = -error;
+		sk->sk_err = -error;
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_association_put(asoc);
 }
 
@@ -367,9 +369,10 @@ void sctp_generate_heartbeat_event(unsigned long data)
 	int error = 0;
 	struct sctp_transport *transport = (struct sctp_transport *) data;
 	struct sctp_association *asoc = transport->asoc;
+	struct sock *sk = asoc->base.sk;
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
 
 		/* Try again later.  */
@@ -390,10 +393,10 @@ void sctp_generate_heartbeat_event(unsigned long data)
 			   transport, GFP_ATOMIC);
 
 	 if (error)
-		 asoc->base.sk->sk_err = -error;
+		sk->sk_err = -error;
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_transport_put(transport);
 }
 
@@ -404,9 +407,10 @@ void sctp_generate_proto_unreach_event(unsigned long data)
 {
 	struct sctp_transport *transport = (struct sctp_transport *) data;
 	struct sctp_association *asoc = transport->asoc;
+	struct sock *sk = asoc->base.sk;
 
-	sctp_bh_lock_sock(asoc->base.sk);
-	if (sock_owned_by_user(asoc->base.sk)) {
+	sctp_bh_lock_sock(sk);
+	if (sock_owned_by_user(sk)) {
 		SCTP_DEBUG_PRINTK("%s:Sock is busy.\n", __func__);
 
 		/* Try again later.  */
@@ -427,7 +431,7 @@ void sctp_generate_proto_unreach_event(unsigned long data)
 		   asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC);
 
 out_unlock:
-	sctp_bh_unlock_sock(asoc->base.sk);
+	sctp_bh_unlock_sock(sk);
 	sctp_association_put(asoc);
 }
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 05/55] sctp: translate network order to host order when users get a hmacid
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (4 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 04/55] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 06/55] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) Willy Tarreau
                   ` (48 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Xin Long, Marcelo Ricardo Leitner, David S. Miller, Ben Hutchings,
	Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Xin Long <lucien.xin@gmail.com>

commit 7a84bd46647ff181eb2659fdc99590e6f16e501d upstream.

Commit ed5a377d87dc ("sctp: translate host order to network order when
setting a hmacid") corrected the hmacid byte-order when setting a hmacid.
but the same issue also exists on getting a hmacid.

We fix it by changing hmacids to host order when users get them with
getsockopt.

Fixes: Commit ed5a377d87dc ("sctp: translate host order to network order when setting a hmacid")
Signed-off-by: Xin Long <lucien.xin@gmail.com>
Acked-by: Marcelo Ricardo Leitner <marcelo.leitner@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 net/sctp/socket.c | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 37daea5..3a5981a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -5408,6 +5408,7 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
 	struct sctp_hmac_algo_param *hmacs;
 	__u16 data_len = 0;
 	u32 num_idents;
+	int i;
 
 	if (!sctp_auth_enable)
 		return -EACCES;
@@ -5425,8 +5426,12 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len,
 		return -EFAULT;
 	if (put_user(num_idents, &p->shmac_num_idents))
 		return -EFAULT;
-	if (copy_to_user(p->shmac_idents, hmacs->hmac_ids, data_len))
-		return -EFAULT;
+	for (i = 0; i < num_idents; i++) {
+		__u16 hmacid = ntohs(hmacs->hmac_ids[i]);
+
+		if (copy_to_user(&p->shmac_idents[i], &hmacid, sizeof(__u16)))
+			return -EFAULT;
+	}
 	return 0;
 }
 
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 06/55] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD)
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (5 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 05/55] sctp: translate network order to host order when users get a hmacid Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 07/55] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization Willy Tarreau
                   ` (47 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Peter Hurley, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Peter Hurley <peter@hurleysoftware.com>

commit 5c17c861a357e9458001f021a7afa7aab9937439 upstream.

ioctl(TIOCGETD) retrieves the line discipline id directly from the
ldisc because the line discipline id (c_line) in termios is untrustworthy;
userspace may have set termios via ioctl(TCSETS*) without actually
changing the line discipline via ioctl(TIOCSETD).

However, directly accessing the current ldisc via tty->ldisc is
unsafe; the ldisc ptr dereferenced may be stale if the line discipline
is changing via ioctl(TIOCSETD) or hangup.

Wait for the line discipline reference (just like read() or write())
to retrieve the "current" line discipline id.

Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
[bwh: Backported to 2.6.32: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/char/tty_io.c | 24 +++++++++++++++++++++++-
 1 file changed, 23 insertions(+), 1 deletion(-)

diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 6c71534..35692d2 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2336,6 +2336,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
 }
 
 /**
+ *	tiocgetd	-	get line discipline
+ *	@tty: tty device
+ *	@p: pointer to user data
+ *
+ *	Retrieves the line discipline id directly from the ldisc.
+ *
+ *	Locking: waits for ldisc reference (in case the line discipline
+ *		is changing or the tty is being hungup)
+ */
+
+static int tiocgetd(struct tty_struct *tty, int __user *p)
+{
+	struct tty_ldisc *ld;
+	int ret;
+
+	ld = tty_ldisc_ref_wait(tty);
+	ret = put_user(ld->ops->num, p);
+	tty_ldisc_deref(ld);
+	return ret;
+}
+
+/**
  *	send_break	-	performed time break
  *	@tty: device to break on
  *	@duration: timeout in mS
@@ -2546,7 +2568,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 	case TIOCGSID:
 		return tiocgsid(tty, real_tty, p);
 	case TIOCGETD:
-		return put_user(tty->ldisc->ops->num, (int __user *)p);
+		return tiocgetd(tty, p);
 	case TIOCSETD:
 		return tiocsetd(tty, p);
 	/*
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 07/55] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (6 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 06/55] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 08/55] x86/mm: Improve switch_mm() barrier comments Willy Tarreau
                   ` (46 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Andy Lutomirski, Andrew Morton, Andy Lutomirski, Borislav Petkov,
	Brian Gerst, Dave Hansen, Denys Vlasenko, H. Peter Anvin,
	Linus Torvalds, Peter Zijlstra, Rik van Riel, Thomas Gleixner,
	linux-mm, Ingo Molnar, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Andy Lutomirski <luto@kernel.org>

commit 71b3c126e61177eb693423f2e18a1914205b165e upstream.

When switch_mm() activates a new PGD, it also sets a bit that
tells other CPUs that the PGD is in use so that TLB flush IPIs
will be sent.  In order for that to work correctly, the bit
needs to be visible prior to loading the PGD and therefore
starting to fill the local TLB.

Document all the barriers that make this work correctly and add
a couple that were missing.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-mm@kvack.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
[bwh: Backported to 2.6.32:
 - There's no flush_tlb_mm_range(), only flush_tlb_mm() which does not use
   INVLPG
 - Adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 arch/x86/include/asm/mmu_context.h | 31 ++++++++++++++++++++++++++++++-
 arch/x86/mm/tlb.c                  | 28 ++++++++++++++++++++++++----
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index 8b5393e..b2c847a 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -42,7 +42,32 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 #endif
 		cpumask_set_cpu(cpu, mm_cpumask(next));
 
-		/* Re-load page tables */
+		/*
+		 * Re-load page tables.
+		 *
+		 * This logic has an ordering constraint:
+		 *
+		 *  CPU 0: Write to a PTE for 'next'
+		 *  CPU 0: load bit 1 in mm_cpumask.  if nonzero, send IPI.
+		 *  CPU 1: set bit 1 in next's mm_cpumask
+		 *  CPU 1: load from the PTE that CPU 0 writes (implicit)
+		 *
+		 * We need to prevent an outcome in which CPU 1 observes
+		 * the new PTE value and CPU 0 observes bit 1 clear in
+		 * mm_cpumask.  (If that occurs, then the IPI will never
+		 * be sent, and CPU 0's TLB will contain a stale entry.)
+		 *
+		 * The bad outcome can occur if either CPU's load is
+		 * reordered before that CPU's store, so both CPUs much
+		 * execute full barriers to prevent this from happening.
+		 *
+		 * Thus, switch_mm needs a full barrier between the
+		 * store to mm_cpumask and any operation that could load
+		 * from next->pgd.  This barrier synchronizes with
+		 * remote TLB flushers.  Fortunately, load_cr3 is
+		 * serializing and thus acts as a full barrier.
+		 *
+		 */
 		load_cr3(next->pgd);
 
 		/* stop flush ipis for the previous mm */
@@ -63,6 +88,10 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			/* We were in lazy tlb mode and leave_mm disabled
 			 * tlb flush IPI delivery. We must reload CR3
 			 * to make sure to use no freed page tables.
+			 *
+			 * As above, this is a barrier that forces
+			 * TLB repopulation to be ordered after the
+			 * store to mm_cpumask.
 			 */
 			load_cr3(next->pgd);
 			load_LDT_nolock(&next->context);
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index 36fe08e..2a655b2 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -234,7 +234,9 @@ void flush_tlb_current_task(void)
 
 	preempt_disable();
 
+	/* This is an implicit full barrier that synchronizes with switch_mm. */
 	local_flush_tlb();
+
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
 		flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL);
 	preempt_enable();
@@ -245,10 +247,20 @@ void flush_tlb_mm(struct mm_struct *mm)
 	preempt_disable();
 
 	if (current->active_mm == mm) {
-		if (current->mm)
+		if (current->mm) {
+			/*
+			 * This is an implicit full barrier (MOV to CR) that
+			 * synchronizes with switch_mm.
+			 */
 			local_flush_tlb();
-		else
+		} else {
 			leave_mm(smp_processor_id());
+			/* Synchronize with switch_mm. */
+			smp_mb();
+		}
+	} else {
+		/* Synchronize with switch_mm. */
+		smp_mb();
 	}
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
 		flush_tlb_others(mm_cpumask(mm), mm, TLB_FLUSH_ALL);
@@ -263,10 +275,18 @@ void flush_tlb_page(struct vm_area_struct *vma, unsigned long va)
 	preempt_disable();
 
 	if (current->active_mm == mm) {
-		if (current->mm)
+		if (current->mm) {
+			/*
+			 * Implicit full barrier (INVLPG) that synchronizes
+			 * with switch_mm.
+			 */
 			__flush_tlb_one(va);
-		else
+		} else {
 			leave_mm(smp_processor_id());
+
+			/* Synchronize with switch_mm. */
+			smp_mb();
+		}
 	}
 
 	if (cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids)
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 08/55] x86/mm: Improve switch_mm() barrier comments
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (7 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 07/55] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 10/55] sparc64: fix incorrect sign extension in sys_sparc64_personality Willy Tarreau
                   ` (45 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Peter Zijlstra, Andy Lutomirski, Andy Lutomirski, Borislav Petkov,
	Brian Gerst, Dave Hansen, Denys Vlasenko, H. Peter Anvin,
	Linus Torvalds, Rik van Riel, Thomas Gleixner, Ingo Molnar,
	Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Andy Lutomirski <luto@kernel.org>

commit 4eaffdd5a5fe6ff9f95e1ab4de1ac904d5e0fa8b upstream.

My previous comments were still a bit confusing and there was a
typo. Fix it up.

Reported-by: Peter Zijlstra <peterz@infradead.org>
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Rik van Riel <riel@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Fixes: 71b3c126e611 ("x86/mm: Add barriers and document switch_mm()-vs-flush synchronization")
Link: http://lkml.kernel.org/r/0a0b43cdcdd241c5faaaecfbcc91a155ddedc9a1.1452631609.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 arch/x86/include/asm/mmu_context.h | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/arch/x86/include/asm/mmu_context.h b/arch/x86/include/asm/mmu_context.h
index b2c847a..a897c3b 100644
--- a/arch/x86/include/asm/mmu_context.h
+++ b/arch/x86/include/asm/mmu_context.h
@@ -58,14 +58,16 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 		 * be sent, and CPU 0's TLB will contain a stale entry.)
 		 *
 		 * The bad outcome can occur if either CPU's load is
-		 * reordered before that CPU's store, so both CPUs much
+		 * reordered before that CPU's store, so both CPUs must
 		 * execute full barriers to prevent this from happening.
 		 *
 		 * Thus, switch_mm needs a full barrier between the
 		 * store to mm_cpumask and any operation that could load
-		 * from next->pgd.  This barrier synchronizes with
-		 * remote TLB flushers.  Fortunately, load_cr3 is
-		 * serializing and thus acts as a full barrier.
+		 * from next->pgd.  TLB fills are special and can happen
+		 * due to instruction fetches or for no reason at all,
+		 * and neither LOCK nor MFENCE orders them.
+		 * Fortunately, load_cr3() is serializing and gives the
+		 * ordering guarantee we need.
 		 *
 		 */
 		load_cr3(next->pgd);
@@ -89,9 +91,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 			 * tlb flush IPI delivery. We must reload CR3
 			 * to make sure to use no freed page tables.
 			 *
-			 * As above, this is a barrier that forces
-			 * TLB repopulation to be ordered after the
-			 * store to mm_cpumask.
+			 * As above, load_cr3() is serializing and orders TLB
+			 * fills with respect to the mm_cpumask write.
 			 */
 			load_cr3(next->pgd);
 			load_LDT_nolock(&next->context);
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 10/55] sparc64: fix incorrect sign extension in sys_sparc64_personality
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (8 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 08/55] x86/mm: Improve switch_mm() barrier comments Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 11/55] locks: fix unlock when fcntl_setlk races with a close Willy Tarreau
                   ` (44 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry V. Levin, David S. Miller, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: "Dmitry V. Levin" <ldv@altlinux.org>

commit 525fd5a94e1be0776fa652df5c687697db508c91 upstream.

The value returned by sys_personality has type "long int".
It is saved to a variable of type "int", which is not a problem
yet because the type of task_struct->pesonality is "unsigned int".
The problem is the sign extension from "int" to "long int"
that happens on return from sys_sparc64_personality.

For example, a userspace call personality((unsigned) -EINVAL) will
result to any subsequent personality call, including absolutely
harmless read-only personality(0xffffffff) call, failing with
errno set to EINVAL.

Signed-off-by: Dmitry V. Levin <ldv@altlinux.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 arch/sparc/kernel/sys_sparc_64.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c
index cfa0e19..74e579b 100644
--- a/arch/sparc/kernel/sys_sparc_64.c
+++ b/arch/sparc/kernel/sys_sparc_64.c
@@ -524,7 +524,7 @@ SYSCALL_DEFINE1(sparc64_newuname, struct new_utsname __user *, name)
 
 SYSCALL_DEFINE1(sparc64_personality, unsigned long, personality)
 {
-	int ret;
+	long ret;
 
 	if (current->personality == PER_LINUX32 &&
 	    personality == PER_LINUX)
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 11/55] locks: fix unlock when fcntl_setlk races with a close
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (9 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 10/55] sparc64: fix incorrect sign extension in sys_sparc64_personality Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 12/55] l2tp: fix another panic in pppol2tp Willy Tarreau
                   ` (43 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Alexander Viro, Dmitry Vyukov, Jeff Layton, J. Bruce Fields,
	Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Jeff Layton <jeff.layton@primarydata.com>

commit 7f3697e24dc3820b10f445a4a7d914fc356012d1 upstream.

Dmitry reported that he was able to reproduce the WARN_ON_ONCE that
fires in locks_free_lock_context when the flc_posix list isn't empty.

The problem turns out to be that we're basically rebuilding the
file_lock from scratch in fcntl_setlk when we discover that the setlk
has raced with a close. If the l_whence field is SEEK_CUR or SEEK_END,
then we may end up with fl_start and fl_end values that differ from
when the lock was initially set, if the file position or length of the
file has changed in the interim.

Fix this by just reusing the same lock request structure, and simply
override fl_type value with F_UNLCK as appropriate. That ensures that
we really are unlocking the lock that was initially set.

While we're there, make sure that we do pop a WARN_ON_ONCE if the
removal ever fails. Also return -EBADF in this event, since that's
what we would have returned if the close had happened earlier.

Cc: Alexander Viro <viro@zeniv.linux.org.uk>
Fixes: c293621bbf67 (stale POSIX lock handling)
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Jeff Layton <jeff.layton@primarydata.com>
Acked-by: "J. Bruce Fields" <bfields@fieldses.org>
[bwh: Backported to 3.2: s/i_flctx->flc_posix/inode->i_flock/ in comments]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/locks.c | 51 ++++++++++++++++++++++++++++++---------------------
 1 file changed, 30 insertions(+), 21 deletions(-)

diff --git a/fs/locks.c b/fs/locks.c
index fde92d1..d7fc479 100644
--- a/fs/locks.c
+++ b/fs/locks.c
@@ -1796,7 +1796,6 @@ int fcntl_setlk(unsigned int fd, struct file *filp, unsigned int cmd,
 		goto out;
 	}
 
-again:
 	error = flock_to_posix_lock(filp, file_lock, &flock);
 	if (error)
 		goto out;
@@ -1827,19 +1826,22 @@ again:
 	 * Attempt to detect a close/fcntl race and recover by
 	 * releasing the lock that was just acquired.
 	 */
-	/*
-	 * we need that spin_lock here - it prevents reordering between
-	 * update of inode->i_flock and check for it done in close().
-	 * rcu_read_lock() wouldn't do.
-	 */
-	spin_lock(&current->files->file_lock);
-	f = fcheck(fd);
-	spin_unlock(&current->files->file_lock);
-	if (!error && f != filp && flock.l_type != F_UNLCK) {
-		flock.l_type = F_UNLCK;
-		goto again;
+	if (!error && file_lock->fl_type != F_UNLCK) {
+		/*
+		 * We need that spin_lock here - it prevents reordering between
+		 * update of inode->i_flock and check for it done in
+		 * close(). rcu_read_lock() wouldn't do.
+		 */
+		spin_lock(&current->files->file_lock);
+		f = fcheck(fd);
+		spin_unlock(&current->files->file_lock);
+		if (f != filp) {
+			file_lock->fl_type = F_UNLCK;
+			error = do_lock_file_wait(filp, cmd, file_lock);
+			WARN_ON_ONCE(error);
+			error = -EBADF;
+		}
 	}
-
 out:
 	locks_free_lock(file_lock);
 	return error;
@@ -1914,7 +1916,6 @@ int fcntl_setlk64(unsigned int fd, struct file *filp, unsigned int cmd,
 		goto out;
 	}
 
-again:
 	error = flock64_to_posix_lock(filp, file_lock, &flock);
 	if (error)
 		goto out;
@@ -1945,14 +1946,22 @@ again:
 	 * Attempt to detect a close/fcntl race and recover by
 	 * releasing the lock that was just acquired.
 	 */
-	spin_lock(&current->files->file_lock);
-	f = fcheck(fd);
-	spin_unlock(&current->files->file_lock);
-	if (!error && f != filp && flock.l_type != F_UNLCK) {
-		flock.l_type = F_UNLCK;
-		goto again;
+	if (!error && file_lock->fl_type != F_UNLCK) {
+		/*
+		 * We need that spin_lock here - it prevents reordering between
+		 * update of inode->i_flock and check for it done in
+		 * close(). rcu_read_lock() wouldn't do.
+		 */
+		spin_lock(&current->files->file_lock);
+		f = fcheck(fd);
+		spin_unlock(&current->files->file_lock);
+		if (f != filp) {
+			file_lock->fl_type = F_UNLCK;
+			error = do_lock_file_wait(filp, cmd, file_lock);
+			WARN_ON_ONCE(error);
+			error = -EBADF;
+		}
 	}
-
 out:
 	locks_free_lock(file_lock);
 	return error;
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 12/55] l2tp: fix another panic in pppol2tp
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (10 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 11/55] locks: fix unlock when fcntl_setlk races with a close Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 13/55] vfs: make AIO use the proper rw_verify_area() area helpers Willy Tarreau
                   ` (42 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Willy Tarreau <w@1wt.eu>

Commit 3feec9095d1 ("l2tp: Fix oops in pppol2tp_xmit") was backported
into 2.6.32.16 to fix a possible null deref in pppol2tp. But the same
still exists in pppol2tp_sendmsg() possibly causing the same crash.
Note that this bug doesn't appear to have any other impact than crashing
the system, as the dereferenced pointer is only used to test a value
against a 3-bit mask, so it can hardly be abused for anything except
leaking one third of a bit of memory.

This issue doesn't exist upstream because the code was replaced in 2.6.35
and the new function l2tp_xmit_skb() performs the appropriate check.

Reported-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/net/pppol2tp.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c
index 4c8f019..2295c13 100644
--- a/drivers/net/pppol2tp.c
+++ b/drivers/net/pppol2tp.c
@@ -975,7 +975,8 @@ static int pppol2tp_sendmsg(struct kiocb *iocb, struct socket *sock, struct msgh
 	/* Calculate UDP checksum if configured to do so */
 	if (sk_tun->sk_no_check == UDP_CSUM_NOXMIT)
 		skb->ip_summed = CHECKSUM_NONE;
-	else if (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM)) {
+	else if ((skb_dst(skb) && skb_dst(skb)->dev) &&
+		 (!(skb_dst(skb)->dev->features & NETIF_F_V4_CSUM))) {
 		skb->ip_summed = CHECKSUM_COMPLETE;
 		csum = skb_checksum(skb, 0, udp_len, 0);
 		uh->check = csum_tcpudp_magic(inet->saddr, inet->daddr,
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 13/55] vfs: make AIO use the proper rw_verify_area() area helpers
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (11 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 12/55] l2tp: fix another panic in pppol2tp Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 14/55] readv/writev: do the same MAX_RW_COUNT truncation that read/write does Willy Tarreau
                   ` (41 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Manish Honap, Linus Torvalds, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Linus Torvalds <torvalds@linux-foundation.org>

commit a70b52ec1aaeaf60f4739edb1b422827cb6f3893 upstream.

We had for some reason overlooked the AIO interface, and it didn't use
the proper rw_verify_area() helper function that checks (for example)
mandatory locking on the file, and that the size of the access doesn't
cause us to overflow the provided offset limits etc.

Instead, AIO did just the security_file_permission() thing (that
rw_verify_area() also does) directly.

This fixes it to do all the proper helper functions, which not only
means that now mandatory file locking works with AIO too, we can
actually remove lines of code.

Reported-by: Manish Honap <manish_honap_vit@yahoo.co.in>
Cc: stable@vger.kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/aio.c | 30 ++++++++++++++----------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/fs/aio.c b/fs/aio.c
index 22a19ad..5030dc6 100644
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1389,6 +1389,10 @@ static ssize_t aio_setup_vectored_rw(int type, struct kiocb *kiocb)
 	if (ret < 0)
 		goto out;
 
+	ret = rw_verify_area(type, kiocb->ki_filp, &kiocb->ki_pos, ret);
+	if (ret < 0)
+		goto out;
+
 	kiocb->ki_nr_segs = kiocb->ki_nbytes;
 	kiocb->ki_cur_seg = 0;
 	/* ki_nbytes/left now reflect bytes instead of segs */
@@ -1400,11 +1404,17 @@ out:
 	return ret;
 }
 
-static ssize_t aio_setup_single_vector(struct kiocb *kiocb)
+static ssize_t aio_setup_single_vector(int type, struct file * file, struct kiocb *kiocb)
 {
+	int bytes;
+
+	bytes = rw_verify_area(type, file, &kiocb->ki_pos, kiocb->ki_left);
+	if (bytes < 0)
+		return bytes;
+
 	kiocb->ki_iovec = &kiocb->ki_inline_vec;
 	kiocb->ki_iovec->iov_base = kiocb->ki_buf;
-	kiocb->ki_iovec->iov_len = kiocb->ki_left;
+	kiocb->ki_iovec->iov_len = bytes;
 	kiocb->ki_nr_segs = 1;
 	kiocb->ki_cur_seg = 0;
 	return 0;
@@ -1429,10 +1439,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
 		if (unlikely(!access_ok(VERIFY_WRITE, kiocb->ki_buf,
 			kiocb->ki_left)))
 			break;
-		ret = security_file_permission(file, MAY_READ);
-		if (unlikely(ret))
-			break;
-		ret = aio_setup_single_vector(kiocb);
+		ret = aio_setup_single_vector(READ, file, kiocb);
 		if (ret)
 			break;
 		ret = -EINVAL;
@@ -1447,10 +1454,7 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
 		if (unlikely(!access_ok(VERIFY_READ, kiocb->ki_buf,
 			kiocb->ki_left)))
 			break;
-		ret = security_file_permission(file, MAY_WRITE);
-		if (unlikely(ret))
-			break;
-		ret = aio_setup_single_vector(kiocb);
+		ret = aio_setup_single_vector(WRITE, file, kiocb);
 		if (ret)
 			break;
 		ret = -EINVAL;
@@ -1461,9 +1465,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
 		ret = -EBADF;
 		if (unlikely(!(file->f_mode & FMODE_READ)))
 			break;
-		ret = security_file_permission(file, MAY_READ);
-		if (unlikely(ret))
-			break;
 		ret = aio_setup_vectored_rw(READ, kiocb);
 		if (ret)
 			break;
@@ -1475,9 +1476,6 @@ static ssize_t aio_setup_iocb(struct kiocb *kiocb)
 		ret = -EBADF;
 		if (unlikely(!(file->f_mode & FMODE_WRITE)))
 			break;
-		ret = security_file_permission(file, MAY_WRITE);
-		if (unlikely(ret))
-			break;
 		ret = aio_setup_vectored_rw(WRITE, kiocb);
 		if (ret)
 			break;
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 14/55] readv/writev: do the same MAX_RW_COUNT truncation that read/write does
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (12 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 13/55] vfs: make AIO use the proper rw_verify_area() area helpers Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 15/55] pipe: Fix buffer offset after partially failed read Willy Tarreau
                   ` (40 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Linus Torvalds, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Linus Torvalds <torvalds@linux-foundation.org>

commit 435f49a518c78eec8e2edbbadd912737246cbe20 upstream.

We used to protect against overflow, but rather than return an error, do
what read/write does, namely to limit the total size to MAX_RW_COUNT.
This is not only more consistent, but it also means that any broken
low-level read/write routine that still keeps counts in 'int' can't
break.

Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/read_write.c    | 62 +++++++++++++++++++++++++++++-------------------------
 include/linux/fs.h |  1 +
 2 files changed, 34 insertions(+), 29 deletions(-)

diff --git a/fs/read_write.c b/fs/read_write.c
index b7f4a1f..ab80120 100644
--- a/fs/read_write.c
+++ b/fs/read_write.c
@@ -210,8 +210,6 @@ bad:
  * them to something that fits in "int" so that others
  * won't have to do range checks all the time.
  */
-#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
-
 int rw_verify_area(int read_write, struct file *file, loff_t *ppos, size_t count)
 {
 	struct inode *inode;
@@ -546,65 +544,71 @@ ssize_t rw_copy_check_uvector(int type, const struct iovec __user * uvector,
 			      unsigned long nr_segs, unsigned long fast_segs,
 			      struct iovec *fast_pointer,
 			      struct iovec **ret_pointer)
-  {
+{
 	unsigned long seg;
-  	ssize_t ret;
+	ssize_t ret;
 	struct iovec *iov = fast_pointer;
 
-  	/*
-  	 * SuS says "The readv() function *may* fail if the iovcnt argument
-  	 * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
-  	 * traditionally returned zero for zero segments, so...
-  	 */
+	/*
+	 * SuS says "The readv() function *may* fail if the iovcnt argument
+	 * was less than or equal to 0, or greater than {IOV_MAX}.  Linux has
+	 * traditionally returned zero for zero segments, so...
+	 */
 	if (nr_segs == 0) {
 		ret = 0;
-  		goto out;
+		goto out;
 	}
 
-  	/*
-  	 * First get the "struct iovec" from user memory and
-  	 * verify all the pointers
-  	 */
+	/*
+	 * First get the "struct iovec" from user memory and
+	 * verify all the pointers
+	 */
 	if (nr_segs > UIO_MAXIOV) {
 		ret = -EINVAL;
-  		goto out;
+		goto out;
 	}
 	if (nr_segs > fast_segs) {
-  		iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
+		iov = kmalloc(nr_segs*sizeof(struct iovec), GFP_KERNEL);
 		if (iov == NULL) {
 			ret = -ENOMEM;
-  			goto out;
+			goto out;
 		}
-  	}
+	}
 	if (copy_from_user(iov, uvector, nr_segs*sizeof(*uvector))) {
 		ret = -EFAULT;
-  		goto out;
+		goto out;
 	}
 
-  	/*
+	/*
 	 * According to the Single Unix Specification we should return EINVAL
 	 * if an element length is < 0 when cast to ssize_t or if the
 	 * total length would overflow the ssize_t return value of the
 	 * system call.
-  	 */
+	 *
+	 * Linux caps all read/write calls to MAX_RW_COUNT, and avoids the
+	 * overflow case.
+	 */
 	ret = 0;
-  	for (seg = 0; seg < nr_segs; seg++) {
-  		void __user *buf = iov[seg].iov_base;
-  		ssize_t len = (ssize_t)iov[seg].iov_len;
+	for (seg = 0; seg < nr_segs; seg++) {
+		void __user *buf = iov[seg].iov_base;
+		ssize_t len = (ssize_t)iov[seg].iov_len;
 
 		/* see if we we're about to use an invalid len or if
 		 * it's about to overflow ssize_t */
-		if (len < 0 || (ret + len < ret)) {
+		if (len < 0) {
 			ret = -EINVAL;
-  			goto out;
+			goto out;
 		}
 		if (unlikely(!access_ok(vrfy_dir(type), buf, len))) {
 			ret = -EFAULT;
-  			goto out;
+			goto out;
+		}
+		if (len > MAX_RW_COUNT - ret) {
+			len = MAX_RW_COUNT - ret;
+			iov[seg].iov_len = len;
 		}
-
 		ret += len;
-  	}
+	}
 out:
 	*ret_pointer = iov;
 	return ret;
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 860cb6d..acfad75 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1817,6 +1817,7 @@ extern int current_umask(void);
 /* /sys/fs */
 extern struct kobject *fs_kobj;
 
+#define MAX_RW_COUNT (INT_MAX & PAGE_CACHE_MASK)
 extern int rw_verify_area(int, struct file *, loff_t *, size_t);
 
 #define FLOCK_VERIFY_READ  1
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 15/55] pipe: Fix buffer offset after partially failed read
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (13 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 14/55] readv/writev: do the same MAX_RW_COUNT truncation that read/write does Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 16/55] af_unix: fix struct pid memory leak Willy Tarreau
                   ` (39 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Ben Hutchings <ben@decadent.org.uk>

Quoting the RHEL advisory:

> It was found that the fix for CVE-2015-1805 incorrectly kept buffer
> offset and buffer length in sync on a failed atomic read, potentially
> resulting in a pipe buffer state corruption. A local, unprivileged user
> could use this flaw to crash the system or leak kernel memory to user
> space. (CVE-2016-0774, Moderate)

The same flawed fix was applied to stable branches from 2.6.32.y to
3.14.y inclusive, and I was able to reproduce the issue on 3.2.y.
We need to give pipe_iov_copy_to_user() a separate offset variable
and only update the buffer offset if it succeeds.

References: https://rhn.redhat.com/errata/RHSA-2016-0103.html
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/pipe.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/fs/pipe.c b/fs/pipe.c
index daa71ea..d34cce9 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -360,6 +360,7 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
 			void *addr;
 			size_t chars = buf->len, remaining;
 			int error, atomic;
+			int offset;
 
 			if (chars > total_len)
 				chars = total_len;
@@ -373,9 +374,10 @@ pipe_read(struct kiocb *iocb, const struct iovec *_iov,
 
 			atomic = !iov_fault_in_pages_write(iov, chars);
 			remaining = chars;
+			offset = buf->offset;
 redo:
 			addr = ops->map(pipe, buf, atomic);
-			error = pipe_iov_copy_to_user(iov, addr, &buf->offset,
+			error = pipe_iov_copy_to_user(iov, addr, &offset,
 						      &remaining, atomic);
 			ops->unmap(pipe, buf, addr);
 			if (unlikely(error)) {
@@ -391,6 +393,7 @@ redo:
 				break;
 			}
 			ret += chars;
+			buf->offset += chars;
 			buf->len -= chars;
 			if (!buf->len) {
 				buf->ops = NULL;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 16/55] af_unix: fix struct pid memory leak
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (14 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 15/55] pipe: Fix buffer offset after partially failed read Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 17/55] PCI/AER: Flush workqueue on device remove to avoid use-after-free Willy Tarreau
                   ` (38 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Eric Dumazet, Rainer Weikusat, David S. Miller,
	Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Eric Dumazet <edumazet@google.com>

commit fa0dc04df259ba2df3ce1920e9690c7842f8fa4b upstream.

Dmitry reported a struct pid leak detected by a syzkaller program.

Bug happens in unix_stream_recvmsg() when we break the loop when a
signal is pending, without properly releasing scm.

Fixes: b3ca9b02b007 ("net: fix multithreaded signal handling in unix recv routines")
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Rainer Weikusat <rweikusat@mobileactivedefense.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Cc: Ben Hutchings <ben@decadent.org.uk>
[wt: note, according to Rainer & Ben the bug was really introduced in
 2.5.65, not by the commit mentionned in Fixes. 2.6.32 uses siocb->scm
 instead of scm]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 net/unix/af_unix.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 8e6a609..67f50be 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2018,6 +2018,7 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock,
 
 			if (signal_pending(current)) {
 				err = sock_intr_errno(timeo);
+				scm_destroy(siocb->scm);
 				goto out;
 			}
 			mutex_lock(&u->readlock);
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 17/55] PCI/AER: Flush workqueue on device remove to avoid use-after-free
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (15 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 16/55] af_unix: fix struct pid memory leak Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 18/55] libata: disable forced PORTS_IMPL for >= AHCI 1.3 Willy Tarreau
                   ` (37 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Sebastian Andrzej Siewior, Bjorn Helgaas, Ben Hutchings,
	Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

commit 4ae2182b1e3407de369f8c5d799543b7db74221b upstream.

A Root Port's AER structure (rpc) contains a queue of events.  aer_irq()
enqueues AER status information and schedules aer_isr() to dequeue and
process it.  When we remove a device, aer_remove() waits for the queue to
be empty, then frees the rpc struct.

But aer_isr() references the rpc struct after dequeueing and possibly
emptying the queue, which can cause a use-after-free error as in the
following scenario with two threads, aer_isr() on the left and a
concurrent aer_remove() on the right:

  Thread A                      Thread B
  --------                      --------
  aer_irq():
    rpc->prod_idx++
                                aer_remove():
                                  wait_event(rpc->prod_idx == rpc->cons_idx)
                                  # now blocked until queue becomes empty
  aer_isr():                      # ...
    rpc->cons_idx++               # unblocked because queue is now empty
    ...                           kfree(rpc)
    mutex_unlock(&rpc->rpc_mutex)

To prevent this problem, use flush_work() to wait until the last scheduled
instance of aer_isr() has completed before freeing the rpc struct in
aer_remove().

I reproduced this use-after-free by flashing a device FPGA and
re-enumerating the bus to find the new device.  With SLUB debug, this
crashes with 0x6b bytes (POISON_FREE, the use-after-free magic number) in
GPR25:

  pcieport 0000:00:00.0: AER: Multiple Corrected error received: id=0000
  Unable to handle kernel paging request for data at address 0x27ef9e3e
  Workqueue: events aer_isr
  GPR24: dd6aa000 6b6b6b6b 605f8378 605f8360 d99b12c0 604fc674 606b1704 d99b12c0
  NIP [602f5328] pci_walk_bus+0xd4/0x104

[bhelgaas: changelog, stable tag]
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
[wt: in 2.6.32, kfree() is called from aer_delete_rootport()]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/pci/pcie/aer/aerdrv.c      | 3 +--
 drivers/pci/pcie/aer/aerdrv.h      | 1 -
 drivers/pci/pcie/aer/aerdrv_core.c | 2 --
 3 files changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 40c3cc5..8d8bef3 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -153,7 +153,6 @@ static struct aer_rpc *aer_alloc_rpc(struct pcie_device *dev)
 	INIT_WORK(&rpc->dpc_handler, aer_isr);
 	rpc->prod_idx = rpc->cons_idx = 0;
 	mutex_init(&rpc->rpc_mutex);
-	init_waitqueue_head(&rpc->wait_release);
 
 	/* Use PCIE bus function to store rpc into PCIE device */
 	set_service_data(dev, rpc);
@@ -176,7 +175,7 @@ static void aer_remove(struct pcie_device *dev)
 		if (rpc->isr)
 			free_irq(dev->irq, dev);
 
-		wait_event(rpc->wait_release, rpc->prod_idx == rpc->cons_idx);
+		flush_work(&rpc->dpc_handler);
 
 		aer_delete_rootport(rpc);
 		set_service_data(dev, NULL);
diff --git a/drivers/pci/pcie/aer/aerdrv.h b/drivers/pci/pcie/aer/aerdrv.h
index bd833ea..ef6163f 100644
--- a/drivers/pci/pcie/aer/aerdrv.h
+++ b/drivers/pci/pcie/aer/aerdrv.h
@@ -86,7 +86,6 @@ struct aer_rpc {
 					 * recovery on the same
 					 * root port hierarchy
 					 */
-	wait_queue_head_t wait_release;
 };
 
 struct aer_broadcast_data {
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 72fa87c0..093045a 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -844,8 +844,6 @@ void aer_isr(struct work_struct *work)
 		e_src = get_e_source(rpc);
 	}
 	mutex_unlock(&rpc->rpc_mutex);
-
-	wake_up(&rpc->wait_release);
 }
 
 /**
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 18/55] libata: disable forced PORTS_IMPL for >= AHCI 1.3
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (16 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 17/55] PCI/AER: Flush workqueue on device remove to avoid use-after-free Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 19/55] rfkill: fix rfkill_fop_read wait_event usage Willy Tarreau
                   ` (36 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Tejun Heo, Andy Lutomirski, Sergei Shtylyov, Ben Hutchings,
	Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Tejun Heo <tj@kernel.org>

commit 566d1827df2ef0cbe921d3d6946ac3007b1a6938 upstream.

Some early controllers incorrectly reported zero ports in PORTS_IMPL
register and the ahci driver fabricates PORTS_IMPL from the number of
ports in those cases.  This hasn't mattered but with the new nvme
controllers there are cases where zero PORTS_IMPL is valid and should
be honored.

Disable the workaround for >= AHCI 1.3.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Andy Lutomirski <luto@amacapital.net>
Link: http://lkml.kernel.org/g/CALCETrU7yMvXEDhjAUShoHEhDwifJGapdw--BKxsP0jmjKGmRw@mail.gmail.com
Cc: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
[wt: file is drivers/ata/ahci.c in 2.6.32]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/ata/ahci.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 6787aab..c075664 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -924,8 +924,8 @@ static void ahci_save_initial_config(struct pci_dev *pdev,
 		}
 	}
 
-	/* fabricate port_map from cap.nr_ports */
-	if (!port_map) {
+	/* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
+	if (!port_map && vers < 0x10300) {
 		port_map = (1 << ahci_nr_ports(cap)) - 1;
 		dev_printk(KERN_WARNING, &pdev->dev,
 			   "forcing PORTS_IMPL to 0x%x\n", port_map);
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 19/55] rfkill: fix rfkill_fop_read wait_event usage
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (17 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 18/55] libata: disable forced PORTS_IMPL for >= AHCI 1.3 Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 20/55] SCSI: fix crashes in sd and sr runtime PM Willy Tarreau
                   ` (35 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Johannes Berg, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Johannes Berg <johannes.berg@intel.com>

commit 6736fde9672ff6717ac576e9bba2fd5f3dfec822 upstream.

The code within wait_event_interruptible() is called with
!TASK_RUNNING, so mustn't call any functions that can sleep,
like mutex_lock().

Since we re-check the list_empty() in a loop after the wait,
it's safe to simply use list_empty() without locking.

This bug has existed forever, but was only discovered now
because all userspace implementations, including the default
'rfkill' tool, use poll() or select() to get a readable fd
before attempting to read.

Fixes: c64fb01627e24 ("rfkill: create useful userspace interface")
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 net/rfkill/core.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)

diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index 85334a0..898f8cf 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -1037,17 +1037,6 @@ static unsigned int rfkill_fop_poll(struct file *file, poll_table *wait)
 	return res;
 }
 
-static bool rfkill_readable(struct rfkill_data *data)
-{
-	bool r;
-
-	mutex_lock(&data->mtx);
-	r = !list_empty(&data->events);
-	mutex_unlock(&data->mtx);
-
-	return r;
-}
-
 static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
 			       size_t count, loff_t *pos)
 {
@@ -1064,8 +1053,11 @@ static ssize_t rfkill_fop_read(struct file *file, char __user *buf,
 			goto out;
 		}
 		mutex_unlock(&data->mtx);
+		/* since we re-check and it just compares pointers,
+		 * using !list_empty() without locking isn't a problem
+		 */
 		ret = wait_event_interruptible(data->read_wait,
-					       rfkill_readable(data));
+					       !list_empty(&data->events));
 		mutex_lock(&data->mtx);
 
 		if (ret)
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 20/55] SCSI: fix crashes in sd and sr runtime PM
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (18 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 19/55] rfkill: fix rfkill_fop_read wait_event usage Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 21/55] tda1004x: only update the frontend properties if locked Willy Tarreau
                   ` (34 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Alan Stern, Paul Menzel, Erich Schubert, Alexandre Rossi,
	James Bottomley, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Alan Stern <stern@rowland.harvard.edu>

commit 13b4389143413a1f18127c07f72c74cad5b563e8 upstream.

Runtime suspend during driver probe and removal can cause problems.
The driver's runtime_suspend or runtime_resume callbacks may invoked
before the driver has finished binding to the device or after the
driver has unbound from the device.

This problem shows up with the sd and sr drivers, and can cause disk
or CD/DVD drives to become unusable as a result.  The fix is simple.
The drivers store a pointer to the scsi_disk or scsi_cd structure as
their private device data when probing is finished, so we simply have
to be sure to clear the private data during removal and test it during
runtime suspend/resume.

This fixes <https://bugs.debian.org/801925>.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Paul Menzel <paul.menzel@giantmonkey.de>
Reported-by: Erich Schubert <erich@debian.org>
Reported-by: Alexandre Rossi <alexandre.rossi@gmail.com>
Tested-by: Paul Menzel <paul.menzel@giantmonkey.de>
Tested-by: Erich Schubert <erich@debian.org>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
[bwh: Backported to 3.2: drop changes to sr as it doesn't support runtime PM]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/scsi/sd.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 9202fc8..88de52c 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -2311,8 +2311,8 @@ static int sd_suspend(struct device *dev, pm_message_t mesg)
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 	int ret = 0;
 
-	if (!sdkp)
-		return 0;	/* this can happen */
+	if (!sdkp)	/* E.g.: runtime suspend following sd_remove() */
+		return 0;
 
 	if (sdkp->WCE) {
 		sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
@@ -2336,6 +2336,9 @@ static int sd_resume(struct device *dev)
 	struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev);
 	int ret = 0;
 
+	if (!sdkp)	/* E.g.: runtime resume at the start of sd_probe() */
+		return 0;
+
 	if (!sdkp->device->manage_start_stop)
 		goto done;
 
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 21/55] tda1004x: only update the frontend properties if locked
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (19 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 20/55] SCSI: fix crashes in sd and sr runtime PM Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 22/55] saa7134-alsa: Only frees registered sound cards Willy Tarreau
                   ` (33 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Mauro Carvalho Chehab, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

commit e8beb02343e7582980c6705816cd957cf4f74c7a upstream.

The tda1004x was updating the properties cache before locking.
If the device is not locked, the data at the registers are just
random values with no real meaning.

This caused the driver to fail with libdvbv5, as such library
calls GET_PROPERTY from time to time, in order to return the
DVB stats.

Tested with a saa7134 card 78:
	ASUSTeK P7131 Dual, vendor PCI ID: 1043:4862

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
[bwh: Backported to 3.2: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/media/dvb/frontends/tda1004x.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/drivers/media/dvb/frontends/tda1004x.c b/drivers/media/dvb/frontends/tda1004x.c
index f2a8abe..97696c3 100644
--- a/drivers/media/dvb/frontends/tda1004x.c
+++ b/drivers/media/dvb/frontends/tda1004x.c
@@ -898,9 +898,18 @@ static int tda1004x_set_fe(struct dvb_frontend* fe,
 static int tda1004x_get_fe(struct dvb_frontend* fe, struct dvb_frontend_parameters *fe_params)
 {
 	struct tda1004x_state* state = fe->demodulator_priv;
+	int status;
 
 	dprintk("%s\n", __func__);
 
+	status = tda1004x_read_byte(state, TDA1004X_STATUS_CD);
+	if (status == -1)
+		return -EIO;
+
+	/* Only update the properties cache if device is locked */
+	if (!(status & 8))
+		return 0;
+
 	// inversion status
 	fe_params->inversion = INVERSION_OFF;
 	if (tda1004x_read_byte(state, TDA1004X_CONFC1) & 0x20)
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 22/55] saa7134-alsa: Only frees registered sound cards
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (20 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 21/55] tda1004x: only update the frontend properties if locked Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 23/55] scsi_dh_rdac: always retry MODE SELECT on command lock violation Willy Tarreau
                   ` (32 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Mauro Carvalho Chehab, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Mauro Carvalho Chehab <mchehab@osg.samsung.com>

commit ac75fe5d8fe4a0bf063be18fb29684405279e79e upstream.

That prevents this bug:
[ 2382.269496] BUG: unable to handle kernel NULL pointer dereference at 0000000000000540
[ 2382.270013] IP: [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
[ 2382.270013] PGD 0
[ 2382.270013] Oops: 0002 [#1] SMP
[ 2382.270013] Modules linked in: saa7134_alsa(-) tda1004x saa7134_dvb videobuf2_dvb dvb_core tda827x tda8290 tuner saa7134 tveeprom videobuf2_dma_sg videobuf2_memops videobuf2_v4l2 videobuf2_core v4l2_common videodev media auth_rpcgss nfsv4 dns_resolver nfs lockd grace sunrpc tun bridge stp llc ebtables ip6table_filter ip6_tables nf_conntrack_ipv4 nf_defrag_ipv4 xt_conntrack nf_conntrack it87 hwmon_vid snd_hda_codec_idt snd_hda_codec_generic iTCO_wdt iTCO_vendor_support snd_hda_intel snd_hda_codec snd_hwdep snd_hda_core snd_seq pcspkr i2c_i801 snd_seq_device snd_pcm snd_timer lpc_ich snd mfd_core soundcore binfmt_misc i915 video i2c_algo_bit drm_kms_helper drm r8169 ata_generic serio_raw pata_acpi mii i2c_core [last unloaded: videobuf2_memops]
[ 2382.270013] CPU: 0 PID: 4899 Comm: rmmod Not tainted 4.5.0-rc1+ #4
[ 2382.270013] Hardware name: PCCHIPS P17G/P17G, BIOS 080012  05/14/2008
[ 2382.270013] task: ffff880039c38000 ti: ffff88003c764000 task.ti: ffff88003c764000
[ 2382.270013] RIP: 0010:[<ffffffffa01fe616>]  [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
[ 2382.270013] RSP: 0018:ffff88003c767ea0  EFLAGS: 00010286
[ 2382.270013] RAX: ffff88003c767eb8 RBX: 0000000000000000 RCX: 0000000000006260
[ 2382.270013] RDX: ffffffffa020a060 RSI: ffffffffa0206de1 RDI: ffff88003c767eb0
[ 2382.270013] RBP: ffff88003c767ed8 R08: 0000000000019960 R09: ffffffff811a5412
[ 2382.270013] R10: ffffea0000d7c200 R11: 0000000000000000 R12: ffff88003c767ea8
[ 2382.270013] R13: 00007ffe760617f7 R14: 0000000000000000 R15: 0000557625d7f1e0
[ 2382.270013] FS:  00007f80bb1c0700(0000) GS:ffff88003f400000(0000) knlGS:0000000000000000
[ 2382.270013] CS:  0010 DS: 0000 ES: 0000 CR0: 000000008005003b
[ 2382.270013] CR2: 0000000000000540 CR3: 000000003c00f000 CR4: 00000000000006f0
[ 2382.270013] Stack:
[ 2382.270013]  000000003c767ed8 ffffffff00000000 ffff880000000000 ffff88003c767eb8
[ 2382.270013]  ffff88003c767eb8 ffffffffa049a890 00007ffe76060060 ffff88003c767ef0
[ 2382.270013]  ffffffffa049889d ffffffffa049a500 ffff88003c767f48 ffffffff8111079c
[ 2382.270013] Call Trace:
[ 2382.270013]  [<ffffffffa049889d>] saa7134_alsa_exit+0x1d/0x780 [saa7134_alsa]
[ 2382.270013]  [<ffffffff8111079c>] SyS_delete_module+0x19c/0x1f0
[ 2382.270013]  [<ffffffff8170fc2e>] entry_SYSCALL_64_fastpath+0x12/0x71
[ 2382.270013] Code: 20 a0 48 c7 c6 e1 6d 20 a0 48 89 e5 41 54 53 4c 8d 65 d0 48 89 fb 48 83 ec 28 c7 45 d0 00 00 00 00 49 8d 7c 24 08 e8 7a 55 ed e0 <4c> 89 a3 40 05 00 00 48 89 df e8 eb fd ff ff 85 c0 75 1a 48 8d
[ 2382.270013] RIP  [<ffffffffa01fe616>] snd_card_free+0x36/0x70 [snd]
[ 2382.270013]  RSP <ffff88003c767ea0>
[ 2382.270013] CR2: 0000000000000540

Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
[bwh: Backported to 3.2: adjust filename]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/media/video/saa7134/saa7134-alsa.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c
index d48c450..18cfdf8 100644
--- a/drivers/media/video/saa7134/saa7134-alsa.c
+++ b/drivers/media/video/saa7134/saa7134-alsa.c
@@ -1145,6 +1145,8 @@ static int alsa_device_init(struct saa7134_dev *dev)
 
 static int alsa_device_exit(struct saa7134_dev *dev)
 {
+	if (!snd_saa7134_cards[dev->nr])
+		return 1;
 
 	snd_card_free(snd_saa7134_cards[dev->nr]);
 	snd_saa7134_cards[dev->nr] = NULL;
@@ -1194,7 +1196,8 @@ static void saa7134_alsa_exit(void)
 	int idx;
 
 	for (idx = 0; idx < SNDRV_CARDS; idx++) {
-		snd_card_free(snd_saa7134_cards[idx]);
+		if (snd_saa7134_cards[idx])
+			snd_card_free(snd_saa7134_cards[idx]);
 	}
 
 	saa7134_dmasound_init = NULL;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 23/55] scsi_dh_rdac: always retry MODE SELECT on command lock violation
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (21 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 22/55] saa7134-alsa: Only frees registered sound cards Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 24/55] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup Willy Tarreau
                   ` (31 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Hannes Reinecke, Johannes Thumshirn, Martin K. Petersen,
	Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Hannes Reinecke <hare@suse.de>

commit d2d06d4fe0f2cc2df9b17fefec96e6e1a1271d91 upstream.

If MODE SELECT returns with sense '05/91/36' (command lock violation)
it should always be retried without counting the number of retries.
During an HBA upgrade or similar circumstances one might see a flood
of MODE SELECT command from various HBAs, which will easily trigger
the sense code and exceed the retry count.

Signed-off-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/scsi/device_handler/scsi_dh_rdac.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 268189d..ec985bc 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -518,7 +518,7 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
 			/*
 			 * Command Lock contention
 			 */
-			err = SCSI_DH_RETRY;
+			err = SCSI_DH_IMM_RETRY;
 		break;
 	default:
 		break;
@@ -556,6 +556,8 @@ retry:
 		err = mode_select_handle_sense(sdev, h->sense);
 		if (err == SCSI_DH_RETRY && retry_cnt--)
 			goto retry;
+		if (err == SCSI_DH_IMM_RETRY)
+			goto retry;
 	}
 	if (err == SCSI_DH_OK) {
 		h->state = RDAC_STATE_ACTIVE;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 24/55] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (22 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 23/55] scsi_dh_rdac: always retry MODE SELECT on command lock violation Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 25/55] udf: Promote some debugging messages to udf_error Willy Tarreau
                   ` (30 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: xuejiufei, Joseph Qi, Mark Fasheh, Joel Becker, Junxiao Bi,
	Andrew Morton, Linus Torvalds, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: xuejiufei <xuejiufei@huawei.com>

commit c95a51807b730e4681e2ecbdfd669ca52601959e upstream.

When recovery master down, dlm_do_local_recovery_cleanup() only remove
the $RECOVERY lock owned by dead node, but do not clear the refmap bit.
Which will make umount thread falling in dead loop migrating $RECOVERY
to the dead node.

Signed-off-by: xuejiufei <xuejiufei@huawei.com>
Reviewed-by: Joseph Qi <joseph.qi@huawei.com>
Cc: Mark Fasheh <mfasheh@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
[wt: dlm_lockres_clear_refmap_bit() takes 2 args in 2.6.32]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/ocfs2/dlm/dlmrecovery.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 3492550..d693254 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -2260,6 +2260,7 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
 						break;
 					}
 				}
+				dlm_lockres_clear_refmap_bit(dead_node, res);
 				spin_unlock(&res->spinlock);
 				continue;
 			}			
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 25/55] udf: Promote some debugging messages to udf_error
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (23 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 24/55] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 26/55] udf: limit the maximum number of indirect extents in a row Willy Tarreau
                   ` (29 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: NamJae Jeon, Joe Perches, Jan Kara, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Joe Perches <joe@perches.com>

commit 7e273e3b41e32716dc122b293b5f15635af495ff upstream.

If there is a problem with a scratched disc or loader, it's valuable to know
which error occurred.

Convert some debug messages to udf_error, neaten those messages too.
Add the calculated tag checksum and the read checksum to error message.
Make udf_error a public function and move the logging prototypes together.

Original-patch-by: NamJae Jeon <linkinjeon@gmail.com>
Reviewed-by: NamJae Jeon <linkinjeon@gmail.com>
Signed-off-by: Joe Perches <joe@perches.com>
Signed-off-by: Jan Kara <jack@suse.cz>
[wt: this one is only here to export udf_error() for next commit]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/udf/misc.c    | 13 +++++++++----
 fs/udf/super.c   |  6 ++----
 fs/udf/udfdecl.h |  8 +++++++-
 3 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/fs/udf/misc.c b/fs/udf/misc.c
index 9215700..a85fa7c 100644
--- a/fs/udf/misc.c
+++ b/fs/udf/misc.c
@@ -204,6 +204,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 {
 	struct tag *tag_p;
 	struct buffer_head *bh = NULL;
+	u8 checksum;
 
 	/* Read the block */
 	if (block == 0xFFFFFFFF)
@@ -211,7 +212,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 
 	bh = udf_tread(sb, block);
 	if (!bh) {
-		udf_debug("block=%d, location=%d: read failed\n",
+		udf_error(sb, __func__, "read failed, block=%u, location=%d\n",
 			  block, location);
 		return NULL;
 	}
@@ -227,15 +228,19 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block,
 	}
 
 	/* Verify the tag checksum */
-	if (udf_tag_checksum(tag_p) != tag_p->tagChecksum) {
-		printk(KERN_ERR "udf: tag checksum failed block %d\n", block);
+	checksum = udf_tag_checksum(tag_p);
+	if (checksum != tag_p->tagChecksum) {
+		udf_error(sb, __func__,
+			  "tag checksum failed, block %u: 0x%02x != 0x%02x\n",
+			  block, checksum, tag_p->tagChecksum);
 		goto error_out;
 	}
 
 	/* Verify the tag version */
 	if (tag_p->descVersion != cpu_to_le16(0x0002U) &&
 	    tag_p->descVersion != cpu_to_le16(0x0003U)) {
-		udf_debug("tag version 0x%04x != 0x0002 || 0x0003 block %d\n",
+		udf_error(sb, __func__,
+			  "tag version 0x%04x != 0x0002 || 0x0003, block %u\n",
 			  le16_to_cpu(tag_p->descVersion), block);
 		goto error_out;
 	}
diff --git a/fs/udf/super.c b/fs/udf/super.c
index 0045ebc..197eb58 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -94,8 +94,6 @@ static void udf_close_lvid(struct super_block *);
 static unsigned int udf_count_free(struct super_block *);
 static int udf_statfs(struct dentry *, struct kstatfs *);
 static int udf_show_options(struct seq_file *, struct vfsmount *);
-static void udf_error(struct super_block *sb, const char *function,
-		      const char *fmt, ...);
 
 struct logicalVolIntegrityDescImpUse *udf_sb_lvidiu(struct udf_sb_info *sbi)
 {
@@ -2098,8 +2096,8 @@ error_out:
 	return -EINVAL;
 }
 
-static void udf_error(struct super_block *sb, const char *function,
-		      const char *fmt, ...)
+void udf_error(struct super_block *sb, const char *function,
+	       const char *fmt, ...)
 {
 	va_list args;
 
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h
index 1b56330..6337725 100644
--- a/fs/udf/udfdecl.h
+++ b/fs/udf/udfdecl.h
@@ -29,6 +29,13 @@ do { \
 #define udf_debug(f, a...) /**/
 #endif
 
+__attribute__((format(printf, 3, 4)))
+extern void udf_warning(struct super_block *, const char *, const char *, ...);
+
+__attribute__((format(printf, 3, 4)))
+extern void udf_error(struct super_block *sb, const char *function,
+		      const char *fmt, ...);
+
 #define udf_info(f, a...) \
 	printk(KERN_INFO "UDF-fs INFO " f, ##a);
 
@@ -110,7 +117,6 @@ struct extent_position {
 };
 
 /* super.c */
-extern void udf_warning(struct super_block *, const char *, const char *, ...);
 static inline void udf_updated_lvid(struct super_block *sb)
 {
 	struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 26/55] udf: limit the maximum number of indirect extents in a row
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (24 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 25/55] udf: Promote some debugging messages to udf_error Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 27/55] udf: Prevent buffer overrun with multi-byte characters Willy Tarreau
                   ` (28 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Vegard Nossum, Jan Kara, Quentin Casasnovas, Andrew Morton,
	Jan Kara, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Vegard Nossum <vegard.nossum@oracle.com>

commit b0918d9f476a8434b055e362b83fa4fd1d462c3f upstream.

udf_next_aext() just follows extent pointers while extents are marked as
indirect. This can loop forever for corrupted filesystem. Limit number
the of indirect extents we are willing to follow in a row.

[JK: Updated changelog, limit, style]

Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Cc: Jan Kara <jack@suse.com>
Cc: Quentin Casasnovas <quentin.casasnovas@oracle.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
[wt: udf_error() instead of udf_err() in 2.6.32]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/udf/inode.c | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/fs/udf/inode.c b/fs/udf/inode.c
index b8d7a0e..a22f568 100644
--- a/fs/udf/inode.c
+++ b/fs/udf/inode.c
@@ -1869,14 +1869,29 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos,
 	return (elen >> 30);
 }
 
+/*
+ * Only 1 indirect extent in a row really makes sense but allow upto 16 in case
+ * someone does some weird stuff.
+ */
+#define UDF_MAX_INDIR_EXTS 16
+
 int8_t udf_next_aext(struct inode *inode, struct extent_position *epos,
 		     struct kernel_lb_addr *eloc, uint32_t *elen, int inc)
 {
 	int8_t etype;
+	unsigned int indirections = 0;
 
 	while ((etype = udf_current_aext(inode, epos, eloc, elen, inc)) ==
 	       (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) {
 		int block;
+
+		if (++indirections > UDF_MAX_INDIR_EXTS) {
+			udf_error(inode->i_sb, __func__,
+				  "too many indirect extents in inode %lu\n",
+				  inode->i_ino);
+			return -1;
+		}
+
 		epos->block = *eloc;
 		epos->offset = sizeof(struct allocExtDesc);
 		brelse(epos->bh);
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 27/55] udf: Prevent buffer overrun with multi-byte characters
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (25 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 26/55] udf: limit the maximum number of indirect extents in a row Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 28/55] udf: Check output buffer length when converting name to CS0 Willy Tarreau
                   ` (27 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Andrew Gabbasov, Jan Kara, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Andrew Gabbasov <andrew_gabbasov@mentor.com>

commit ad402b265ecf6fa22d04043b41444cdfcdf4f52d upstream.

udf_CS0toUTF8 function stops the conversion when the output buffer
length reaches UDF_NAME_LEN-2, which is correct maximum name length,
but, when checking, it leaves the space for a single byte only,
while multi-bytes output characters can take more space, causing
buffer overflow.

Similar error exists in udf_CS0toNLS function, that restricts
the output length to UDF_NAME_LEN, while actual maximum allowed
length is UDF_NAME_LEN-2.

In these cases the output can override not only the current buffer
length field, causing corruption of the name buffer itself, but also
following allocation structures, causing kernel crash.

Adjust the output length checks in both functions to prevent buffer
overruns in case of multi-bytes UTF8 or NLS characters.

Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/udf/unicode.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index c690157..e1e04d7 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -132,11 +132,15 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
 		if (c < 0x80U)
 			utf_o->u_name[utf_o->u_len++] = (uint8_t)c;
 		else if (c < 0x800U) {
+			if (utf_o->u_len > (UDF_NAME_LEN - 4))
+				break;
 			utf_o->u_name[utf_o->u_len++] =
 						(uint8_t)(0xc0 | (c >> 6));
 			utf_o->u_name[utf_o->u_len++] =
 						(uint8_t)(0x80 | (c & 0x3f));
 		} else {
+			if (utf_o->u_len > (UDF_NAME_LEN - 5))
+				break;
 			utf_o->u_name[utf_o->u_len++] =
 						(uint8_t)(0xe0 | (c >> 12));
 			utf_o->u_name[utf_o->u_len++] =
@@ -281,7 +285,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o,
 			c = (c << 8) | ocu[i++];
 
 		len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len],
-				    UDF_NAME_LEN - utf_o->u_len);
+				    UDF_NAME_LEN - 2 - utf_o->u_len);
 		/* Valid character? */
 		if (len >= 0)
 			utf_o->u_len += len;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 28/55] udf: Check output buffer length when converting name to CS0
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (26 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 27/55] udf: Prevent buffer overrun with multi-byte characters Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 29/55] ocfs2/dlm: ignore cleaning the migration mle that is inuse Willy Tarreau
                   ` (26 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Andrew Gabbasov, Jan Kara, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Andrew Gabbasov <andrew_gabbasov@mentor.com>

commit bb00c898ad1ce40c4bb422a8207ae562e9aea7ae upstream.

If a name contains at least some characters with Unicode values
exceeding single byte, the CS0 output should have 2 bytes per character.
And if other input characters have single byte Unicode values, then
the single input byte is converted to 2 output bytes, and the length
of output becomes larger than the length of input. And if the input
name is long enough, the output length may exceed the allocated buffer
length.

All this means that conversion from UTF8 or NLS to CS0 requires
checking of output length in order to stop when it exceeds the given
output buffer size.

[JK: Make code return -ENAMETOOLONG instead of silently truncating the
name]

Signed-off-by: Andrew Gabbasov <andrew_gabbasov@mentor.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/udf/unicode.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c
index e1e04d7..7bfbcf9 100644
--- a/fs/udf/unicode.c
+++ b/fs/udf/unicode.c
@@ -181,17 +181,22 @@ int udf_CS0toUTF8(struct ustr *utf_o, const struct ustr *ocu_i)
 static int udf_UTF8toCS0(dstring *ocu, struct ustr *utf, int length)
 {
 	unsigned c, i, max_val, utf_char;
-	int utf_cnt, u_len;
+	int utf_cnt, u_len, u_ch;
 
 	memset(ocu, 0, sizeof(dstring) * length);
 	ocu[0] = 8;
 	max_val = 0xffU;
+	u_ch = 1;
 
 try_again:
 	u_len = 0U;
 	utf_char = 0U;
 	utf_cnt = 0U;
 	for (i = 0U; i < utf->u_len; i++) {
+		/* Name didn't fit? */
+		if (u_len + 1 + u_ch >= length)
+			return 0;
+
 		c = (uint8_t)utf->u_name[i];
 
 		/* Complete a multi-byte UTF-8 character */
@@ -233,6 +238,7 @@ try_again:
 			if (max_val == 0xffU) {
 				max_val = 0xffffU;
 				ocu[0] = (uint8_t)0x10U;
+				u_ch = 2;
 				goto try_again;
 			}
 			goto error_out;
@@ -303,15 +309,19 @@ static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni,
 	int len;
 	unsigned i, max_val;
 	uint16_t uni_char;
-	int u_len;
+	int u_len, u_ch;
 
 	memset(ocu, 0, sizeof(dstring) * length);
 	ocu[0] = 8;
 	max_val = 0xffU;
+	u_ch = 1;
 
 try_again:
 	u_len = 0U;
 	for (i = 0U; i < uni->u_len; i++) {
+		/* Name didn't fit? */
+		if (u_len + 1 + u_ch >= length)
+			return 0;
 		len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char);
 		if (!len)
 			continue;
@@ -324,6 +334,7 @@ try_again:
 		if (uni_char > max_val) {
 			max_val = 0xffffU;
 			ocu[0] = (uint8_t)0x10U;
+			u_ch = 2;
 			goto try_again;
 		}
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 29/55] ocfs2/dlm: ignore cleaning the migration mle that is inuse
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (27 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 28/55] udf: Check output buffer length when converting name to CS0 Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 30/55] ALSA: dummy: Disable switching timer backend via sysfs Willy Tarreau
                   ` (25 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Jiufei Xue, Joseph Qi, Mark Fasheh, Joel Becker, Junxiao Bi,
	Andrew Morton, Linus Torvalds, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: xuejiufei <xuejiufei@huawei.com>

commit bef5502de074b6f6fa647b94b73155d675694420 upstream.

We have found that migration source will trigger a BUG that the refcount
of mle is already zero before put when the target is down during
migration.  The situation is as follows:

dlm_migrate_lockres
  dlm_add_migration_mle
  dlm_mark_lockres_migrating
  dlm_get_mle_inuse
  <<<<<< Now the refcount of the mle is 2.
  dlm_send_one_lockres and wait for the target to become the
  new master.
  <<<<<< o2hb detect the target down and clean the migration
  mle. Now the refcount is 1.

dlm_migrate_lockres woken, and put the mle twice when found the target
goes down which trigger the BUG with the following message:

  "ERROR: bad mle: ".

Signed-off-by: Jiufei Xue <xuejiufei@huawei.com>
Reviewed-by: Joseph Qi <joseph.qi@huawei.com>
Cc: Mark Fasheh <mfasheh@suse.de>
Cc: Joel Becker <jlbec@evilplan.org>
Cc: Junxiao Bi <junxiao.bi@oracle.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 fs/ocfs2/dlm/dlmmaster.c | 26 +++++++++++++++-----------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index ef1ac9a..e2f2c4e 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -2491,6 +2491,11 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
 	spin_lock(&dlm->master_lock);
 	ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name,
 				    namelen, target, dlm->node_num);
+	/* get an extra reference on the mle.
+	 * otherwise the assert_master from the new
+	 * master will destroy this.
+	 */
+	dlm_get_mle_inuse(mle);
 	spin_unlock(&dlm->master_lock);
 	spin_unlock(&dlm->spinlock);
 
@@ -2526,6 +2531,7 @@ fail:
 		if (mle_added) {
 			dlm_mle_detach_hb_events(dlm, mle);
 			dlm_put_mle(mle);
+			dlm_put_mle_inuse(mle);
 		} else if (mle) {
 			kmem_cache_free(dlm_mle_cache, mle);
 		}
@@ -2542,17 +2548,6 @@ fail:
 	 * ensure that all assert_master work is flushed. */
 	flush_workqueue(dlm->dlm_worker);
 
-	/* get an extra reference on the mle.
-	 * otherwise the assert_master from the new
-	 * master will destroy this.
-	 * also, make sure that all callers of dlm_get_mle
-	 * take both dlm->spinlock and dlm->master_lock */
-	spin_lock(&dlm->spinlock);
-	spin_lock(&dlm->master_lock);
-	dlm_get_mle_inuse(mle);
-	spin_unlock(&dlm->master_lock);
-	spin_unlock(&dlm->spinlock);
-
 	/* notify new node and send all lock state */
 	/* call send_one_lockres with migration flag.
 	 * this serves as notice to the target node that a
@@ -3288,6 +3283,15 @@ top:
 			    mle->new_master != dead_node)
 				continue;
 
+			if (mle->new_master == dead_node && mle->inuse) {
+				mlog(ML_NOTICE, "%s: target %u died during "
+						"migration from %u, the MLE is "
+						"still keep used, ignore it!\n",
+						dlm->name, dead_node,
+						mle->master);
+				continue;
+			}
+
 			/* If we have reached this point, this mle needs to be
 			 * removed from the list and freed. */
 			dlm_clean_migration_mle(dlm, mle);
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 30/55] ALSA: dummy: Disable switching timer backend via sysfs
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (28 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 29/55] ocfs2/dlm: ignore cleaning the migration mle that is inuse Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 31/55] ALSA: timer: Harden slave timer list handling Willy Tarreau
                   ` (24 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 7ee96216c31aabe1eb42fb91ff50dae9fcd014b2 upstream.

ALSA dummy driver can switch the timer backend between system timer
and hrtimer via its hrtimer module option.  This can be also switched
dynamically via sysfs, but it may lead to a memory corruption when
switching is done while a PCM stream is running; the stream instance
for the newly switched timer method tries to access the memory that
was allocated by another timer method although the sizes differ.

As the simplest fix, this patch just disables the switch via sysfs by
dropping the writable bit.

BugLink: http://lkml.kernel.org/r/CACT4Y+ZGEeEBntHW5WHn2GoeE0G_kRrCmUh6=dWyy-wfzvuJLg@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/drivers/dummy.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 252e04c..7136c7a 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -171,7 +171,7 @@ MODULE_PARM_DESC(pcm_substreams, "PCM substreams # (1-128) for dummy driver.");
 module_param(fake_buffer, bool, 0444);
 MODULE_PARM_DESC(fake_buffer, "Fake buffer allocations.");
 #ifdef CONFIG_HIGH_RES_TIMERS
-module_param(hrtimer, bool, 0644);
+module_param(hrtimer, bool, 0444);
 MODULE_PARM_DESC(hrtimer, "Use hrtimer as the timer source.");
 #endif
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 31/55] ALSA: timer: Harden slave timer list handling
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (29 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 30/55] ALSA: dummy: Disable switching timer backend via sysfs Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 32/55] ALSA: hrtimer: Fix stall by hrtimer_cancel() Willy Tarreau
                   ` (23 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit b5a663aa426f4884c71cd8580adae73f33570f0d upstream.

A slave timer instance might be still accessible in a racy way while
operating the master instance as it lacks of locking.  Since the
master operation is mostly protected with timer->lock, we should cope
with it while changing the slave instance, too.  Also, some linked
lists (active_list and ack_list) of slave instances aren't unlinked
immediately at stopping or closing, and this may lead to unexpected
accesses.

This patch tries to address these issues.  It adds spin lock of
timer->lock (either from master or slave, which is equivalent) in a
few places.  For avoiding a deadlock, we ensure that the global
slave_active_lock is always locked at first before each timer lock.

Also, ack and active_list of slave instances are properly unlinked at
snd_timer_stop() and snd_timer_close().

Last but not least, remove the superfluous call of _snd_timer_stop()
at removing slave links.  This is a noop, and calling it may confuse
readers wrt locking.  Further cleanup will follow in a later patch.

Actually we've got reports of use-after-free by syzkaller fuzzer, and
this hopefully fixes these issues.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 18 ++++++++++++++----
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index 4a13844..ae4742d 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -212,11 +212,13 @@ static void snd_timer_check_master(struct snd_timer_instance *master)
 		    slave->slave_id == master->slave_id) {
 			list_move_tail(&slave->open_list, &master->slave_list_head);
 			spin_lock_irq(&slave_active_lock);
+			spin_lock(&master->timer->lock);
 			slave->master = master;
 			slave->timer = master->timer;
 			if (slave->flags & SNDRV_TIMER_IFLG_RUNNING)
 				list_add_tail(&slave->active_list,
 					      &master->slave_active_head);
+			spin_unlock(&master->timer->lock);
 			spin_unlock_irq(&slave_active_lock);
 		}
 	}
@@ -340,15 +342,18 @@ int snd_timer_close(struct snd_timer_instance *timeri)
 		    timer->hw.close)
 			timer->hw.close(timer);
 		/* remove slave links */
+		spin_lock_irq(&slave_active_lock);
+		spin_lock(&timer->lock);
 		list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
 					 open_list) {
-			spin_lock_irq(&slave_active_lock);
-			_snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
 			list_move_tail(&slave->open_list, &snd_timer_slave_list);
 			slave->master = NULL;
 			slave->timer = NULL;
-			spin_unlock_irq(&slave_active_lock);
+			list_del_init(&slave->ack_list);
+			list_del_init(&slave->active_list);
 		}
+		spin_unlock(&timer->lock);
+		spin_unlock_irq(&slave_active_lock);
 		mutex_unlock(&register_mutex);
 	}
 	if (timeri->private_free)
@@ -435,9 +440,12 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
 
 	spin_lock_irqsave(&slave_active_lock, flags);
 	timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
-	if (timeri->master)
+	if (timeri->master && timeri->timer) {
+		spin_lock(&timeri->timer->lock);
 		list_add_tail(&timeri->active_list,
 			      &timeri->master->slave_active_head);
+		spin_unlock(&timeri->timer->lock);
+	}
 	spin_unlock_irqrestore(&slave_active_lock, flags);
 	return 1; /* delayed start */
 }
@@ -483,6 +491,8 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
 		if (!keep_flag) {
 			spin_lock_irqsave(&slave_active_lock, flags);
 			timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+			list_del_init(&timeri->ack_list);
+			list_del_init(&timeri->active_list);
 			spin_unlock_irqrestore(&slave_active_lock, flags);
 		}
 		goto __end;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 32/55] ALSA: hrtimer: Fix stall by hrtimer_cancel()
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (30 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 31/55] ALSA: timer: Harden slave timer list handling Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 33/55] ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode Willy Tarreau
                   ` (22 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 2ba1fe7a06d3624f9a7586d672b55f08f7c670f3 upstream.

hrtimer_cancel() waits for the completion from the callback, thus it
must not be called inside the callback itself.  This was already a
problem in the past with ALSA hrtimer driver, and the early commit
[fcfdebe70759: ALSA: hrtimer - Fix lock-up] tried to address it.

However, the previous fix is still insufficient: it may still cause a
lockup when the ALSA timer instance reprograms itself in its callback.
Then it invokes the start function even in snd_timer_interrupt() that
is called in hrtimer callback itself, results in a CPU stall.  This is
no hypothetical problem but actually triggered by syzkaller fuzzer.

This patch tries to fix the issue again.  Now we call
hrtimer_try_to_cancel() at both start and stop functions so that it
won't fall into a deadlock, yet giving some chance to cancel the queue
if the functions have been called outside the callback.  The proper
hrtimer_cancel() is called in anyway at closing, so this should be
enough.

Reported-and-tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/hrtimer.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
index 2475bda..cbccaf2 100644
--- a/sound/core/hrtimer.c
+++ b/sound/core/hrtimer.c
@@ -89,7 +89,7 @@ static int snd_hrtimer_start(struct snd_timer *t)
 	struct snd_hrtimer *stime = t->private_data;
 
 	atomic_set(&stime->running, 0);
-	hrtimer_cancel(&stime->hrt);
+	hrtimer_try_to_cancel(&stime->hrt);
 	hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
 		      HRTIMER_MODE_REL);
 	atomic_set(&stime->running, 1);
@@ -100,6 +100,7 @@ static int snd_hrtimer_stop(struct snd_timer *t)
 {
 	struct snd_hrtimer *stime = t->private_data;
 	atomic_set(&stime->running, 0);
+	hrtimer_try_to_cancel(&stime->hrt);
 	return 0;
 }
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 33/55] ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (31 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 32/55] ALSA: hrtimer: Fix stall by hrtimer_cancel() Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 34/55] ALSA: seq: Fix snd_seq_call_port_info_ioctl " Willy Tarreau
                   ` (21 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Nicolas Boichat, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Nicolas Boichat <drinkcat@chromium.org>

commit 43c54b8c7cfe22f868a751ba8a59abf1724160b1 upstream.

This reverts one hunk of
commit ef44a1ec6eee ("ALSA: sound/core: use memdup_user()"), which
replaced a number of kmalloc followed by memcpy with memdup calls.

In this case, we are copying from a struct snd_pcm_hw_params32 to
a struct snd_pcm_hw_params, but the latter is 4 bytes longer than
the 32-bit version, so we need to separate kmalloc and copy calls.

This actually leads to an out-of-bounds memory access later on
in sound/soc/soc-pcm.c:soc_pcm_hw_params() (detected using KASan).

Fixes: ef44a1ec6eee ('ALSA: sound/core: use memdup_user()')
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/pcm_compat.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 038232d..0423434 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -232,10 +232,15 @@ static int snd_pcm_ioctl_hw_params_compat(struct snd_pcm_substream *substream,
 	if (! (runtime = substream->runtime))
 		return -ENOTTY;
 
-	/* only fifo_size is different, so just copy all */
-	data = memdup_user(data32, sizeof(*data32));
-	if (IS_ERR(data))
-		return PTR_ERR(data);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	/* only fifo_size (RO from userspace) is different, so just copy all */
+	if (copy_from_user(data, data32, sizeof(*data32))) {
+		err = -EFAULT;
+		goto error;
+	}
 
 	if (refine)
 		err = snd_pcm_hw_refine(substream, data);
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 34/55] ALSA: seq: Fix snd_seq_call_port_info_ioctl in compat mode
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (32 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 33/55] ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 35/55] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0 Willy Tarreau
                   ` (20 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Nicolas Boichat, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Nicolas Boichat <drinkcat@chromium.org>

commit 9586495dc3011a80602329094e746dbce16cb1f1 upstream.

This reverts one hunk of
commit ef44a1ec6eee ("ALSA: sound/core: use memdup_user()"), which
replaced a number of kmalloc followed by memcpy with memdup calls.

In this case, we are copying from a struct snd_seq_port_info32 to a
struct snd_seq_port_info, but the latter is 4 bytes longer than the
32-bit version, so we need to separate kmalloc and copy calls.

Fixes: ef44a1ec6eee ('ALSA: sound/core: use memdup_user()')
Signed-off-by: Nicolas Boichat <drinkcat@chromium.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/seq_compat.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/sound/core/seq/seq_compat.c b/sound/core/seq/seq_compat.c
index c956fe4..9bb2c39 100644
--- a/sound/core/seq/seq_compat.c
+++ b/sound/core/seq/seq_compat.c
@@ -48,11 +48,12 @@ static int snd_seq_call_port_info_ioctl(struct snd_seq_client *client, unsigned
 	struct snd_seq_port_info *data;
 	mm_segment_t fs;
 
-	data = memdup_user(data32, sizeof(*data32));
-	if (IS_ERR(data))
-		return PTR_ERR(data);
+	data = kmalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
 
-	if (get_user(data->flags, &data32->flags) ||
+	if (copy_from_user(data, data32, sizeof(*data32)) ||
+	    get_user(data->flags, &data32->flags) ||
 	    get_user(data->time_queue, &data32->time_queue))
 		goto error;
 	data->kernel = NULL;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 35/55] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (33 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 34/55] ALSA: seq: Fix snd_seq_call_port_info_ioctl " Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 36/55] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() Willy Tarreau
                   ` (19 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit c0bcdbdff3ff73a54161fca3cb8b6cdbd0bb8762 upstream.

When a TLV ioctl with numid zero is handled, the driver may spew a
kernel warning with a stack trace at each call.  The check was
intended obviously only for a kernel driver, but not for a user
interaction.  Let's fix it.

This was spotted by syzkaller fuzzer.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/control.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/core/control.c b/sound/core/control.c
index ffa7857..e6fcf56 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1130,6 +1130,8 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
 		return -EFAULT;
 	if (tlv.length < sizeof(unsigned int) * 3)
 		return -EINVAL;
+	if (!tlv.numid)
+		return -EINVAL;
 	down_read(&card->controls_rwsem);
 	kctl = snd_ctl_find_numid(card, tlv.numid);
 	if (kctl == NULL) {
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 36/55] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup()
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (34 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 35/55] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0 Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 37/55] ALSA: seq: Degrade the error message for too many opens Willy Tarreau
                   ` (18 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 599151336638d57b98d92338aa59c048e3a3e97d upstream.

ALSA sequencer OSS emulation code has a sanity check for currently
opened devices, but there is a thinko there, eventually it spews
warnings and skips the operation wrongly like:
  WARNING: CPU: 1 PID: 7573 at sound/core/seq/oss/seq_oss_synth.c:311

Fix this off-by-one error.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/oss/seq_oss_synth.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 945a27c..97f2461 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -308,7 +308,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
 	struct seq_oss_synth *rec;
 	struct seq_oss_synthinfo *info;
 
-	if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+	if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
 		return;
 	for (i = 0; i < dp->max_synthdev; i++) {
 		info = &dp->synths[i];
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 37/55] ALSA: seq: Degrade the error message for too many opens
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (35 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 36/55] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 38/55] ALSA: seq: Fix race at closing in virmidi driver Willy Tarreau
                   ` (17 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit da10816e3d923565b470fec78a674baba794ed33 upstream.

ALSA OSS sequencer spews a kernel error message ("ALSA: seq_oss: too
many applications") when user-space tries to open more than the
limit.  This means that it can easily fill the log buffer.

Since it's merely a normal error, it's safe to suppress it via
pr_debug() instead.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
[bwh: Backported to 3.2: this was still using snd_printk()]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/oss/seq_oss_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index 1f133fe..335b7e1 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -194,7 +194,7 @@ snd_seq_oss_open(struct file *file, int level)
 
 	dp->index = i;
 	if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
-		snd_printk(KERN_ERR "too many applications\n");
+		pr_debug("ALSA: seq_oss: too many applications\n");
 		rc = -ENOMEM;
 		goto _error;
 	}
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 38/55] ALSA: seq: Fix race at closing in virmidi driver
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (36 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 37/55] ALSA: seq: Degrade the error message for too many opens Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 39/55] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check Willy Tarreau
                   ` (16 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 2d1b5c08366acd46c35a2e9aba5d650cb5bf5c19 upstream.

The virmidi driver has an open race at closing its assigned rawmidi
device, and this may lead to use-after-free in
snd_seq_deliver_single_event().

Plug the hole by properly protecting the linked list deletion and
calling in the right order in snd_virmidi_input_close().

BugLink: http://lkml.kernel.org/r/CACT4Y+Zd66+w12fNN85-425cVQT=K23kWbhnCEcMB8s3us-Frw@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/seq_virmidi.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 86e7739..081a099 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -253,9 +253,13 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
  */
 static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
 {
+	struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
 	struct snd_virmidi *vmidi = substream->runtime->private_data;
-	snd_midi_event_free(vmidi->parser);
+
+	write_lock_irq(&rdev->filelist_lock);
 	list_del(&vmidi->list);
+	write_unlock_irq(&rdev->filelist_lock);
+	snd_midi_event_free(vmidi->parser);
 	substream->runtime->private_data = NULL;
 	kfree(vmidi);
 	return 0;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 39/55] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (37 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 38/55] ALSA: seq: Fix race at closing in virmidi driver Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 40/55] ALSA: pcm: Fix potential deadlock in OSS emulation Willy Tarreau
                   ` (15 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit cc85f7a634cfaf9f0713c6aa06d08817424db37a upstream.

NULL user-space buffer can be passed even in a normal path, thus it's
not good to spew a kernel warning with stack trace at each time.
Just drop snd_BUG_ON() macro usage there.

BugLink: http://lkml.kernel.org/r/CACT4Y+YfVJ3L+q0i-4vyQVyyPD7V=OMX0PWPi29x9Bo3QaBLdw@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/rawmidi.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index e4c12a1..07aed6b 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1160,7 +1160,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
 	long count1, result;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
 
-	if (snd_BUG_ON(!kernelbuf && !userbuf))
+	if (!kernelbuf && !userbuf)
 		return -EINVAL;
 	if (snd_BUG_ON(!runtime->buffer))
 		return -EINVAL;
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 40/55] ALSA: pcm: Fix potential deadlock in OSS emulation
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (38 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 39/55] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 41/55] ALSA: seq: Fix yet another races among ALSA timer accesses Willy Tarreau
                   ` (14 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit b248371628aad599a48540962f6b85a21a8a0c3f upstream.

There are potential deadlocks in PCM OSS emulation code while
accessing read/write and mmap concurrently.  This comes from the
infamous mmap_sem usage in copy_from/to_user().  Namely,

   snd_pcm_oss_write() ->
     &runtime->oss.params_lock ->
        copy_to_user() ->
          &mm->mmap_sem
  mmap() ->
    &mm->mmap_sem ->
      snd_pcm_oss_mmap() ->
        &runtime->oss.params_lock

Since we can't avoid taking params_lock from mmap code path, use
trylock variant and aborts with -EAGAIN as a workaround of this AB/BA
deadlock.

BugLink: http://lkml.kernel.org/r/CACT4Y+bVrBKDG0G2_AcUgUQa+X91VKTeS4v+wN7BSHwHtqn3kQ@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/oss/pcm_oss.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index d9c9635..07a249e 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -826,7 +826,8 @@ static int choose_rate(struct snd_pcm_substream *substream,
 	return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
 }
 
-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
+static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+				     bool trylock)
 {
 	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct snd_pcm_hw_params *params, *sparams;
@@ -839,7 +840,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
 	struct snd_mask sformat_mask;
 	struct snd_mask mask;
 
-	if (mutex_lock_interruptible(&runtime->oss.params_lock))
+	if (trylock) {
+		if (!(mutex_trylock(&runtime->oss.params_lock)))
+			return -EAGAIN;
+	} else if (mutex_lock_interruptible(&runtime->oss.params_lock))
 		return -EINTR;
 	sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
 	params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -1079,7 +1083,7 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil
 		if (asubstream == NULL)
 			asubstream = substream;
 		if (substream->runtime->oss.params) {
-			err = snd_pcm_oss_change_params(substream);
+			err = snd_pcm_oss_change_params(substream, false);
 			if (err < 0)
 				return err;
 		}
@@ -1118,7 +1122,7 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
 		return 0;
 	runtime = substream->runtime;
 	if (runtime->oss.params) {
-		err = snd_pcm_oss_change_params(substream);
+		err = snd_pcm_oss_change_params(substream, false);
 		if (err < 0)
 			return err;
 	}
@@ -2149,7 +2153,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
 	runtime = substream->runtime;
 
 	if (runtime->oss.params &&
-	    (err = snd_pcm_oss_change_params(substream)) < 0)
+	    (err = snd_pcm_oss_change_params(substream, false)) < 0)
 		return err;
 
 	info.fragsize = runtime->oss.period_bytes;
@@ -2770,7 +2774,12 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
 		return -EIO;
 	
 	if (runtime->oss.params) {
-		if ((err = snd_pcm_oss_change_params(substream)) < 0)
+		/* use mutex_trylock() for params_lock for avoiding a deadlock
+		 * between mmap_sem and params_lock taken by
+		 * copy_from/to_user() in snd_pcm_oss_write/read()
+		 */
+		err = snd_pcm_oss_change_params(substream, true);
+		if (err < 0)
 			return err;
 	}
 #ifdef CONFIG_SND_PCM_OSS_PLUGINS
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 41/55] ALSA: seq: Fix yet another races among ALSA timer accesses
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (39 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 40/55] ALSA: pcm: Fix potential deadlock in OSS emulation Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 42/55] ALSA: timer: Fix link corruption due to double start or stop Willy Tarreau
                   ` (13 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 2cdc7b636d55cbcf42e1e6c8accd85e62d3e9ae8 upstream.

ALSA sequencer may open/close and control ALSA timer instance
dynamically either via sequencer events or direct ioctls.  These are
done mostly asynchronously, and it may call still some timer action
like snd_timer_start() while another is calling snd_timer_close().
Since the instance gets removed by snd_timer_close(), it may lead to
a use-after-free.

This patch tries to address such a race by protecting each
snd_timer_*() call via the existing spinlock and also by avoiding the
access to timer during close call.

BugLink: http://lkml.kernel.org/r/CACT4Y+Z6RzW5MBr-HUdV-8zwg71WQfKTdPpYGvOeS7v4cyurNQ@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/seq_timer.c | 87 +++++++++++++++++++++++++++++++++++-----------
 1 file changed, 67 insertions(+), 20 deletions(-)

diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index c2ec4ef..4a9edcb 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -93,6 +93,9 @@ void snd_seq_timer_delete(struct snd_seq_timer **tmr)
 
 void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
 {
+	unsigned long flags;
+
+	spin_lock_irqsave(&tmr->lock, flags);
 	/* setup defaults */
 	tmr->ppq = 96;		/* 96 PPQ */
 	tmr->tempo = 500000;	/* 120 BPM */
@@ -108,21 +111,25 @@ void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
 	tmr->preferred_resolution = seq_default_timer_resolution;
 
 	tmr->skew = tmr->skew_base = SKEW_BASE;
+	spin_unlock_irqrestore(&tmr->lock, flags);
 }
 
-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
+static void seq_timer_reset(struct snd_seq_timer *tmr)
 {
-	unsigned long flags;
-
-	spin_lock_irqsave(&tmr->lock, flags);
-
 	/* reset time & songposition */
 	tmr->cur_time.tv_sec = 0;
 	tmr->cur_time.tv_nsec = 0;
 
 	tmr->tick.cur_tick = 0;
 	tmr->tick.fraction = 0;
+}
+
+void snd_seq_timer_reset(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
 
+	spin_lock_irqsave(&tmr->lock, flags);
+	seq_timer_reset(tmr);
 	spin_unlock_irqrestore(&tmr->lock, flags);
 }
 
@@ -141,8 +148,11 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
 	tmr = q->timer;
 	if (tmr == NULL)
 		return;
-	if (!tmr->running)
+	spin_lock_irqsave(&tmr->lock, flags);
+	if (!tmr->running) {
+		spin_unlock_irqrestore(&tmr->lock, flags);
 		return;
+	}
 
 	resolution *= ticks;
 	if (tmr->skew != tmr->skew_base) {
@@ -151,8 +161,6 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
 			(((resolution & 0xffff) * tmr->skew) >> 16);
 	}
 
-	spin_lock_irqsave(&tmr->lock, flags);
-
 	/* update timer */
 	snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
 
@@ -299,26 +307,30 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
 	t->callback = snd_seq_timer_interrupt;
 	t->callback_data = q;
 	t->flags |= SNDRV_TIMER_IFLG_AUTO;
+	spin_lock_irq(&tmr->lock);
 	tmr->timeri = t;
+	spin_unlock_irq(&tmr->lock);
 	return 0;
 }
 
 int snd_seq_timer_close(struct snd_seq_queue *q)
 {
 	struct snd_seq_timer *tmr;
+	struct snd_timer_instance *t;
 	
 	tmr = q->timer;
 	if (snd_BUG_ON(!tmr))
 		return -EINVAL;
-	if (tmr->timeri) {
-		snd_timer_stop(tmr->timeri);
-		snd_timer_close(tmr->timeri);
-		tmr->timeri = NULL;
-	}
+	spin_lock_irq(&tmr->lock);
+	t = tmr->timeri;
+	tmr->timeri = NULL;
+	spin_unlock_irq(&tmr->lock);
+	if (t)
+		snd_timer_close(t);
 	return 0;
 }
 
-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
+static int seq_timer_stop(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
@@ -329,6 +341,17 @@ int snd_seq_timer_stop(struct snd_seq_timer * tmr)
 	return 0;
 }
 
+int snd_seq_timer_stop(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_stop(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
 static int initialize_timer(struct snd_seq_timer *tmr)
 {
 	struct snd_timer *t;
@@ -361,13 +384,13 @@ static int initialize_timer(struct snd_seq_timer *tmr)
 	return 0;
 }
 
-int snd_seq_timer_start(struct snd_seq_timer * tmr)
+static int seq_timer_start(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
 	if (tmr->running)
-		snd_seq_timer_stop(tmr);
-	snd_seq_timer_reset(tmr);
+		seq_timer_stop(tmr);
+	seq_timer_reset(tmr);
 	if (initialize_timer(tmr) < 0)
 		return -EINVAL;
 	snd_timer_start(tmr->timeri, tmr->ticks);
@@ -376,14 +399,25 @@ int snd_seq_timer_start(struct snd_seq_timer * tmr)
 	return 0;
 }
 
-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
+int snd_seq_timer_start(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_start(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
+static int seq_timer_continue(struct snd_seq_timer *tmr)
 {
 	if (! tmr->timeri)
 		return -EINVAL;
 	if (tmr->running)
 		return -EBUSY;
 	if (! tmr->initialized) {
-		snd_seq_timer_reset(tmr);
+		seq_timer_reset(tmr);
 		if (initialize_timer(tmr) < 0)
 			return -EINVAL;
 	}
@@ -393,11 +427,24 @@ int snd_seq_timer_continue(struct snd_seq_timer * tmr)
 	return 0;
 }
 
+int snd_seq_timer_continue(struct snd_seq_timer *tmr)
+{
+	unsigned long flags;
+	int err;
+
+	spin_lock_irqsave(&tmr->lock, flags);
+	err = seq_timer_continue(tmr);
+	spin_unlock_irqrestore(&tmr->lock, flags);
+	return err;
+}
+
 /* return current 'real' time. use timeofday() to get better granularity. */
 snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
 {
 	snd_seq_real_time_t cur_time;
+	unsigned long flags;
 
+	spin_lock_irqsave(&tmr->lock, flags);
 	cur_time = tmr->cur_time;
 	if (tmr->running) { 
 		struct timeval tm;
@@ -413,7 +460,7 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
 		}
 		snd_seq_sanity_real_time(&cur_time);
 	}
-                
+	spin_unlock_irqrestore(&tmr->lock, flags);
 	return cur_time;	
 }
 
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 42/55] ALSA: timer: Fix link corruption due to double start or stop
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (40 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 41/55] ALSA: seq: Fix yet another races among ALSA timer accesses Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 43/55] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free Willy Tarreau
                   ` (12 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit f784beb75ce82f4136f8a0960d3ee872f7109e09 upstream.

Although ALSA timer code got hardening for races, it still causes
use-after-free error.  This is however rather a corrupted linked list,
not actually the concurrent accesses.  Namely, when timer start is
triggered twice, list_add_tail() is called twice, too.  This ends
up with the link corruption and triggers KASAN error.

The simplest fix would be replacing list_add_tail() with
list_move_tail(), but fundamentally it's the problem that we don't
check the double start/stop correctly.  So, the right fix here is to
add the proper checks to snd_timer_start() and snd_timer_stop() (and
their variants).

BugLink: http://lkml.kernel.org/r/CACT4Y+ZyPRoMQjmawbvmCEDrkBD2BQuH7R09=eOkf5ESK8kJAw@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
[bwh: Backported to 3.2: adjust context, indentation]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 30 ++++++++++++++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index ae4742d..21f5df6 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -439,6 +439,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
 	unsigned long flags;
 
 	spin_lock_irqsave(&slave_active_lock, flags);
+	if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
+		spin_unlock_irqrestore(&slave_active_lock, flags);
+		return -EBUSY;
+	}
 	timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
 	if (timeri->master && timeri->timer) {
 		spin_lock(&timeri->timer->lock);
@@ -463,18 +467,26 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
 		return -EINVAL;
 	if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
 		result = snd_timer_start_slave(timeri);
-		snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+		if (result >= 0)
+			snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
 		return result;
 	}
 	timer = timeri->timer;
 	if (timer == NULL)
 		return -EINVAL;
 	spin_lock_irqsave(&timer->lock, flags);
+	if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
+			     SNDRV_TIMER_IFLG_START)) {
+		result = -EBUSY;
+		goto unlock;
+	}
 	timeri->ticks = timeri->cticks = ticks;
 	timeri->pticks = 0;
 	result = snd_timer_start1(timer, timeri, ticks);
+ unlock:
 	spin_unlock_irqrestore(&timer->lock, flags);
-	snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+	if (result >= 0)
+		snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
 	return result;
 }
 
@@ -490,6 +502,10 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
 	if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
 		if (!keep_flag) {
 			spin_lock_irqsave(&slave_active_lock, flags);
+			if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
+				spin_unlock_irqrestore(&slave_active_lock, flags);
+				return -EBUSY;
+			}
 			timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
 			list_del_init(&timeri->ack_list);
 			list_del_init(&timeri->active_list);
@@ -501,6 +517,11 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
 	if (!timer)
 		return -EINVAL;
 	spin_lock_irqsave(&timer->lock, flags);
+	if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
+			       SNDRV_TIMER_IFLG_START))) {
+		spin_unlock_irqrestore(&timer->lock, flags);
+		return -EBUSY;
+	}
 	list_del_init(&timeri->ack_list);
 	list_del_init(&timeri->active_list);
 	if ((timeri->flags & SNDRV_TIMER_IFLG_RUNNING) &&
@@ -566,10 +587,15 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
 	if (! timer)
 		return -EINVAL;
 	spin_lock_irqsave(&timer->lock, flags);
+	if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
+		result = -EBUSY;
+		goto unlock;
+	}
 	if (!timeri->cticks)
 		timeri->cticks = 1;
 	timeri->pticks = 0;
 	result = snd_timer_start1(timer, timeri, timer->sticks);
+ unlock:
 	spin_unlock_irqrestore(&timer->lock, flags);
 	snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
 	return result;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 43/55] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (41 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 42/55] ALSA: timer: Fix link corruption due to double start or stop Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 44/55] ALSA: rawmidi: Fix race at copying & updating the position Willy Tarreau
                   ` (11 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 06ab30034ed9c200a570ab13c017bde248ddb2a6 upstream.

A kernel WARNING in snd_rawmidi_transmit_ack() is triggered by
syzkaller fuzzer:
  WARNING: CPU: 1 PID: 20739 at sound/core/rawmidi.c:1136
Call Trace:
 [<     inline     >] __dump_stack lib/dump_stack.c:15
 [<ffffffff82999e2d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
 [<ffffffff81352089>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
 [<ffffffff813522b9>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
 [<ffffffff84f80bd5>] snd_rawmidi_transmit_ack+0x275/0x400 sound/core/rawmidi.c:1136
 [<ffffffff84fdb3c1>] snd_virmidi_output_trigger+0x4b1/0x5a0 sound/core/seq/seq_virmidi.c:163
 [<     inline     >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
 [<ffffffff84f87ed9>] snd_rawmidi_kernel_write1+0x549/0x780 sound/core/rawmidi.c:1223
 [<ffffffff84f89fd3>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1273
 [<ffffffff817b0323>] __vfs_write+0x113/0x480 fs/read_write.c:528
 [<ffffffff817b1db7>] vfs_write+0x167/0x4a0 fs/read_write.c:577
 [<     inline     >] SYSC_write fs/read_write.c:624
 [<ffffffff817b50a1>] SyS_write+0x111/0x220 fs/read_write.c:616
 [<ffffffff86336c36>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185

Also a similar warning is found but in another path:
Call Trace:
 [<     inline     >] __dump_stack lib/dump_stack.c:15
 [<ffffffff82be2c0d>] dump_stack+0x6f/0xa2 lib/dump_stack.c:50
 [<ffffffff81355139>] warn_slowpath_common+0xd9/0x140 kernel/panic.c:482
 [<ffffffff81355369>] warn_slowpath_null+0x29/0x30 kernel/panic.c:515
 [<ffffffff8527e69a>] rawmidi_transmit_ack+0x24a/0x3b0 sound/core/rawmidi.c:1133
 [<ffffffff8527e851>] snd_rawmidi_transmit_ack+0x51/0x80 sound/core/rawmidi.c:1163
 [<ffffffff852d9046>] snd_virmidi_output_trigger+0x2b6/0x570 sound/core/seq/seq_virmidi.c:185
 [<     inline     >] snd_rawmidi_output_trigger sound/core/rawmidi.c:150
 [<ffffffff85285a0b>] snd_rawmidi_kernel_write1+0x4bb/0x760 sound/core/rawmidi.c:1252
 [<ffffffff85287b73>] snd_rawmidi_write+0x543/0xb30 sound/core/rawmidi.c:1302
 [<ffffffff817ba5f3>] __vfs_write+0x113/0x480 fs/read_write.c:528
 [<ffffffff817bc087>] vfs_write+0x167/0x4a0 fs/read_write.c:577
 [<     inline     >] SYSC_write fs/read_write.c:624
 [<ffffffff817bf371>] SyS_write+0x111/0x220 fs/read_write.c:616
 [<ffffffff86660276>] entry_SYSCALL_64_fastpath+0x16/0x7a arch/x86/entry/entry_64.S:185

In the former case, the reason is that virmidi has an open code
calling snd_rawmidi_transmit_ack() with the value calculated outside
the spinlock.   We may use snd_rawmidi_transmit() in a loop just for
consuming the input data, but even there, there is a race between
snd_rawmidi_transmit_peek() and snd_rawmidi_tranmit_ack().

Similarly in the latter case, it calls snd_rawmidi_transmit_peek() and
snd_rawmidi_tranmit_ack() separately without protection, so they are
racy as well.

The patch tries to address these issues by the following ways:
- Introduce the unlocked versions of snd_rawmidi_transmit_peek() and
  snd_rawmidi_transmit_ack() to be called inside the explicit lock.
- Rewrite snd_rawmidi_transmit() to be race-free (the former case).
- Make the split calls (the latter case) protected in the rawmidi spin
  lock.

BugLink: http://lkml.kernel.org/r/CACT4Y+YPq1+cYLkadwjWa5XjzF1_Vki1eHnVn-Lm0hzhSpu5PA@mail.gmail.com
BugLink: http://lkml.kernel.org/r/CACT4Y+acG4iyphdOZx47Nyq_VHGbpJQK-6xNpiqUjaZYqsXOGw@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 include/sound/rawmidi.h      |  4 ++
 sound/core/rawmidi.c         | 98 ++++++++++++++++++++++++++++++++------------
 sound/core/seq/seq_virmidi.c | 17 +++++---
 3 files changed, 88 insertions(+), 31 deletions(-)

diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index c23c265..b06c4f1 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -163,6 +163,10 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
 int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
 			 unsigned char *buffer, int count);
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+			      unsigned char *buffer, int count);
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
+			       int count);
 
 /* main midi functions */
 
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 07aed6b..d3447b3f 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -1042,23 +1042,16 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
 }
 
 /**
- * snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
  * @substream: the rawmidi substream
  * @buffer: the buffer pointer
  * @count: data size to transfer
  *
- * Copies data from the internal output buffer to the given buffer.
- *
- * Call this in the interrupt handler when the midi output is ready,
- * and call snd_rawmidi_transmit_ack() after the transmission is
- * finished.
- *
- * Returns the size of copied data, or a negative error code on failure.
+ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
  */
-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 			      unsigned char *buffer, int count)
 {
-	unsigned long flags;
 	int result, count1;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
 
@@ -1067,7 +1060,6 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 		return -EINVAL;
 	}
 	result = 0;
-	spin_lock_irqsave(&runtime->lock, flags);
 	if (runtime->avail >= runtime->buffer_size) {
 		/* warning: lowlevel layer MUST trigger down the hardware */
 		goto __skip;
@@ -1092,31 +1084,52 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
 		}
 	}
       __skip:
-	spin_unlock_irqrestore(&runtime->lock, flags);
 	return result;
 }
+EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
 
 /**
- * snd_rawmidi_transmit_ack - acknowledge the transmission
+ * snd_rawmidi_transmit_peek - copy data from the internal buffer
  * @substream: the rawmidi substream
- * @count: the tranferred count
+ * @buffer: the buffer pointer
+ * @count: data size to transfer
  *
- * Advances the hardware pointer for the internal output buffer with
- * the given size and updates the condition.
- * Call after the transmission is finished.
+ * Copies data from the internal output buffer to the given buffer.
+ *
+ * Call this in the interrupt handler when the midi output is ready,
+ * and call snd_rawmidi_transmit_ack() after the transmission is
+ * finished.
  *
- * Returns the advanced size if successful, or a negative error code on failure.
+ * Return: The size of copied data, or a negative error code on failure.
  */
-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+			      unsigned char *buffer, int count)
 {
+	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	int result;
 	unsigned long flags;
+
+	spin_lock_irqsave(&runtime->lock, flags);
+	result = __snd_rawmidi_transmit_peek(substream, buffer, count);
+	spin_unlock_irqrestore(&runtime->lock, flags);
+	return result;
+}
+
+/**
+ * __snd_rawmidi_transmit_ack - acknowledge the transmission
+ * @substream: the rawmidi substream
+ * @count: the tranferred count
+ *
+ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
+ */
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+{
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
 
 	if (runtime->buffer == NULL) {
 		snd_printd("snd_rawmidi_transmit_ack: output is not active!!!\n");
 		return -EINVAL;
 	}
-	spin_lock_irqsave(&runtime->lock, flags);
 	snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
 	runtime->hw_ptr += count;
 	runtime->hw_ptr %= runtime->buffer_size;
@@ -1126,9 +1139,32 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
 		if (runtime->drain || snd_rawmidi_ready(substream))
 			wake_up(&runtime->sleep);
 	}
-	spin_unlock_irqrestore(&runtime->lock, flags);
 	return count;
 }
+EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
+
+/**
+ * snd_rawmidi_transmit_ack - acknowledge the transmission
+ * @substream: the rawmidi substream
+ * @count: the transferred count
+ *
+ * Advances the hardware pointer for the internal output buffer with
+ * the given size and updates the condition.
+ * Call after the transmission is finished.
+ *
+ * Return: The advanced size if successful, or a negative error code on failure.
+ */
+int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+{
+	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&runtime->lock, flags);
+	result = __snd_rawmidi_transmit_ack(substream, count);
+	spin_unlock_irqrestore(&runtime->lock, flags);
+	return result;
+}
 
 /**
  * snd_rawmidi_transmit - copy from the buffer to the device
@@ -1143,12 +1179,22 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
 int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
 			 unsigned char *buffer, int count)
 {
+	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	int result;
+	unsigned long flags;
+
+	spin_lock_irqsave(&runtime->lock, flags);
 	if (!substream->opened)
-		return -EBADFD;
-	count = snd_rawmidi_transmit_peek(substream, buffer, count);
-	if (count < 0)
-		return count;
-	return snd_rawmidi_transmit_ack(substream, count);
+		result = -EBADFD;
+	else {
+		count = __snd_rawmidi_transmit_peek(substream, buffer, count);
+		if (count <= 0)
+			result = count;
+		else
+			result = __snd_rawmidi_transmit_ack(substream, count);
+	}
+	spin_unlock_irqrestore(&runtime->lock, flags);
+	return result;
 }
 
 static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 081a099..0473560 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -154,21 +154,26 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
 	struct snd_virmidi *vmidi = substream->runtime->private_data;
 	int count, res;
 	unsigned char buf[32], *pbuf;
+	unsigned long flags;
 
 	if (up) {
 		vmidi->trigger = 1;
 		if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
 		    !(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
-			snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
-			return;		/* ignored */
+			while (snd_rawmidi_transmit(substream, buf,
+						    sizeof(buf)) > 0) {
+				/* ignored */
+			}
+			return;
 		}
 		if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
 			if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
 				return;
 			vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
 		}
+		spin_lock_irqsave(&substream->runtime->lock, flags);
 		while (1) {
-			count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+			count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
 			if (count <= 0)
 				break;
 			pbuf = buf;
@@ -178,16 +183,18 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
 					snd_midi_event_reset_encode(vmidi->parser);
 					continue;
 				}
-				snd_rawmidi_transmit_ack(substream, res);
+				__snd_rawmidi_transmit_ack(substream, res);
 				pbuf += res;
 				count -= res;
 				if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
 					if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
-						return;
+						goto out;
 					vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
 				}
 			}
 		}
+	out:
+		spin_unlock_irqrestore(&substream->runtime->lock, flags);
 	} else {
 		vmidi->trigger = 0;
 	}
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 44/55] ALSA: rawmidi: Fix race at copying & updating the position
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (42 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 43/55] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 45/55] ALSA: seq: Fix lockdep warnings due to double mutex locks Willy Tarreau
                   ` (10 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 81f577542af15640cbcb6ef68baa4caa610cbbfc upstream.

The rawmidi read and write functions manage runtime stream status
such as runtime->appl_ptr and runtime->avail.  These point where to
copy the new data and how many bytes have been copied (or to be
read).  The problem is that rawmidi read/write call copy_from_user()
or copy_to_user(), and the runtime spinlock is temporarily unlocked
and relocked while copying user-space.  Since the current code
advances and updates the runtime status after the spin unlock/relock,
the copy and the update may be asynchronous, and eventually
runtime->avail might go to a negative value when many concurrent
accesses are done.  This may lead to memory corruption in the end.

For fixing this race, in this patch, the status update code is
performed in the same lock before the temporary unlock.  Also, the
spinlock is now taken more widely in snd_rawmidi_kernel_read1() for
protecting more properly during the whole operation.

BugLink: http://lkml.kernel.org/r/CACT4Y+b-dCmNf1GpgPKfDO0ih+uZCL2JV4__j-r1kdhPLSgQCQ@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/rawmidi.c | 34 ++++++++++++++++++++++------------
 1 file changed, 22 insertions(+), 12 deletions(-)

diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index d3447b3f..8c381fd 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -934,31 +934,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
 	unsigned long flags;
 	long result = 0, count1;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	unsigned long appl_ptr;
 
+	spin_lock_irqsave(&runtime->lock, flags);
 	while (count > 0 && runtime->avail) {
 		count1 = runtime->buffer_size - runtime->appl_ptr;
 		if (count1 > count)
 			count1 = count;
-		spin_lock_irqsave(&runtime->lock, flags);
 		if (count1 > (int)runtime->avail)
 			count1 = runtime->avail;
+
+		/* update runtime->appl_ptr before unlocking for userbuf */
+		appl_ptr = runtime->appl_ptr;
+		runtime->appl_ptr += count1;
+		runtime->appl_ptr %= runtime->buffer_size;
+		runtime->avail -= count1;
+
 		if (kernelbuf)
-			memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
+			memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
 		if (userbuf) {
 			spin_unlock_irqrestore(&runtime->lock, flags);
 			if (copy_to_user(userbuf + result,
-					 runtime->buffer + runtime->appl_ptr, count1)) {
+					 runtime->buffer + appl_ptr, count1)) {
 				return result > 0 ? result : -EFAULT;
 			}
 			spin_lock_irqsave(&runtime->lock, flags);
 		}
-		runtime->appl_ptr += count1;
-		runtime->appl_ptr %= runtime->buffer_size;
-		runtime->avail -= count1;
-		spin_unlock_irqrestore(&runtime->lock, flags);
 		result += count1;
 		count -= count1;
 	}
+	spin_unlock_irqrestore(&runtime->lock, flags);
 	return result;
 }
 
@@ -1205,6 +1210,7 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
 	unsigned long flags;
 	long count1, result;
 	struct snd_rawmidi_runtime *runtime = substream->runtime;
+	unsigned long appl_ptr;
 
 	if (!kernelbuf && !userbuf)
 		return -EINVAL;
@@ -1225,12 +1231,19 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
 			count1 = count;
 		if (count1 > (long)runtime->avail)
 			count1 = runtime->avail;
+
+		/* update runtime->appl_ptr before unlocking for userbuf */
+		appl_ptr = runtime->appl_ptr;
+		runtime->appl_ptr += count1;
+		runtime->appl_ptr %= runtime->buffer_size;
+		runtime->avail -= count1;
+
 		if (kernelbuf)
-			memcpy(runtime->buffer + runtime->appl_ptr,
+			memcpy(runtime->buffer + appl_ptr,
 			       kernelbuf + result, count1);
 		else if (userbuf) {
 			spin_unlock_irqrestore(&runtime->lock, flags);
-			if (copy_from_user(runtime->buffer + runtime->appl_ptr,
+			if (copy_from_user(runtime->buffer + appl_ptr,
 					   userbuf + result, count1)) {
 				spin_lock_irqsave(&runtime->lock, flags);
 				result = result > 0 ? result : -EFAULT;
@@ -1238,9 +1251,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
 			}
 			spin_lock_irqsave(&runtime->lock, flags);
 		}
-		runtime->appl_ptr += count1;
-		runtime->appl_ptr %= runtime->buffer_size;
-		runtime->avail -= count1;
 		result += count1;
 		count -= count1;
 	}
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 45/55] ALSA: seq: Fix lockdep warnings due to double mutex locks
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (43 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 44/55] ALSA: rawmidi: Fix race at copying & updating the position Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 46/55] ALSA: timer: Fix double unlink of active_list Willy Tarreau
                   ` (9 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 7f0973e973cd74aa40747c9d38844560cd184ee8 upstream.

The port subscription code uses double mutex locks for source and
destination ports, and this may become racy once when wrongly set up.
It leads to lockdep warning splat, typically triggered by fuzzer like
syzkaller, although the actual deadlock hasn't been seen, so far.

This patch simplifies the handling by reducing to two single locks, so
that no lockdep warning will be trigger any longer.

By splitting to two actions, a still-in-progress element shall be
added in one list while handling another.  For ignoring this element,
a new check is added in deliver_to_subscribers().

Along with it, the code to add/remove the subscribers list element was
cleaned up and refactored.

BugLink: http://lkml.kernel.org/r/CACT4Y+aKQXV7xkBW9hpQbzaDO7LrUvohxWh-UwMxXjDy-yBD=A@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/seq_clientmgr.c |   3 +
 sound/core/seq/seq_ports.c     | 233 +++++++++++++++++++++++------------------
 2 files changed, 133 insertions(+), 103 deletions(-)

diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 8ca2be3..84aac18 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -672,6 +672,9 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
 	else
 		down_read(&grp->list_mutex);
 	list_for_each_entry(subs, &grp->list_head, src_list) {
+		/* both ports ready? */
+		if (atomic_read(&subs->ref_count) != 2)
+			continue;
 		event->dest = subs->info.dest;
 		if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
 			/* convert time according to flag with subscription */
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 3bf7d73..b824d32 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -174,10 +174,6 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
 }
 
 /* */
-enum group_type {
-	SRC_LIST, DEST_LIST
-};
-
 static int subscribe_port(struct snd_seq_client *client,
 			  struct snd_seq_client_port *port,
 			  struct snd_seq_port_subs_info *grp,
@@ -204,6 +200,20 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
 	return NULL;
 }
 
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+					struct snd_seq_client_port *port,
+					struct snd_seq_subscribers *subs,
+					bool is_src, bool ack);
+
+static inline struct snd_seq_subscribers *
+get_subscriber(struct list_head *p, bool is_src)
+{
+	if (is_src)
+		return list_entry(p, struct snd_seq_subscribers, src_list);
+	else
+		return list_entry(p, struct snd_seq_subscribers, dest_list);
+}
+
 /*
  * remove all subscribers on the list
  * this is called from port_delete, for each src and dest list.
@@ -211,7 +221,7 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
 static void clear_subscriber_list(struct snd_seq_client *client,
 				  struct snd_seq_client_port *port,
 				  struct snd_seq_port_subs_info *grp,
-				  int grptype)
+				  int is_src)
 {
 	struct list_head *p, *n;
 
@@ -220,15 +230,13 @@ static void clear_subscriber_list(struct snd_seq_client *client,
 		struct snd_seq_client *c;
 		struct snd_seq_client_port *aport;
 
-		if (grptype == SRC_LIST) {
-			subs = list_entry(p, struct snd_seq_subscribers, src_list);
+		subs = get_subscriber(p, is_src);
+		if (is_src)
 			aport = get_client_port(&subs->info.dest, &c);
-		} else {
-			subs = list_entry(p, struct snd_seq_subscribers, dest_list);
+		else
 			aport = get_client_port(&subs->info.sender, &c);
-		}
-		list_del(p);
-		unsubscribe_port(client, port, grp, &subs->info, 0);
+		delete_and_unsubscribe_port(client, port, subs, is_src, false);
+
 		if (!aport) {
 			/* looks like the connected port is being deleted.
 			 * we decrease the counter, and when both ports are deleted
@@ -236,21 +244,14 @@ static void clear_subscriber_list(struct snd_seq_client *client,
 			 */
 			if (atomic_dec_and_test(&subs->ref_count))
 				kfree(subs);
-		} else {
-			/* ok we got the connected port */
-			struct snd_seq_port_subs_info *agrp;
-			agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
-			down_write(&agrp->list_mutex);
-			if (grptype == SRC_LIST)
-				list_del(&subs->dest_list);
-			else
-				list_del(&subs->src_list);
-			up_write(&agrp->list_mutex);
-			unsubscribe_port(c, aport, agrp, &subs->info, 1);
-			kfree(subs);
-			snd_seq_port_unlock(aport);
-			snd_seq_client_unlock(c);
+			continue;
 		}
+
+		/* ok we got the connected port */
+		delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
+		kfree(subs);
+		snd_seq_port_unlock(aport);
+		snd_seq_client_unlock(c);
 	}
 }
 
@@ -263,8 +264,8 @@ static int port_delete(struct snd_seq_client *client,
 	snd_use_lock_sync(&port->use_lock); 
 
 	/* clear subscribers info */
-	clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
-	clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
+	clear_subscriber_list(client, port, &port->c_src, true);
+	clear_subscriber_list(client, port, &port->c_dest, false);
 
 	if (port->private_free)
 		port->private_free(port->private_data);
@@ -483,85 +484,120 @@ static int match_subs_info(struct snd_seq_port_subscribe *r,
 	return 0;
 }
 
-
-/* connect two ports */
-int snd_seq_port_connect(struct snd_seq_client *connector,
-			 struct snd_seq_client *src_client,
-			 struct snd_seq_client_port *src_port,
-			 struct snd_seq_client *dest_client,
-			 struct snd_seq_client_port *dest_port,
-			 struct snd_seq_port_subscribe *info)
+static int check_and_subscribe_port(struct snd_seq_client *client,
+				    struct snd_seq_client_port *port,
+				    struct snd_seq_subscribers *subs,
+				    bool is_src, bool exclusive, bool ack)
 {
-	struct snd_seq_port_subs_info *src = &src_port->c_src;
-	struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
-	struct snd_seq_subscribers *subs, *s;
-	int err, src_called = 0;
-	unsigned long flags;
-	int exclusive;
+	struct snd_seq_port_subs_info *grp;
+	struct list_head *p;
+	struct snd_seq_subscribers *s;
+	int err;
 
-	subs = kzalloc(sizeof(*subs), GFP_KERNEL);
-	if (! subs)
-		return -ENOMEM;
-
-	subs->info = *info;
-	atomic_set(&subs->ref_count, 2);
-
-	down_write(&src->list_mutex);
-	down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
-	exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
+	grp = is_src ? &port->c_src : &port->c_dest;
 	err = -EBUSY;
+	down_write(&grp->list_mutex);
 	if (exclusive) {
-		if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
+		if (!list_empty(&grp->list_head))
 			goto __error;
 	} else {
-		if (src->exclusive || dest->exclusive)
+		if (grp->exclusive)
 			goto __error;
 		/* check whether already exists */
-		list_for_each_entry(s, &src->list_head, src_list) {
-			if (match_subs_info(info, &s->info))
-				goto __error;
-		}
-		list_for_each_entry(s, &dest->list_head, dest_list) {
-			if (match_subs_info(info, &s->info))
+		list_for_each(p, &grp->list_head) {
+			s = get_subscriber(p, is_src);
+			if (match_subs_info(&subs->info, &s->info))
 				goto __error;
 		}
 	}
 
-	if ((err = subscribe_port(src_client, src_port, src, info,
-				  connector->number != src_client->number)) < 0)
-		goto __error;
-	src_called = 1;
-
-	if ((err = subscribe_port(dest_client, dest_port, dest, info,
-				  connector->number != dest_client->number)) < 0)
+	err = subscribe_port(client, port, grp, &subs->info, ack);
+	if (err < 0) {
+		grp->exclusive = 0;
 		goto __error;
+	}
 
 	/* add to list */
-	write_lock_irqsave(&src->list_lock, flags);
-	// write_lock(&dest->list_lock); // no other lock yet
-	list_add_tail(&subs->src_list, &src->list_head);
-	list_add_tail(&subs->dest_list, &dest->list_head);
-	// write_unlock(&dest->list_lock); // no other lock yet
-	write_unlock_irqrestore(&src->list_lock, flags);
+	write_lock_irq(&grp->list_lock);
+	if (is_src)
+		list_add_tail(&subs->src_list, &grp->list_head);
+	else
+		list_add_tail(&subs->dest_list, &grp->list_head);
+	grp->exclusive = exclusive;
+	atomic_inc(&subs->ref_count);
+	write_unlock_irq(&grp->list_lock);
+	err = 0;
+
+ __error:
+	up_write(&grp->list_mutex);
+	return err;
+}
 
-	src->exclusive = dest->exclusive = exclusive;
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+					struct snd_seq_client_port *port,
+					struct snd_seq_subscribers *subs,
+					bool is_src, bool ack)
+{
+	struct snd_seq_port_subs_info *grp;
+
+	grp = is_src ? &port->c_src : &port->c_dest;
+	down_write(&grp->list_mutex);
+	write_lock_irq(&grp->list_lock);
+	if (is_src)
+		list_del(&subs->src_list);
+	else
+		list_del(&subs->dest_list);
+	grp->exclusive = 0;
+	write_unlock_irq(&grp->list_lock);
+	up_write(&grp->list_mutex);
+
+	unsubscribe_port(client, port, grp, &subs->info, ack);
+}
+
+/* connect two ports */
+int snd_seq_port_connect(struct snd_seq_client *connector,
+			 struct snd_seq_client *src_client,
+			 struct snd_seq_client_port *src_port,
+			 struct snd_seq_client *dest_client,
+			 struct snd_seq_client_port *dest_port,
+			 struct snd_seq_port_subscribe *info)
+{
+	struct snd_seq_subscribers *subs;
+	bool exclusive;
+	int err;
+
+	subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+	if (!subs)
+		return -ENOMEM;
+
+	subs->info = *info;
+	atomic_set(&subs->ref_count, 0);
+	INIT_LIST_HEAD(&subs->src_list);
+	INIT_LIST_HEAD(&subs->dest_list);
+
+	exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
+
+	err = check_and_subscribe_port(src_client, src_port, subs, true,
+				       exclusive,
+				       connector->number != src_client->number);
+	if (err < 0)
+		goto error;
+	err = check_and_subscribe_port(dest_client, dest_port, subs, false,
+				       exclusive,
+				       connector->number != dest_client->number);
+	if (err < 0)
+		goto error_dest;
 
-	up_write(&dest->list_mutex);
-	up_write(&src->list_mutex);
 	return 0;
 
- __error:
-	if (src_called)
-		unsubscribe_port(src_client, src_port, src, info,
-				 connector->number != src_client->number);
+ error_dest:
+	delete_and_unsubscribe_port(src_client, src_port, subs, true,
+				    connector->number != src_client->number);
+ error:
 	kfree(subs);
-	up_write(&dest->list_mutex);
-	up_write(&src->list_mutex);
 	return err;
 }
 
-
 /* remove the connection */
 int snd_seq_port_disconnect(struct snd_seq_client *connector,
 			    struct snd_seq_client *src_client,
@@ -571,37 +607,28 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
 			    struct snd_seq_port_subscribe *info)
 {
 	struct snd_seq_port_subs_info *src = &src_port->c_src;
-	struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
 	struct snd_seq_subscribers *subs;
 	int err = -ENOENT;
-	unsigned long flags;
 
 	down_write(&src->list_mutex);
-	down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
 	/* look for the connection */
 	list_for_each_entry(subs, &src->list_head, src_list) {
 		if (match_subs_info(info, &subs->info)) {
-			write_lock_irqsave(&src->list_lock, flags);
-			// write_lock(&dest->list_lock);  // no lock yet
-			list_del(&subs->src_list);
-			list_del(&subs->dest_list);
-			// write_unlock(&dest->list_lock);
-			write_unlock_irqrestore(&src->list_lock, flags);
-			src->exclusive = dest->exclusive = 0;
-			unsubscribe_port(src_client, src_port, src, info,
-					 connector->number != src_client->number);
-			unsubscribe_port(dest_client, dest_port, dest, info,
-					 connector->number != dest_client->number);
-			kfree(subs);
+			atomic_dec(&subs->ref_count); /* mark as not ready */
 			err = 0;
 			break;
 		}
 	}
-
-	up_write(&dest->list_mutex);
 	up_write(&src->list_mutex);
-	return err;
+	if (err < 0)
+		return err;
+
+	delete_and_unsubscribe_port(src_client, src_port, subs, true,
+				    connector->number != src_client->number);
+	delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
+				    connector->number != dest_client->number);
+	kfree(subs);
+	return 0;
 }
 
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 46/55] ALSA: timer: Fix double unlink of active_list
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (44 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 45/55] ALSA: seq: Fix lockdep warnings due to double mutex locks Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 47/55] ALSA: timer: Fix leftover link at closing Willy Tarreau
                   ` (8 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit ee8413b01045c74340aa13ad5bdf905de32be736 upstream.

ALSA timer instance object has a couple of linked lists and they are
unlinked unconditionally at snd_timer_stop().  Meanwhile
snd_timer_interrupt() unlinks it, but it calls list_del() which leaves
the element list itself unchanged.  This ends up with unlinking twice,
and it was caught by syzkaller fuzzer.

The fix is to use list_del_init() variant properly there, too.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index 21f5df6..fb29803 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -724,7 +724,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
 		} else {
 			ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
 			if (--timer->running)
-				list_del(&ti->active_list);
+				list_del_init(&ti->active_list);
 		}
 		if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
 		    (ti->flags & SNDRV_TIMER_IFLG_FAST))
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 47/55] ALSA: timer: Fix leftover link at closing
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (45 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 46/55] ALSA: timer: Fix double unlink of active_list Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 48/55] ALSA: timer: Fix race among timer ioctls Willy Tarreau
                   ` (7 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 094fd3be87b0f102589e2d5c3fa5d06b7e20496d upstream.

In ALSA timer core, the active timer instance is managed in
active_list linked list.  Each element is added / removed dynamically
at timer start, stop and in timer interrupt.  The problem is that
snd_timer_interrupt() has a thinko and leaves the element in
active_list when it's the last opened element.  This eventually leads
to list corruption or use-after-free error.

This hasn't been revealed because we used to delete the list forcibly
in snd_timer_stop() in the past.  However, the recent fix avoids the
double-stop behavior (in commit [f784beb75ce8: ALSA: timer: Fix link
corruption due to double start or stop]), and this leak hits reality.

This patch fixes the link management in snd_timer_interrupt().  Now it
simply unlinks no matter which stream is.

BugLink: http://lkml.kernel.org/r/CACT4Y+Yy2aukHP-EDp8-ziNqNNmb-NTf=jDWXMP7jB8HDa2vng@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index fb29803..2383874 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -723,8 +723,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
 			ti->cticks = ti->ticks;
 		} else {
 			ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
-			if (--timer->running)
-				list_del_init(&ti->active_list);
+			--timer->running;
+			list_del_init(&ti->active_list);
 		}
 		if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
 		    (ti->flags & SNDRV_TIMER_IFLG_FAST))
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 48/55] ALSA: timer: Fix race among timer ioctls
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (46 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 47/55] ALSA: timer: Fix leftover link at closing Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 49/55] ALSA: timer: Fix wrong instance passed to slave callbacks Willy Tarreau
                   ` (6 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit af368027a49a751d6ff4ee9e3f9961f35bb4fede upstream.

ALSA timer ioctls have an open race and this may lead to a
use-after-free of timer instance object.  A simplistic fix is to make
each ioctl exclusive.  We have already tread_sem for controlling the
tread, and extend this as a global mutex to be applied to each ioctl.

The downside is, of course, the worse concurrency.  But these ioctls
aren't to be parallel accessible, in anyway, so it should be fine to
serialize there.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 32 +++++++++++++++++++-------------
 1 file changed, 19 insertions(+), 13 deletions(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index 2383874..a0c2684 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -69,7 +69,7 @@ struct snd_timer_user {
 	struct timespec tstamp;		/* trigger tstamp */
 	wait_queue_head_t qchange_sleep;
 	struct fasync_struct *fasync;
-	struct mutex tread_sem;
+	struct mutex ioctl_lock;
 };
 
 /* list of timers */
@@ -1281,7 +1281,7 @@ static int snd_timer_user_open(struct inode *inode, struct file *file)
 		return -ENOMEM;
 	spin_lock_init(&tu->qlock);
 	init_waitqueue_head(&tu->qchange_sleep);
-	mutex_init(&tu->tread_sem);
+	mutex_init(&tu->ioctl_lock);
 	tu->ticks = 1;
 	tu->queue_size = 128;
 	tu->queue = kmalloc(tu->queue_size * sizeof(struct snd_timer_read),
@@ -1301,8 +1301,10 @@ static int snd_timer_user_release(struct inode *inode, struct file *file)
 	if (file->private_data) {
 		tu = file->private_data;
 		file->private_data = NULL;
+		mutex_lock(&tu->ioctl_lock);
 		if (tu->timeri)
 			snd_timer_close(tu->timeri);
+		mutex_unlock(&tu->ioctl_lock);
 		kfree(tu->queue);
 		kfree(tu->tqueue);
 		kfree(tu);
@@ -1540,7 +1542,6 @@ static int snd_timer_user_tselect(struct file *file,
 	int err = 0;
 
 	tu = file->private_data;
-	mutex_lock(&tu->tread_sem);
 	if (tu->timeri) {
 		snd_timer_close(tu->timeri);
 		tu->timeri = NULL;
@@ -1584,7 +1585,6 @@ static int snd_timer_user_tselect(struct file *file,
 	}
 
       __err:
-      	mutex_unlock(&tu->tread_sem);
 	return err;
 }
 
@@ -1797,7 +1797,7 @@ enum {
 	SNDRV_TIMER_IOCTL_PAUSE_OLD = _IO('T', 0x23),
 };
 
-static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+static long __snd_timer_user_ioctl(struct file *file, unsigned int cmd,
 				 unsigned long arg)
 {
 	struct snd_timer_user *tu;
@@ -1814,17 +1814,11 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
 	{
 		int xarg;
 
-		mutex_lock(&tu->tread_sem);
-		if (tu->timeri)	{	/* too late */
-			mutex_unlock(&tu->tread_sem);
+		if (tu->timeri)	/* too late */
 			return -EBUSY;
-		}
-		if (get_user(xarg, p)) {
-			mutex_unlock(&tu->tread_sem);
+		if (get_user(xarg, p))
 			return -EFAULT;
-		}
 		tu->tread = xarg ? 1 : 0;
-		mutex_unlock(&tu->tread_sem);
 		return 0;
 	}
 	case SNDRV_TIMER_IOCTL_GINFO:
@@ -1857,6 +1851,18 @@ static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
 	return -ENOTTY;
 }
 
+static long snd_timer_user_ioctl(struct file *file, unsigned int cmd,
+				 unsigned long arg)
+{
+	struct snd_timer_user *tu = file->private_data;
+	long ret;
+
+	mutex_lock(&tu->ioctl_lock);
+	ret = __snd_timer_user_ioctl(file, cmd, arg);
+	mutex_unlock(&tu->ioctl_lock);
+	return ret;
+}
+
 static int snd_timer_user_fasync(int fd, struct file * file, int on)
 {
 	struct snd_timer_user *tu;
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 49/55] ALSA: timer: Fix wrong instance passed to slave callbacks
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (47 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 48/55] ALSA: timer: Fix race among timer ioctls Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 50/55] ALSA: timer: Fix race at concurrent reads Willy Tarreau
                   ` (5 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 117159f0b9d392fb433a7871426fad50317f06f7 upstream.

In snd_timer_notify1(), the wrong timer instance was passed for slave
ccallback function.  This leads to the access to the wrong data when
an incompatible master is handled (e.g. the master is the sequencer
timer and the slave is a user timer), as spotted by syzkaller fuzzer.

This patch fixes that wrong assignment.

BugLink: http://lkml.kernel.org/r/CACT4Y+Y_Bm+7epAb=8Wi=AaWd+DYS7qawX52qxdCfOfY49vozQ@mail.gmail.com
Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index a0c2684..3141dda 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -409,7 +409,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
 	spin_lock_irqsave(&timer->lock, flags);
 	list_for_each_entry(ts, &ti->slave_active_head, active_list)
 		if (ts->ccallback)
-			ts->ccallback(ti, event + 100, &tstamp, resolution);
+			ts->ccallback(ts, event + 100, &tstamp, resolution);
 	spin_unlock_irqrestore(&timer->lock, flags);
 }
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 50/55] ALSA: timer: Fix race at concurrent reads
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (48 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 49/55] ALSA: timer: Fix wrong instance passed to slave callbacks Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 51/55] ALSA: usb-audio: avoid freeing umidi object twice Willy Tarreau
                   ` (4 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable; +Cc: Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 4dff5c7b7093b19c19d3a100f8a3ad87cb7cd9e7 upstream.

snd_timer_user_read() has a potential race among parallel reads, as
qhead and qused are updated outside the critical section due to
copy_to_user() calls.  Move them into the critical section, and also
sanitize the relevant code a bit.

Signed-off-by: Takashi Iwai <tiwai@suse.de>
[bwh: Backported to 3.2: there's no check for tu->connected to fix up]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/timer.c | 32 ++++++++++++++------------------
 1 file changed, 14 insertions(+), 18 deletions(-)

diff --git a/sound/core/timer.c b/sound/core/timer.c
index 3141dda..5e2c554 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -1876,6 +1876,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 {
 	struct snd_timer_user *tu;
 	long result = 0, unit;
+	int qhead;
 	int err = 0;
 
 	tu = file->private_data;
@@ -1887,7 +1888,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 
 			if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
 				err = -EAGAIN;
-				break;
+				goto _error;
 			}
 
 			set_current_state(TASK_INTERRUPTIBLE);
@@ -1902,38 +1903,33 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
 
 			if (signal_pending(current)) {
 				err = -ERESTARTSYS;
-				break;
+				goto _error;
 			}
 		}
 
+		qhead = tu->qhead++;
+		tu->qhead %= tu->queue_size;
 		spin_unlock_irq(&tu->qlock);
-		if (err < 0)
-			goto _error;
 
 		if (tu->tread) {
-			if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
-					 sizeof(struct snd_timer_tread))) {
+			if (copy_to_user(buffer, &tu->tqueue[qhead],
+					 sizeof(struct snd_timer_tread)))
 				err = -EFAULT;
-				goto _error;
-			}
 		} else {
-			if (copy_to_user(buffer, &tu->queue[tu->qhead++],
-					 sizeof(struct snd_timer_read))) {
+			if (copy_to_user(buffer, &tu->queue[qhead],
+					 sizeof(struct snd_timer_read)))
 				err = -EFAULT;
-				goto _error;
-			}
 		}
 
-		tu->qhead %= tu->queue_size;
-
-		result += unit;
-		buffer += unit;
-
 		spin_lock_irq(&tu->qlock);
 		tu->qused--;
+		if (err < 0)
+			goto _error;
+		result += unit;
+		buffer += unit;
 	}
-	spin_unlock_irq(&tu->qlock);
  _error:
+	spin_unlock_irq(&tu->qlock);
 	return result > 0 ? result : err;
 }
 
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 51/55] ALSA: usb-audio: avoid freeing umidi object twice
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (49 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 50/55] ALSA: timer: Fix race at concurrent reads Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 52/55] ALSA: seq: Fix missing NULL check at remove_events ioctl Willy Tarreau
                   ` (3 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Andrey Konovalov, Clemens Ladisch, Takashi Iwai, Ben Hutchings,
	Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Andrey Konovalov <andreyknvl@gmail.com>

commit 07d86ca93db7e5cdf4743564d98292042ec21af7 upstream.

The 'umidi' object will be free'd on the error path by snd_usbmidi_free()
when tearing down the rawmidi interface. So we shouldn't try to free it
in snd_usbmidi_create() after having registered the rawmidi interface.

Found by KASAN.

Signed-off-by: Andrey Konovalov <andreyknvl@gmail.com>
Acked-by: Clemens Ladisch <clemens@ladisch.de>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
[wt: file is sound/midi/usbmidi.c in 2.6.32]
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/usb/usbmidi.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/sound/usb/usbmidi.c b/sound/usb/usbmidi.c
index 64d8d2e..366020a 100644
--- a/sound/usb/usbmidi.c
+++ b/sound/usb/usbmidi.c
@@ -1947,7 +1947,6 @@ int snd_usb_create_midi_interface(struct snd_usb_audio* chip,
 	else
 		err = snd_usbmidi_create_endpoints(umidi, endpoints);
 	if (err < 0) {
-		snd_usbmidi_free(umidi);
 		return err;
 	}
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 52/55] ALSA: seq: Fix missing NULL check at remove_events ioctl
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (50 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 51/55] ALSA: usb-audio: avoid freeing umidi object twice Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 53/55] ALSA: seq: Fix race at timer setup and close Willy Tarreau
                   ` (2 subsequent siblings)
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 030e2c78d3a91dd0d27fef37e91950dde333eba1 upstream.

snd_seq_ioctl_remove_events() calls snd_seq_fifo_clear()
unconditionally even if there is no FIFO assigned, and this leads to
an Oops due to NULL dereference.  The fix is just to add a proper NULL
check.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/seq_clientmgr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 84aac18..95169c7 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1947,7 +1947,7 @@ static int snd_seq_ioctl_remove_events(struct snd_seq_client *client,
 		 * No restrictions so for a user client we can clear
 		 * the whole fifo
 		 */
-		if (client->type == USER_CLIENT)
+		if (client->type == USER_CLIENT && client->data.user.fifo)
 			snd_seq_fifo_clear(client->data.user.fifo);
 	}
 
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 53/55] ALSA: seq: Fix race at timer setup and close
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (51 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 52/55] ALSA: seq: Fix missing NULL check at remove_events ioctl Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 54/55] RDMA/cxgb3: Dont free skbs on NET_XMIT_* indications from LLD Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 55/55] iw_cxgb3: Fix incorrectly returning error on success Willy Tarreau
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Dmitry Vyukov, Takashi Iwai, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Takashi Iwai <tiwai@suse.de>

commit 3567eb6af614dac436c4b16a8d426f9faed639b3 upstream.

ALSA sequencer code has an open race between the timer setup ioctl and
the close of the client.  This was triggered by syzkaller fuzzer, and
a use-after-free was caught there as a result.

This patch papers over it by adding a proper queue->timer_mutex lock
around the timer-related calls in the relevant code path.

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 sound/core/seq/seq_queue.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/sound/core/seq/seq_queue.c b/sound/core/seq/seq_queue.c
index e7a8e9e..a5d191e 100644
--- a/sound/core/seq/seq_queue.c
+++ b/sound/core/seq/seq_queue.c
@@ -144,8 +144,10 @@ static struct snd_seq_queue *queue_new(int owner, int locked)
 static void queue_delete(struct snd_seq_queue *q)
 {
 	/* stop and release the timer */
+	mutex_lock(&q->timer_mutex);
 	snd_seq_timer_stop(q->timer);
 	snd_seq_timer_close(q);
+	mutex_unlock(&q->timer_mutex);
 	/* wait until access free */
 	snd_use_lock_sync(&q->use_lock);
 	/* release resources... */
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 54/55] RDMA/cxgb3: Dont free skbs on NET_XMIT_* indications from LLD
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (52 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 53/55] ALSA: seq: Fix race at timer setup and close Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  2016-03-04 15:30 ` [PATCH 2.6.32 55/55] iw_cxgb3: Fix incorrectly returning error on success Willy Tarreau
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Steve Wise, Roland Dreier, Ben Hutchings, Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Steve Wise <swise@opengridcomputing.com>

commit 73a203d2014f50d874b9e40083ad481ca70408e8 upstream.

The low level cxgb3 driver can return NET_XMIT_CN and friends.
The iw_cxgb3 driver should _not_ treat these as errors.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Roland Dreier <rolandd@cisco.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/infiniband/hw/cxgb3/iwch_cm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 675fc04..148f288 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -150,7 +150,7 @@ int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_entry *l2
 		return -EIO;
 	}
 	error = l2t_send(tdev, skb, l2e);
-	if (error)
+	if (error < 0)
 		kfree_skb(skb);
 	return error;
 }
@@ -166,7 +166,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
 		return -EIO;
 	}
 	error = cxgb3_ofld_send(tdev, skb);
-	if (error)
+	if (error < 0)
 		kfree_skb(skb);
 	return error;
 }
-- 
1.7.12.2.21.g234cd45.dirty

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH 2.6.32 55/55] iw_cxgb3: Fix incorrectly returning error on success
       [not found] <148ee355b419e9976ca727513a1405c8@local>
                   ` (53 preceding siblings ...)
  2016-03-04 15:30 ` [PATCH 2.6.32 54/55] RDMA/cxgb3: Dont free skbs on NET_XMIT_* indications from LLD Willy Tarreau
@ 2016-03-04 15:30 ` Willy Tarreau
  54 siblings, 0 replies; 55+ messages in thread
From: Willy Tarreau @ 2016-03-04 15:30 UTC (permalink / raw)
  To: linux-kernel, stable
  Cc: Steve Wise, Hariprasad Shenai, Doug Ledford, Ben Hutchings,
	Willy Tarreau

2.6.32-longterm review patch.  If anyone has any objections, please let me know.

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

From: Hariprasad S <hariprasad@chelsio.com>

commit 67f1aee6f45059fd6b0f5b0ecb2c97ad0451f6b3 upstream.

The cxgb3_*_send() functions return NET_XMIT_ values, which are
positive integers values. So don't treat positive return values
as an error.

Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Hariprasad Shenai <hariprasad@chelsio.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Signed-off-by: Willy Tarreau <w@1wt.eu>
---
 drivers/infiniband/hw/cxgb3/iwch_cm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 148f288..9ddff3d 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -152,7 +152,7 @@ int iwch_l2t_send(struct t3cdev *tdev, struct sk_buff *skb, struct l2t_entry *l2
 	error = l2t_send(tdev, skb, l2e);
 	if (error < 0)
 		kfree_skb(skb);
-	return error;
+	return error < 0 ? error : 0;
 }
 
 int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
@@ -168,7 +168,7 @@ int iwch_cxgb3_ofld_send(struct t3cdev *tdev, struct sk_buff *skb)
 	error = cxgb3_ofld_send(tdev, skb);
 	if (error < 0)
 		kfree_skb(skb);
-	return error;
+	return error < 0 ? error : 0;
 }
 
 static void release_tid(struct t3cdev *tdev, u32 hwtid, struct sk_buff *skb)
-- 
1.7.12.2.21.g234cd45.dirty




^ permalink raw reply related	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2016-03-04 16:04 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <148ee355b419e9976ca727513a1405c8@local>
2016-03-04 15:30 ` [PATCH 2.6.32 00/55] 2.6.32.71-longterm review Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 01/55] usb: serial: visor: fix crash on detecting device without write_urbs Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 02/55] usbvision fix overflow of interfaces array Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 03/55] USB: visor: fix null-deref at probe Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 04/55] sctp: Prevent soft lockup when sctp_accept() is called during a timeout event Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 05/55] sctp: translate network order to host order when users get a hmacid Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 06/55] tty: Fix unsafe ldisc reference via ioctl(TIOCGETD) Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 07/55] x86/mm: Add barriers and document switch_mm()-vs-flush synchronization Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 08/55] x86/mm: Improve switch_mm() barrier comments Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 10/55] sparc64: fix incorrect sign extension in sys_sparc64_personality Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 11/55] locks: fix unlock when fcntl_setlk races with a close Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 12/55] l2tp: fix another panic in pppol2tp Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 13/55] vfs: make AIO use the proper rw_verify_area() area helpers Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 14/55] readv/writev: do the same MAX_RW_COUNT truncation that read/write does Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 15/55] pipe: Fix buffer offset after partially failed read Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 16/55] af_unix: fix struct pid memory leak Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 17/55] PCI/AER: Flush workqueue on device remove to avoid use-after-free Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 18/55] libata: disable forced PORTS_IMPL for >= AHCI 1.3 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 19/55] rfkill: fix rfkill_fop_read wait_event usage Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 20/55] SCSI: fix crashes in sd and sr runtime PM Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 21/55] tda1004x: only update the frontend properties if locked Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 22/55] saa7134-alsa: Only frees registered sound cards Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 23/55] scsi_dh_rdac: always retry MODE SELECT on command lock violation Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 24/55] ocfs2/dlm: clear refmap bit of recovery lock while doing local recovery cleanup Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 25/55] udf: Promote some debugging messages to udf_error Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 26/55] udf: limit the maximum number of indirect extents in a row Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 27/55] udf: Prevent buffer overrun with multi-byte characters Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 28/55] udf: Check output buffer length when converting name to CS0 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 29/55] ocfs2/dlm: ignore cleaning the migration mle that is inuse Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 30/55] ALSA: dummy: Disable switching timer backend via sysfs Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 31/55] ALSA: timer: Harden slave timer list handling Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 32/55] ALSA: hrtimer: Fix stall by hrtimer_cancel() Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 33/55] ALSA: pcm: Fix snd_pcm_hw_params struct copy in compat mode Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 34/55] ALSA: seq: Fix snd_seq_call_port_info_ioctl " Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 35/55] ALSA: control: Avoid kernel warnings from tlv ioctl with numid 0 Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 36/55] ALSA: seq: Fix incorrect sanity check at snd_seq_oss_synth_cleanup() Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 37/55] ALSA: seq: Degrade the error message for too many opens Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 38/55] ALSA: seq: Fix race at closing in virmidi driver Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 39/55] ALSA: rawmidi: Remove kernel WARNING for NULL user-space buffer check Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 40/55] ALSA: pcm: Fix potential deadlock in OSS emulation Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 41/55] ALSA: seq: Fix yet another races among ALSA timer accesses Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 42/55] ALSA: timer: Fix link corruption due to double start or stop Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 43/55] ALSA: rawmidi: Make snd_rawmidi_transmit() race-free Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 44/55] ALSA: rawmidi: Fix race at copying & updating the position Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 45/55] ALSA: seq: Fix lockdep warnings due to double mutex locks Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 46/55] ALSA: timer: Fix double unlink of active_list Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 47/55] ALSA: timer: Fix leftover link at closing Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 48/55] ALSA: timer: Fix race among timer ioctls Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 49/55] ALSA: timer: Fix wrong instance passed to slave callbacks Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 50/55] ALSA: timer: Fix race at concurrent reads Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 51/55] ALSA: usb-audio: avoid freeing umidi object twice Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 52/55] ALSA: seq: Fix missing NULL check at remove_events ioctl Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 53/55] ALSA: seq: Fix race at timer setup and close Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 54/55] RDMA/cxgb3: Dont free skbs on NET_XMIT_* indications from LLD Willy Tarreau
2016-03-04 15:30 ` [PATCH 2.6.32 55/55] iw_cxgb3: Fix incorrectly returning error on success Willy Tarreau

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).