]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Oct 2023 17:38:41 +0000 (19:38 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 12 Oct 2023 17:38:41 +0000 (19:38 +0200)
added patches:
hid-logitech-hidpp-fix-kernel-crash-on-receiver-usb-disconnect.patch
net-prevent-address-rewrite-in-kernel_bind.patch
quota-fix-slow-quotaoff.patch

queue-5.4/hid-logitech-hidpp-fix-kernel-crash-on-receiver-usb-disconnect.patch [new file with mode: 0644]
queue-5.4/net-prevent-address-rewrite-in-kernel_bind.patch [new file with mode: 0644]
queue-5.4/quota-fix-slow-quotaoff.patch [new file with mode: 0644]
queue-5.4/series

diff --git a/queue-5.4/hid-logitech-hidpp-fix-kernel-crash-on-receiver-usb-disconnect.patch b/queue-5.4/hid-logitech-hidpp-fix-kernel-crash-on-receiver-usb-disconnect.patch
new file mode 100644 (file)
index 0000000..24a48e8
--- /dev/null
@@ -0,0 +1,177 @@
+From dac501397b9d81e4782232c39f94f4307b137452 Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Thu, 5 Oct 2023 20:26:38 +0200
+Subject: HID: logitech-hidpp: Fix kernel crash on receiver USB disconnect
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit dac501397b9d81e4782232c39f94f4307b137452 upstream.
+
+hidpp_connect_event() has *four* time-of-check vs time-of-use (TOCTOU)
+races when it races with itself.
+
+hidpp_connect_event() primarily runs from a workqueue but it also runs
+on probe() and if a "device-connected" packet is received by the hw
+when the thread running hidpp_connect_event() from probe() is waiting on
+the hw, then a second thread running hidpp_connect_event() will be
+started from the workqueue.
+
+This opens the following races (note the below code is simplified):
+
+1. Retrieving + printing the protocol (harmless race):
+
+       if (!hidpp->protocol_major) {
+               hidpp_root_get_protocol_version()
+               hidpp->protocol_major = response.rap.params[0];
+       }
+
+We can actually see this race hit in the dmesg in the abrt output
+attached to rhbz#2227968:
+
+[ 3064.624215] logitech-hidpp-device 0003:046D:4071.0049: HID++ 4.5 device connected.
+[ 3064.658184] logitech-hidpp-device 0003:046D:4071.0049: HID++ 4.5 device connected.
+
+Testing with extra logging added has shown that after this the 2 threads
+take turn grabbing the hw access mutex (send_mutex) so they ping-pong
+through all the other TOCTOU cases managing to hit all of them:
+
+2. Updating the name to the HIDPP name (harmless race):
+
+       if (hidpp->name == hdev->name) {
+               ...
+               hidpp->name = new_name;
+       }
+
+3. Initializing the power_supply class for the battery (problematic!):
+
+hidpp_initialize_battery()
+{
+        if (hidpp->battery.ps)
+                return 0;
+
+       probe_battery(); /* Blocks, threads take turns executing this */
+
+       hidpp->battery.desc.properties =
+               devm_kmemdup(dev, hidpp_battery_props, cnt, GFP_KERNEL);
+
+       hidpp->battery.ps =
+               devm_power_supply_register(&hidpp->hid_dev->dev,
+                                          &hidpp->battery.desc, cfg);
+}
+
+4. Creating delayed input_device (potentially problematic):
+
+       if (hidpp->delayed_input)
+               return;
+
+       hidpp->delayed_input = hidpp_allocate_input(hdev);
+
+The really big problem here is 3. Hitting the race leads to the following
+sequence:
+
+       hidpp->battery.desc.properties =
+               devm_kmemdup(dev, hidpp_battery_props, cnt, GFP_KERNEL);
+
+       hidpp->battery.ps =
+               devm_power_supply_register(&hidpp->hid_dev->dev,
+                                          &hidpp->battery.desc, cfg);
+
+       ...
+
+       hidpp->battery.desc.properties =
+               devm_kmemdup(dev, hidpp_battery_props, cnt, GFP_KERNEL);
+
+       hidpp->battery.ps =
+               devm_power_supply_register(&hidpp->hid_dev->dev,
+                                          &hidpp->battery.desc, cfg);
+
+So now we have registered 2 power supplies for the same battery,
+which looks a bit weird from userspace's pov but this is not even
+the really big problem.
+
+Notice how:
+
+1. This is all devm-maganaged
+2. The hidpp->battery.desc struct is shared between the 2 power supplies
+3. hidpp->battery.desc.properties points to the result from the second
+   devm_kmemdup()
+
+This causes a use after free scenario on USB disconnect of the receiver:
+1. The last registered power supply class device gets unregistered
+2. The memory from the last devm_kmemdup() call gets freed,
+   hidpp->battery.desc.properties now points to freed memory
+3. The first registered power supply class device gets unregistered,
+   this involves sending a remove uevent to userspace which invokes
+   power_supply_uevent() to fill the uevent data
+4. power_supply_uevent() uses hidpp->battery.desc.properties which
+   now points to freed memory leading to backtraces like this one:
+
+Sep 22 20:01:35 eric kernel: BUG: unable to handle page fault for address: ffffb2140e017f08
+...
+Sep 22 20:01:35 eric kernel: Workqueue: usb_hub_wq hub_event
+Sep 22 20:01:35 eric kernel: RIP: 0010:power_supply_uevent+0xee/0x1d0
+...
+Sep 22 20:01:35 eric kernel:  ? asm_exc_page_fault+0x26/0x30
+Sep 22 20:01:35 eric kernel:  ? power_supply_uevent+0xee/0x1d0
+Sep 22 20:01:35 eric kernel:  ? power_supply_uevent+0x10d/0x1d0
+Sep 22 20:01:35 eric kernel:  dev_uevent+0x10f/0x2d0
+Sep 22 20:01:35 eric kernel:  kobject_uevent_env+0x291/0x680
+Sep 22 20:01:35 eric kernel:  power_supply_unregister+0x8e/0xa0
+Sep 22 20:01:35 eric kernel:  release_nodes+0x3d/0xb0
+Sep 22 20:01:35 eric kernel:  devres_release_group+0xfc/0x130
+Sep 22 20:01:35 eric kernel:  hid_device_remove+0x56/0xa0
+Sep 22 20:01:35 eric kernel:  device_release_driver_internal+0x19f/0x200
+Sep 22 20:01:35 eric kernel:  bus_remove_device+0xc6/0x130
+Sep 22 20:01:35 eric kernel:  device_del+0x15c/0x3f0
+Sep 22 20:01:35 eric kernel:  ? __queue_work+0x1df/0x440
+Sep 22 20:01:35 eric kernel:  hid_destroy_device+0x4b/0x60
+Sep 22 20:01:35 eric kernel:  logi_dj_remove+0x9a/0x100 [hid_logitech_dj 5c91534a0ead2b65e04dd799a0437e3b99b21bc4]
+Sep 22 20:01:35 eric kernel:  hid_device_remove+0x44/0xa0
+Sep 22 20:01:35 eric kernel:  device_release_driver_internal+0x19f/0x200
+Sep 22 20:01:35 eric kernel:  bus_remove_device+0xc6/0x130
+Sep 22 20:01:35 eric kernel:  device_del+0x15c/0x3f0
+Sep 22 20:01:35 eric kernel:  ? __queue_work+0x1df/0x440
+Sep 22 20:01:35 eric kernel:  hid_destroy_device+0x4b/0x60
+Sep 22 20:01:35 eric kernel:  usbhid_disconnect+0x47/0x60 [usbhid 727dcc1c0b94e6b4418727a468398ac3bca492f3]
+Sep 22 20:01:35 eric kernel:  usb_unbind_interface+0x90/0x270
+Sep 22 20:01:35 eric kernel:  device_release_driver_internal+0x19f/0x200
+Sep 22 20:01:35 eric kernel:  bus_remove_device+0xc6/0x130
+Sep 22 20:01:35 eric kernel:  device_del+0x15c/0x3f0
+Sep 22 20:01:35 eric kernel:  ? kobject_put+0xa0/0x1d0
+Sep 22 20:01:35 eric kernel:  usb_disable_device+0xcd/0x1e0
+Sep 22 20:01:35 eric kernel:  usb_disconnect+0xde/0x2c0
+Sep 22 20:01:35 eric kernel:  usb_disconnect+0xc3/0x2c0
+Sep 22 20:01:35 eric kernel:  hub_event+0xe80/0x1c10
+
+There have been quite a few bug reports (see Link tags) about this crash.
+
+Fix all the TOCTOU issues, including the really bad power-supply related
+system crash on USB disconnect, by making probe() use the workqueue for
+running hidpp_connect_event() too, so that it can never run more then once.
+
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=2227221
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=2227968
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=2227968
+Link: https://bugzilla.redhat.com/show_bug.cgi?id=2242189
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=217412#c58
+Cc: stable@vger.kernel.org
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231005182638.3776-1-hdegoede@redhat.com
+Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/hid/hid-logitech-hidpp.c |    3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/hid-logitech-hidpp.c
++++ b/drivers/hid/hid-logitech-hidpp.c
+@@ -3723,7 +3723,8 @@ static int hidpp_probe(struct hid_device
+                       goto hid_hw_init_fail;
+       }
+-      hidpp_connect_event(hidpp);
++      schedule_work(&hidpp->work);
++      flush_work(&hidpp->work);
+       /* Reset the HID node state */
+       hid_device_io_stop(hdev);
diff --git a/queue-5.4/net-prevent-address-rewrite-in-kernel_bind.patch b/queue-5.4/net-prevent-address-rewrite-in-kernel_bind.patch
new file mode 100644 (file)
index 0000000..8babc81
--- /dev/null
@@ -0,0 +1,89 @@
+From c889a99a21bf124c3db08d09df919f0eccc5ea4c Mon Sep 17 00:00:00 2001
+From: Jordan Rife <jrife@google.com>
+Date: Thu, 21 Sep 2023 18:46:42 -0500
+Subject: net: prevent address rewrite in kernel_bind()
+
+From: Jordan Rife <jrife@google.com>
+
+commit c889a99a21bf124c3db08d09df919f0eccc5ea4c upstream.
+
+Similar to the change in commit 0bdf399342c5("net: Avoid address
+overwrite in kernel_connect"), BPF hooks run on bind may rewrite the
+address passed to kernel_bind(). This change
+
+1) Makes a copy of the bind address in kernel_bind() to insulate
+   callers.
+2) Replaces direct calls to sock->ops->bind() in net with kernel_bind()
+
+Link: https://lore.kernel.org/netdev/20230912013332.2048422-1-jrife@google.com/
+Fixes: 4fbac77d2d09 ("bpf: Hooks for sys_bind")
+Cc: stable@vger.kernel.org
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Signed-off-by: Jordan Rife <jrife@google.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/netfilter/ipvs/ip_vs_sync.c |    4 ++--
+ net/rds/tcp_connect.c           |    2 +-
+ net/rds/tcp_listen.c            |    2 +-
+ net/socket.c                    |    6 +++++-
+ 4 files changed, 9 insertions(+), 5 deletions(-)
+
+--- a/net/netfilter/ipvs/ip_vs_sync.c
++++ b/net/netfilter/ipvs/ip_vs_sync.c
+@@ -1444,7 +1444,7 @@ static int bind_mcastif_addr(struct sock
+       sin.sin_addr.s_addr  = addr;
+       sin.sin_port         = 0;
+-      return sock->ops->bind(sock, (struct sockaddr*)&sin, sizeof(sin));
++      return kernel_bind(sock, (struct sockaddr *)&sin, sizeof(sin));
+ }
+ static void get_mcast_sockaddr(union ipvs_sockaddr *sa, int *salen,
+@@ -1551,7 +1551,7 @@ static int make_receive_sock(struct netn
+       get_mcast_sockaddr(&mcast_addr, &salen, &ipvs->bcfg, id);
+       sock->sk->sk_bound_dev_if = dev->ifindex;
+-      result = sock->ops->bind(sock, (struct sockaddr *)&mcast_addr, salen);
++      result = kernel_bind(sock, (struct sockaddr *)&mcast_addr, salen);
+       if (result < 0) {
+               pr_err("Error binding to the multicast addr\n");
+               goto error;
+--- a/net/rds/tcp_connect.c
++++ b/net/rds/tcp_connect.c
+@@ -141,7 +141,7 @@ int rds_tcp_conn_path_connect(struct rds
+               addrlen = sizeof(sin);
+       }
+-      ret = sock->ops->bind(sock, addr, addrlen);
++      ret = kernel_bind(sock, addr, addrlen);
+       if (ret) {
+               rdsdebug("bind failed with %d at address %pI6c\n",
+                        ret, &conn->c_laddr);
+--- a/net/rds/tcp_listen.c
++++ b/net/rds/tcp_listen.c
+@@ -332,7 +332,7 @@ struct socket *rds_tcp_listen_init(struc
+               addr_len = sizeof(*sin);
+       }
+-      ret = sock->ops->bind(sock, (struct sockaddr *)&ss, addr_len);
++      ret = kernel_bind(sock, (struct sockaddr *)&ss, addr_len);
+       if (ret < 0) {
+               rdsdebug("could not bind %s listener socket: %d\n",
+                        isv6 ? "IPv6" : "IPv4", ret);
+--- a/net/socket.c
++++ b/net/socket.c
+@@ -3584,7 +3584,11 @@ static long compat_sock_ioctl(struct fil
+ int kernel_bind(struct socket *sock, struct sockaddr *addr, int addrlen)
+ {
+-      return sock->ops->bind(sock, addr, addrlen);
++      struct sockaddr_storage address;
++
++      memcpy(&address, addr, addrlen);
++
++      return sock->ops->bind(sock, (struct sockaddr *)&address, addrlen);
+ }
+ EXPORT_SYMBOL(kernel_bind);
diff --git a/queue-5.4/quota-fix-slow-quotaoff.patch b/queue-5.4/quota-fix-slow-quotaoff.patch
new file mode 100644 (file)
index 0000000..66902b7
--- /dev/null
@@ -0,0 +1,208 @@
+From 869b6ea1609f655a43251bf41757aa44e5350a8f Mon Sep 17 00:00:00 2001
+From: Jan Kara <jack@suse.cz>
+Date: Wed, 4 Oct 2023 15:32:01 +0200
+Subject: quota: Fix slow quotaoff
+
+From: Jan Kara <jack@suse.cz>
+
+commit 869b6ea1609f655a43251bf41757aa44e5350a8f upstream.
+
+Eric has reported that commit dabc8b207566 ("quota: fix dqput() to
+follow the guarantees dquot_srcu should provide") heavily increases
+runtime of generic/270 xfstest for ext4 in nojournal mode. The reason
+for this is that ext4 in nojournal mode leaves dquots dirty until the last
+dqput() and thus the cleanup done in quota_release_workfn() has to write
+them all. Due to the way quota_release_workfn() is written this results
+in synchronize_srcu() call for each dirty dquot which makes the dquot
+cleanup when turning quotas off extremely slow.
+
+To be able to avoid synchronize_srcu() for each dirty dquot we need to
+rework how we track dquots to be cleaned up. Instead of keeping the last
+dquot reference while it is on releasing_dquots list, we drop it right
+away and mark the dquot with new DQ_RELEASING_B bit instead. This way we
+can we can remove dquot from releasing_dquots list when new reference to
+it is acquired and thus there's no need to call synchronize_srcu() each
+time we drop dq_list_lock.
+
+References: https://lore.kernel.org/all/ZRytn6CxFK2oECUt@debian-BULLSEYE-live-builder-AMD64
+Reported-by: Eric Whitney <enwlinux@gmail.com>
+Fixes: dabc8b207566 ("quota: fix dqput() to follow the guarantees dquot_srcu should provide")
+CC: stable@vger.kernel.org
+Signed-off-by: Jan Kara <jack@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ fs/quota/dquot.c         |   66 +++++++++++++++++++++++++++--------------------
+ include/linux/quota.h    |    4 ++
+ include/linux/quotaops.h |    2 -
+ 3 files changed, 43 insertions(+), 29 deletions(-)
+
+--- a/fs/quota/dquot.c
++++ b/fs/quota/dquot.c
+@@ -231,19 +231,18 @@ static void put_quota_format(struct quot
+  * All dquots are placed to the end of inuse_list when first created, and this
+  * list is used for invalidate operation, which must look at every dquot.
+  *
+- * When the last reference of a dquot will be dropped, the dquot will be
+- * added to releasing_dquots. We'd then queue work item which would call
++ * When the last reference of a dquot is dropped, the dquot is added to
++ * releasing_dquots. We'll then queue work item which will call
+  * synchronize_srcu() and after that perform the final cleanup of all the
+- * dquots on the list. Both releasing_dquots and free_dquots use the
+- * dq_free list_head in the dquot struct. When a dquot is removed from
+- * releasing_dquots, a reference count is always subtracted, and if
+- * dq_count == 0 at that point, the dquot will be added to the free_dquots.
++ * dquots on the list. Each cleaned up dquot is moved to free_dquots list.
++ * Both releasing_dquots and free_dquots use the dq_free list_head in the dquot
++ * struct.
+  *
+- * Unused dquots (dq_count == 0) are added to the free_dquots list when freed,
+- * and this list is searched whenever we need an available dquot.  Dquots are
+- * removed from the list as soon as they are used again, and
+- * dqstats.free_dquots gives the number of dquots on the list. When
+- * dquot is invalidated it's completely released from memory.
++ * Unused and cleaned up dquots are in the free_dquots list and this list is
++ * searched whenever we need an available dquot. Dquots are removed from the
++ * list as soon as they are used again and dqstats.free_dquots gives the number
++ * of dquots on the list. When dquot is invalidated it's completely released
++ * from memory.
+  *
+  * Dirty dquots are added to the dqi_dirty_list of quota_info when mark
+  * dirtied, and this list is searched when writing dirty dquots back to
+@@ -321,6 +320,7 @@ static inline void put_dquot_last(struct
+ static inline void put_releasing_dquots(struct dquot *dquot)
+ {
+       list_add_tail(&dquot->dq_free, &releasing_dquots);
++      set_bit(DQ_RELEASING_B, &dquot->dq_flags);
+ }
+ static inline void remove_free_dquot(struct dquot *dquot)
+@@ -328,8 +328,10 @@ static inline void remove_free_dquot(str
+       if (list_empty(&dquot->dq_free))
+               return;
+       list_del_init(&dquot->dq_free);
+-      if (!atomic_read(&dquot->dq_count))
++      if (!test_bit(DQ_RELEASING_B, &dquot->dq_flags))
+               dqstats_dec(DQST_FREE_DQUOTS);
++      else
++              clear_bit(DQ_RELEASING_B, &dquot->dq_flags);
+ }
+ static inline void put_inuse(struct dquot *dquot)
+@@ -572,12 +574,6 @@ restart:
+                       continue;
+               /* Wait for dquot users */
+               if (atomic_read(&dquot->dq_count)) {
+-                      /* dquot in releasing_dquots, flush and retry */
+-                      if (!list_empty(&dquot->dq_free)) {
+-                              spin_unlock(&dq_list_lock);
+-                              goto restart;
+-                      }
+-
+                       atomic_inc(&dquot->dq_count);
+                       spin_unlock(&dq_list_lock);
+                       /*
+@@ -597,6 +593,15 @@ restart:
+                       goto restart;
+               }
+               /*
++               * The last user already dropped its reference but dquot didn't
++               * get fully cleaned up yet. Restart the scan which flushes the
++               * work cleaning up released dquots.
++               */
++              if (test_bit(DQ_RELEASING_B, &dquot->dq_flags)) {
++                      spin_unlock(&dq_list_lock);
++                      goto restart;
++              }
++              /*
+                * Quota now has no users and it has been written on last
+                * dqput()
+                */
+@@ -687,6 +692,13 @@ int dquot_writeback_dquots(struct super_
+                                                dq_dirty);
+                       WARN_ON(!dquot_active(dquot));
++                      /* If the dquot is releasing we should not touch it */
++                      if (test_bit(DQ_RELEASING_B, &dquot->dq_flags)) {
++                              spin_unlock(&dq_list_lock);
++                              flush_delayed_work(&quota_release_work);
++                              spin_lock(&dq_list_lock);
++                              continue;
++                      }
+                       /* Now we have active dquot from which someone is
+                        * holding reference so we can safely just increase
+@@ -800,18 +812,18 @@ static void quota_release_workfn(struct
+       /* Exchange the list head to avoid livelock. */
+       list_replace_init(&releasing_dquots, &rls_head);
+       spin_unlock(&dq_list_lock);
++      synchronize_srcu(&dquot_srcu);
+ restart:
+-      synchronize_srcu(&dquot_srcu);
+       spin_lock(&dq_list_lock);
+       while (!list_empty(&rls_head)) {
+               dquot = list_first_entry(&rls_head, struct dquot, dq_free);
+-              /* Dquot got used again? */
+-              if (atomic_read(&dquot->dq_count) > 1) {
+-                      remove_free_dquot(dquot);
+-                      atomic_dec(&dquot->dq_count);
+-                      continue;
+-              }
++              WARN_ON_ONCE(atomic_read(&dquot->dq_count));
++              /*
++               * Note that DQ_RELEASING_B protects us from racing with
++               * invalidate_dquots() calls so we are safe to work with the
++               * dquot even after we drop dq_list_lock.
++               */
+               if (dquot_dirty(dquot)) {
+                       spin_unlock(&dq_list_lock);
+                       /* Commit dquot before releasing */
+@@ -825,7 +837,6 @@ restart:
+               }
+               /* Dquot is inactive and clean, now move it to free list */
+               remove_free_dquot(dquot);
+-              atomic_dec(&dquot->dq_count);
+               put_dquot_last(dquot);
+       }
+       spin_unlock(&dq_list_lock);
+@@ -866,6 +877,7 @@ void dqput(struct dquot *dquot)
+       BUG_ON(!list_empty(&dquot->dq_free));
+ #endif
+       put_releasing_dquots(dquot);
++      atomic_dec(&dquot->dq_count);
+       spin_unlock(&dq_list_lock);
+       queue_delayed_work(system_unbound_wq, &quota_release_work, 1);
+ }
+@@ -954,7 +966,7 @@ we_slept:
+               dqstats_inc(DQST_LOOKUPS);
+       }
+       /* Wait for dq_lock - after this we know that either dquot_release() is
+-       * already finished or it will be canceled due to dq_count > 1 test */
++       * already finished or it will be canceled due to dq_count > 0 test */
+       wait_on_dquot(dquot);
+       /* Read the dquot / allocate space in quota file */
+       if (!dquot_active(dquot)) {
+--- a/include/linux/quota.h
++++ b/include/linux/quota.h
+@@ -285,7 +285,9 @@ static inline void dqstats_dec(unsigned
+ #define DQ_FAKE_B     3       /* no limits only usage */
+ #define DQ_READ_B     4       /* dquot was read into memory */
+ #define DQ_ACTIVE_B   5       /* dquot is active (dquot_release not called) */
+-#define DQ_LASTSET_B  6       /* Following 6 bits (see QIF_) are reserved\
++#define DQ_RELEASING_B        6       /* dquot is in releasing_dquots list waiting
++                               * to be cleaned up */
++#define DQ_LASTSET_B  7       /* Following 6 bits (see QIF_) are reserved\
+                                * for the mask of entries set via SETQUOTA\
+                                * quotactl. They are set under dq_data_lock\
+                                * and the quota format handling dquot can\
+--- a/include/linux/quotaops.h
++++ b/include/linux/quotaops.h
+@@ -59,7 +59,7 @@ static inline bool dquot_is_busy(struct
+ {
+       if (test_bit(DQ_MOD_B, &dquot->dq_flags))
+               return true;
+-      if (atomic_read(&dquot->dq_count) > 1)
++      if (atomic_read(&dquot->dq_count) > 0)
+               return true;
+       return false;
+ }
index 63eb2e83490fe585c5a0f43248c9f49c586740d2..60595514356363d9ddac8dbc7c203dd8d42eb3a8 100644 (file)
@@ -2,3 +2,6 @@ rdma-cxgb4-check-skb-value-for-failure-to-allocate.patch
 platform-x86-hp-wmi-mark-driver-struct-with-__refdat.patch
 lib-test_meminit-fix-off-by-one-error-in-test_pages.patch
 pwm-hibvt-explicitly-set-.polarity-in-.get_state.patch
+hid-logitech-hidpp-fix-kernel-crash-on-receiver-usb-disconnect.patch
+quota-fix-slow-quotaoff.patch
+net-prevent-address-rewrite-in-kernel_bind.patch