]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.4
authorSasha Levin <sashal@kernel.org>
Thu, 14 May 2020 19:14:55 +0000 (15:14 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 14 May 2020 19:14:55 +0000 (15:14 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
14 files changed:
queue-5.4/drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch [new file with mode: 0644]
queue-5.4/ftrace-selftests-workaround-cgroup-rt-scheduling-iss.patch [new file with mode: 0644]
queue-5.4/gpio-pca953x-fix-pca953x_gpio_set_config.patch [new file with mode: 0644]
queue-5.4/kvm-arm-vgic-synchronize-the-whole-guest-on-gic-d-r-.patch [new file with mode: 0644]
queue-5.4/net-moxa-fix-a-potential-double-free_irq.patch [new file with mode: 0644]
queue-5.4/net-phy-microchip_t1-add-lan87xx_phy_init-to-initial.patch [new file with mode: 0644]
queue-5.4/net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch [new file with mode: 0644]
queue-5.4/net_sched-fix-tcm_parent-in-tc-filter-dump.patch [new file with mode: 0644]
queue-5.4/series
queue-5.4/shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch [new file with mode: 0644]
queue-5.4/sun6i-dsi-fix-gcc-4.8.patch [new file with mode: 0644]
queue-5.4/sunrpc-add-len-parameter-to-gss_unwrap.patch [new file with mode: 0644]
queue-5.4/sunrpc-fix-gss-privacy-computation-of-auth-au_ralign.patch [new file with mode: 0644]
queue-5.4/virtio-blk-handle-block_device_operations-callbacks-.patch [new file with mode: 0644]

diff --git a/queue-5.4/drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch b/queue-5.4/drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch
new file mode 100644 (file)
index 0000000..968d902
--- /dev/null
@@ -0,0 +1,73 @@
+From f94c08450a7fc61ce9d5b73138686f392972aca1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2020 23:30:49 +0200
+Subject: drop_monitor: work around gcc-10 stringop-overflow warning
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit dc30b4059f6e2abf3712ab537c8718562b21c45d ]
+
+The current gcc-10 snapshot produces a false-positive warning:
+
+net/core/drop_monitor.c: In function 'trace_drop_common.constprop':
+cc1: error: writing 8 bytes into a region of size 0 [-Werror=stringop-overflow=]
+In file included from net/core/drop_monitor.c:23:
+include/uapi/linux/net_dropmon.h:36:8: note: at offset 0 to object 'entries' with size 4 declared here
+   36 |  __u32 entries;
+      |        ^~~~~~~
+
+I reported this in the gcc bugzilla, but in case it does not get
+fixed in the release, work around it by using a temporary variable.
+
+Fixes: 9a8afc8d3962 ("Network Drop Monitor: Adding drop monitor implementation & Netlink protocol")
+Link: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94881
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Acked-by: Neil Horman <nhorman@tuxdriver.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/drop_monitor.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c
+index 246a258b1fac2..af0130039f377 100644
+--- a/net/core/drop_monitor.c
++++ b/net/core/drop_monitor.c
+@@ -212,6 +212,7 @@ static void sched_send_work(struct timer_list *t)
+ static void trace_drop_common(struct sk_buff *skb, void *location)
+ {
+       struct net_dm_alert_msg *msg;
++      struct net_dm_drop_point *point;
+       struct nlmsghdr *nlh;
+       struct nlattr *nla;
+       int i;
+@@ -230,11 +231,13 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
+       nlh = (struct nlmsghdr *)dskb->data;
+       nla = genlmsg_data(nlmsg_data(nlh));
+       msg = nla_data(nla);
++      point = msg->points;
+       for (i = 0; i < msg->entries; i++) {
+-              if (!memcmp(&location, msg->points[i].pc, sizeof(void *))) {
+-                      msg->points[i].count++;
++              if (!memcmp(&location, &point->pc, sizeof(void *))) {
++                      point->count++;
+                       goto out;
+               }
++              point++;
+       }
+       if (msg->entries == dm_hit_limit)
+               goto out;
+@@ -243,8 +246,8 @@ static void trace_drop_common(struct sk_buff *skb, void *location)
+        */
+       __nla_reserve_nohdr(dskb, sizeof(struct net_dm_drop_point));
+       nla->nla_len += NLA_ALIGN(sizeof(struct net_dm_drop_point));
+-      memcpy(msg->points[msg->entries].pc, &location, sizeof(void *));
+-      msg->points[msg->entries].count = 1;
++      memcpy(point->pc, &location, sizeof(void *));
++      point->count = 1;
+       msg->entries++;
+       if (!timer_pending(&data->send_timer)) {
+-- 
+2.20.1
+
diff --git a/queue-5.4/ftrace-selftests-workaround-cgroup-rt-scheduling-iss.patch b/queue-5.4/ftrace-selftests-workaround-cgroup-rt-scheduling-iss.patch
new file mode 100644 (file)
index 0000000..a4d162d
--- /dev/null
@@ -0,0 +1,87 @@
+From f8712def8793d045fd32d713486d61857043a29a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 19 Feb 2020 09:33:29 +0000
+Subject: ftrace/selftests: workaround cgroup RT scheduling issues
+
+From: Alan Maguire <alan.maguire@oracle.com>
+
+[ Upstream commit 57c4cfd4a2eef8f94052bd7c0fce0981f74fb213 ]
+
+wakeup_rt.tc and wakeup.tc tests in tracers/ subdirectory
+fail due to the chrt command returning:
+
+ chrt: failed to set pid 0's policy: Operation not permitted.
+
+To work around this, temporarily disable grout RT scheduling
+during ftracetest execution.  Restore original value on
+test run completion.  With these changes in place, both
+tests consistently pass.
+
+Fixes: c575dea2c1a5 ("selftests/ftrace: Add wakeup_rt tracer testcase")
+Fixes: c1edd060b413 ("selftests/ftrace: Add wakeup tracer testcase")
+Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
+Acked-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
+Signed-off-by: Shuah Khan <skhan@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ tools/testing/selftests/ftrace/ftracetest | 22 ++++++++++++++++++++++
+ 1 file changed, 22 insertions(+)
+
+diff --git a/tools/testing/selftests/ftrace/ftracetest b/tools/testing/selftests/ftrace/ftracetest
+index 063ecb290a5a3..144308a757b70 100755
+--- a/tools/testing/selftests/ftrace/ftracetest
++++ b/tools/testing/selftests/ftrace/ftracetest
+@@ -29,8 +29,25 @@ err_ret=1
+ # kselftest skip code is 4
+ err_skip=4
++# cgroup RT scheduling prevents chrt commands from succeeding, which
++# induces failures in test wakeup tests.  Disable for the duration of
++# the tests.
++
++readonly sched_rt_runtime=/proc/sys/kernel/sched_rt_runtime_us
++
++sched_rt_runtime_orig=$(cat $sched_rt_runtime)
++
++setup() {
++  echo -1 > $sched_rt_runtime
++}
++
++cleanup() {
++  echo $sched_rt_runtime_orig > $sched_rt_runtime
++}
++
+ errexit() { # message
+   echo "Error: $1" 1>&2
++  cleanup
+   exit $err_ret
+ }
+@@ -39,6 +56,8 @@ if [ `id -u` -ne 0 ]; then
+   errexit "this must be run by root user"
+ fi
++setup
++
+ # Utilities
+ absdir() { # file_path
+   (cd `dirname $1`; pwd)
+@@ -235,6 +254,7 @@ TOTAL_RESULT=0
+ INSTANCE=
+ CASENO=0
++
+ testcase() { # testfile
+   CASENO=$((CASENO+1))
+   desc=`grep "^#[ \t]*description:" $1 | cut -f2 -d:`
+@@ -406,5 +426,7 @@ prlog "# of unsupported: " `echo $UNSUPPORTED_CASES | wc -w`
+ prlog "# of xfailed: " `echo $XFAILED_CASES | wc -w`
+ prlog "# of undefined(test bug): " `echo $UNDEFINED_CASES | wc -w`
++cleanup
++
+ # if no error, return 0
+ exit $TOTAL_RESULT
+-- 
+2.20.1
+
diff --git a/queue-5.4/gpio-pca953x-fix-pca953x_gpio_set_config.patch b/queue-5.4/gpio-pca953x-fix-pca953x_gpio_set_config.patch
new file mode 100644 (file)
index 0000000..d4ab27f
--- /dev/null
@@ -0,0 +1,41 @@
+From 92d9a211d4c47a3139f17f122ec1ea0d0db6de0a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 11 Apr 2020 20:33:52 -0500
+Subject: gpio: pca953x: Fix pca953x_gpio_set_config
+
+From: Adam Ford <aford173@gmail.com>
+
+[ Upstream commit dc87f6dd058a648cd2a35e4aa04592dccdc9f0c2 ]
+
+pca953x_gpio_set_config is setup to support pull-up/down
+bias.  Currently the driver uses a variable called 'config' to
+determine which options to use.  Unfortunately, this is incorrect.
+
+This patch uses function pinconf_to_config_param(config), which
+converts this 'config' parameter back to pinconfig to determine
+which option to use.
+
+Fixes: 15add06841a3 ("gpio: pca953x: add ->set_config implementation")
+Signed-off-by: Adam Ford <aford173@gmail.com>
+Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpio/gpio-pca953x.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
+index de5d1383f28da..3edc1762803ac 100644
+--- a/drivers/gpio/gpio-pca953x.c
++++ b/drivers/gpio/gpio-pca953x.c
+@@ -528,7 +528,7 @@ static int pca953x_gpio_set_config(struct gpio_chip *gc, unsigned int offset,
+ {
+       struct pca953x_chip *chip = gpiochip_get_data(gc);
+-      switch (config) {
++      switch (pinconf_to_config_param(config)) {
+       case PIN_CONFIG_BIAS_PULL_UP:
+       case PIN_CONFIG_BIAS_PULL_DOWN:
+               return pca953x_gpio_set_pull_up_down(chip, offset, config);
+-- 
+2.20.1
+
diff --git a/queue-5.4/kvm-arm-vgic-synchronize-the-whole-guest-on-gic-d-r-.patch b/queue-5.4/kvm-arm-vgic-synchronize-the-whole-guest-on-gic-d-r-.patch
new file mode 100644 (file)
index 0000000..ff261af
--- /dev/null
@@ -0,0 +1,255 @@
+From 87db8c2f44ed59049f0a2d3715ff963359c86d90 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 6 Apr 2020 16:21:20 +0100
+Subject: KVM: arm: vgic: Synchronize the whole guest on GIC{D,R}_I{S,C}ACTIVER
+ read
+
+From: Marc Zyngier <maz@kernel.org>
+
+[ Upstream commit 9a50ebbffa9862db7604345f5fd763122b0f6fed ]
+
+When a guest tries to read the active state of its interrupts,
+we currently just return whatever state we have in memory. This
+means that if such an interrupt lives in a List Register on another
+CPU, we fail to obsertve the latest active state for this interrupt.
+
+In order to remedy this, stop all the other vcpus so that they exit
+and we can observe the most recent value for the state. This is
+similar to what we are doing for the write side of the same
+registers, and results in new MMIO handlers for userspace (which
+do not need to stop the guest, as it is supposed to be stopped
+already).
+
+Reported-by: Julien Grall <julien@xen.org>
+Reviewed-by: Andre Przywara <andre.przywara@arm.com>
+Signed-off-by: Marc Zyngier <maz@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ virt/kvm/arm/vgic/vgic-mmio-v2.c |   4 +-
+ virt/kvm/arm/vgic/vgic-mmio-v3.c |  12 ++--
+ virt/kvm/arm/vgic/vgic-mmio.c    | 100 ++++++++++++++++++++-----------
+ virt/kvm/arm/vgic/vgic-mmio.h    |   3 +
+ 4 files changed, 75 insertions(+), 44 deletions(-)
+
+diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
+index 5945f062d7497..d63881f60e1a5 100644
+--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
++++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
+@@ -422,11 +422,11 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = {
+               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
+               vgic_mmio_read_active, vgic_mmio_write_sactive,
+-              NULL, vgic_mmio_uaccess_write_sactive, 1,
++              vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 1,
+               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_CLEAR,
+               vgic_mmio_read_active, vgic_mmio_write_cactive,
+-              NULL, vgic_mmio_uaccess_write_cactive, 1,
++              vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive, 1,
+               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PRI,
+               vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,
+diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
+index 7dfd15dbb308e..4c5909e38f78a 100644
+--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
++++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
+@@ -491,11 +491,11 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = {
+               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISACTIVER,
+               vgic_mmio_read_active, vgic_mmio_write_sactive,
+-              NULL, vgic_mmio_uaccess_write_sactive, 1,
++              vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 1,
+               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICACTIVER,
+               vgic_mmio_read_active, vgic_mmio_write_cactive,
+-              NULL, vgic_mmio_uaccess_write_cactive,
++              vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive,
+               1, VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_IPRIORITYR,
+               vgic_mmio_read_priority, vgic_mmio_write_priority, NULL, NULL,
+@@ -563,12 +563,12 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = {
+               VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISACTIVER0,
+               vgic_mmio_read_active, vgic_mmio_write_sactive,
+-              NULL, vgic_mmio_uaccess_write_sactive,
+-              4, VGIC_ACCESS_32bit),
++              vgic_uaccess_read_active, vgic_mmio_uaccess_write_sactive, 4,
++              VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICACTIVER0,
+               vgic_mmio_read_active, vgic_mmio_write_cactive,
+-              NULL, vgic_mmio_uaccess_write_cactive,
+-              4, VGIC_ACCESS_32bit),
++              vgic_uaccess_read_active, vgic_mmio_uaccess_write_cactive, 4,
++              VGIC_ACCESS_32bit),
+       REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IPRIORITYR0,
+               vgic_mmio_read_priority, vgic_mmio_write_priority, 32,
+               VGIC_ACCESS_32bit | VGIC_ACCESS_8bit),
+diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
+index 7eacf00e5abeb..fb1dcd397b93a 100644
+--- a/virt/kvm/arm/vgic/vgic-mmio.c
++++ b/virt/kvm/arm/vgic/vgic-mmio.c
+@@ -300,8 +300,39 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+       }
+ }
+-unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+-                                  gpa_t addr, unsigned int len)
++
++/*
++ * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
++ * is not queued on some running VCPU's LRs, because then the change to the
++ * active state can be overwritten when the VCPU's state is synced coming back
++ * from the guest.
++ *
++ * For shared interrupts as well as GICv3 private interrupts, we have to
++ * stop all the VCPUs because interrupts can be migrated while we don't hold
++ * the IRQ locks and we don't want to be chasing moving targets.
++ *
++ * For GICv2 private interrupts we don't have to do anything because
++ * userspace accesses to the VGIC state already require all VCPUs to be
++ * stopped, and only the VCPU itself can modify its private interrupts
++ * active state, which guarantees that the VCPU is not running.
++ */
++static void vgic_access_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
++{
++      if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
++          intid >= VGIC_NR_PRIVATE_IRQS)
++              kvm_arm_halt_guest(vcpu->kvm);
++}
++
++/* See vgic_access_active_prepare */
++static void vgic_access_active_finish(struct kvm_vcpu *vcpu, u32 intid)
++{
++      if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
++          intid >= VGIC_NR_PRIVATE_IRQS)
++              kvm_arm_resume_guest(vcpu->kvm);
++}
++
++static unsigned long __vgic_mmio_read_active(struct kvm_vcpu *vcpu,
++                                           gpa_t addr, unsigned int len)
+ {
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       u32 value = 0;
+@@ -311,6 +342,10 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+       for (i = 0; i < len * 8; i++) {
+               struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
++              /*
++               * Even for HW interrupts, don't evaluate the HW state as
++               * all the guest is interested in is the virtual state.
++               */
+               if (irq->active)
+                       value |= (1U << i);
+@@ -320,6 +355,29 @@ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+       return value;
+ }
++unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
++                                  gpa_t addr, unsigned int len)
++{
++      u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
++      u32 val;
++
++      mutex_lock(&vcpu->kvm->lock);
++      vgic_access_active_prepare(vcpu, intid);
++
++      val = __vgic_mmio_read_active(vcpu, addr, len);
++
++      vgic_access_active_finish(vcpu, intid);
++      mutex_unlock(&vcpu->kvm->lock);
++
++      return val;
++}
++
++unsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu,
++                                  gpa_t addr, unsigned int len)
++{
++      return __vgic_mmio_read_active(vcpu, addr, len);
++}
++
+ /* Must be called with irq->irq_lock held */
+ static void vgic_hw_irq_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+                                     bool active, bool is_uaccess)
+@@ -371,36 +429,6 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+ }
+-/*
+- * If we are fiddling with an IRQ's active state, we have to make sure the IRQ
+- * is not queued on some running VCPU's LRs, because then the change to the
+- * active state can be overwritten when the VCPU's state is synced coming back
+- * from the guest.
+- *
+- * For shared interrupts, we have to stop all the VCPUs because interrupts can
+- * be migrated while we don't hold the IRQ locks and we don't want to be
+- * chasing moving targets.
+- *
+- * For private interrupts we don't have to do anything because userspace
+- * accesses to the VGIC state already require all VCPUs to be stopped, and
+- * only the VCPU itself can modify its private interrupts active state, which
+- * guarantees that the VCPU is not running.
+- */
+-static void vgic_change_active_prepare(struct kvm_vcpu *vcpu, u32 intid)
+-{
+-      if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
+-          intid >= VGIC_NR_PRIVATE_IRQS)
+-              kvm_arm_halt_guest(vcpu->kvm);
+-}
+-
+-/* See vgic_change_active_prepare */
+-static void vgic_change_active_finish(struct kvm_vcpu *vcpu, u32 intid)
+-{
+-      if (vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3 ||
+-          intid >= VGIC_NR_PRIVATE_IRQS)
+-              kvm_arm_resume_guest(vcpu->kvm);
+-}
+-
+ static void __vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+                                     gpa_t addr, unsigned int len,
+                                     unsigned long val)
+@@ -422,11 +450,11 @@ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       mutex_lock(&vcpu->kvm->lock);
+-      vgic_change_active_prepare(vcpu, intid);
++      vgic_access_active_prepare(vcpu, intid);
+       __vgic_mmio_write_cactive(vcpu, addr, len, val);
+-      vgic_change_active_finish(vcpu, intid);
++      vgic_access_active_finish(vcpu, intid);
+       mutex_unlock(&vcpu->kvm->lock);
+ }
+@@ -459,11 +487,11 @@ void vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
+       u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
+       mutex_lock(&vcpu->kvm->lock);
+-      vgic_change_active_prepare(vcpu, intid);
++      vgic_access_active_prepare(vcpu, intid);
+       __vgic_mmio_write_sactive(vcpu, addr, len, val);
+-      vgic_change_active_finish(vcpu, intid);
++      vgic_access_active_finish(vcpu, intid);
+       mutex_unlock(&vcpu->kvm->lock);
+ }
+diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
+index 836f418f1ee80..b6aff52524299 100644
+--- a/virt/kvm/arm/vgic/vgic-mmio.h
++++ b/virt/kvm/arm/vgic/vgic-mmio.h
+@@ -157,6 +157,9 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+ unsigned long vgic_mmio_read_active(struct kvm_vcpu *vcpu,
+                                   gpa_t addr, unsigned int len);
++unsigned long vgic_uaccess_read_active(struct kvm_vcpu *vcpu,
++                                  gpa_t addr, unsigned int len);
++
+ void vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
+                            gpa_t addr, unsigned int len,
+                            unsigned long val);
+-- 
+2.20.1
+
diff --git a/queue-5.4/net-moxa-fix-a-potential-double-free_irq.patch b/queue-5.4/net-moxa-fix-a-potential-double-free_irq.patch
new file mode 100644 (file)
index 0000000..6929def
--- /dev/null
@@ -0,0 +1,36 @@
+From 66fd85f33b897af477045731093a37708c125973 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 26 Apr 2020 22:59:21 +0200
+Subject: net: moxa: Fix a potential double 'free_irq()'
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit ee8d2267f0e39a1bfd95532da3a6405004114b27 ]
+
+Should an irq requested with 'devm_request_irq' be released explicitly,
+it should be done by 'devm_free_irq()', not 'free_irq()'.
+
+Fixes: 6c821bd9edc9 ("net: Add MOXA ART SoCs ethernet driver")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/moxa/moxart_ether.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/moxa/moxart_ether.c b/drivers/net/ethernet/moxa/moxart_ether.c
+index e1651756bf9da..f70bb81e1ed65 100644
+--- a/drivers/net/ethernet/moxa/moxart_ether.c
++++ b/drivers/net/ethernet/moxa/moxart_ether.c
+@@ -564,7 +564,7 @@ static int moxart_remove(struct platform_device *pdev)
+       struct net_device *ndev = platform_get_drvdata(pdev);
+       unregister_netdev(ndev);
+-      free_irq(ndev->irq, ndev);
++      devm_free_irq(&pdev->dev, ndev->irq, ndev);
+       moxart_mac_free_memory(ndev);
+       free_netdev(ndev);
+-- 
+2.20.1
+
diff --git a/queue-5.4/net-phy-microchip_t1-add-lan87xx_phy_init-to-initial.patch b/queue-5.4/net-phy-microchip_t1-add-lan87xx_phy_init-to-initial.patch
new file mode 100644 (file)
index 0000000..02708df
--- /dev/null
@@ -0,0 +1,238 @@
+From 4965bcba67ef93ea732ce55a7e4cae79cfafbb15 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Apr 2020 11:51:41 -0400
+Subject: net: phy: microchip_t1: add lan87xx_phy_init to initialize the
+ lan87xx phy.
+
+From: Yuiko Oshino <yuiko.oshino@microchip.com>
+
+[ Upstream commit 63edbcceef612bdd95fa28ce100460c7b79008a4 ]
+
+lan87xx_phy_init() initializes the lan87xx phy hardware
+including its TC10 Wake-up and Sleep features.
+
+Fixes: 3e50d2da5850 ("Add driver for Microchip LAN87XX T1 PHYs")
+Signed-off-by: Yuiko Oshino <yuiko.oshino@microchip.com>
+v0->v1:
+    - Add more details in the commit message and source comments.
+    - Update to the latest initialization sequences.
+    - Add access_ereg_modify_changed().
+    - Fix access_ereg() to access SMI bank correctly.
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/phy/microchip_t1.c | 171 +++++++++++++++++++++++++++++++++
+ 1 file changed, 171 insertions(+)
+
+diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
+index 001def4509c29..fed3e395f18e1 100644
+--- a/drivers/net/phy/microchip_t1.c
++++ b/drivers/net/phy/microchip_t1.c
+@@ -3,9 +3,21 @@
+ #include <linux/kernel.h>
+ #include <linux/module.h>
++#include <linux/delay.h>
+ #include <linux/mii.h>
+ #include <linux/phy.h>
++/* External Register Control Register */
++#define LAN87XX_EXT_REG_CTL                     (0x14)
++#define LAN87XX_EXT_REG_CTL_RD_CTL              (0x1000)
++#define LAN87XX_EXT_REG_CTL_WR_CTL              (0x0800)
++
++/* External Register Read Data Register */
++#define LAN87XX_EXT_REG_RD_DATA                 (0x15)
++
++/* External Register Write Data Register */
++#define LAN87XX_EXT_REG_WR_DATA                 (0x16)
++
+ /* Interrupt Source Register */
+ #define LAN87XX_INTERRUPT_SOURCE                (0x18)
+@@ -14,9 +26,160 @@
+ #define LAN87XX_MASK_LINK_UP                    (0x0004)
+ #define LAN87XX_MASK_LINK_DOWN                  (0x0002)
++/* phyaccess nested types */
++#define       PHYACC_ATTR_MODE_READ           0
++#define       PHYACC_ATTR_MODE_WRITE          1
++#define       PHYACC_ATTR_MODE_MODIFY         2
++
++#define       PHYACC_ATTR_BANK_SMI            0
++#define       PHYACC_ATTR_BANK_MISC           1
++#define       PHYACC_ATTR_BANK_PCS            2
++#define       PHYACC_ATTR_BANK_AFE            3
++#define       PHYACC_ATTR_BANK_MAX            7
++
+ #define DRIVER_AUTHOR "Nisar Sayed <nisar.sayed@microchip.com>"
+ #define DRIVER_DESC   "Microchip LAN87XX T1 PHY driver"
++struct access_ereg_val {
++      u8  mode;
++      u8  bank;
++      u8  offset;
++      u16 val;
++      u16 mask;
++};
++
++static int access_ereg(struct phy_device *phydev, u8 mode, u8 bank,
++                     u8 offset, u16 val)
++{
++      u16 ereg = 0;
++      int rc = 0;
++
++      if (mode > PHYACC_ATTR_MODE_WRITE || bank > PHYACC_ATTR_BANK_MAX)
++              return -EINVAL;
++
++      if (bank == PHYACC_ATTR_BANK_SMI) {
++              if (mode == PHYACC_ATTR_MODE_WRITE)
++                      rc = phy_write(phydev, offset, val);
++              else
++                      rc = phy_read(phydev, offset);
++              return rc;
++      }
++
++      if (mode == PHYACC_ATTR_MODE_WRITE) {
++              ereg = LAN87XX_EXT_REG_CTL_WR_CTL;
++              rc = phy_write(phydev, LAN87XX_EXT_REG_WR_DATA, val);
++              if (rc < 0)
++                      return rc;
++      } else {
++              ereg = LAN87XX_EXT_REG_CTL_RD_CTL;
++      }
++
++      ereg |= (bank << 8) | offset;
++
++      rc = phy_write(phydev, LAN87XX_EXT_REG_CTL, ereg);
++      if (rc < 0)
++              return rc;
++
++      if (mode == PHYACC_ATTR_MODE_READ)
++              rc = phy_read(phydev, LAN87XX_EXT_REG_RD_DATA);
++
++      return rc;
++}
++
++static int access_ereg_modify_changed(struct phy_device *phydev,
++                                    u8 bank, u8 offset, u16 val, u16 mask)
++{
++      int new = 0, rc = 0;
++
++      if (bank > PHYACC_ATTR_BANK_MAX)
++              return -EINVAL;
++
++      rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ, bank, offset, val);
++      if (rc < 0)
++              return rc;
++
++      new = val | (rc & (mask ^ 0xFFFF));
++      rc = access_ereg(phydev, PHYACC_ATTR_MODE_WRITE, bank, offset, new);
++
++      return rc;
++}
++
++static int lan87xx_phy_init(struct phy_device *phydev)
++{
++      static const struct access_ereg_val init[] = {
++              /* TX Amplitude = 5 */
++              {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_AFE, 0x0B,
++               0x000A, 0x001E},
++              /* Clear SMI interrupts */
++              {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_SMI, 0x18,
++               0, 0},
++              /* Clear MISC interrupts */
++              {PHYACC_ATTR_MODE_READ, PHYACC_ATTR_BANK_MISC, 0x08,
++               0, 0},
++              /* Turn on TC10 Ring Oscillator (ROSC) */
++              {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_MISC, 0x20,
++               0x0020, 0x0020},
++              /* WUR Detect Length to 1.2uS, LPC Detect Length to 1.09uS */
++              {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_PCS, 0x20,
++               0x283C, 0},
++              /* Wake_In Debounce Length to 39uS, Wake_Out Length to 79uS */
++              {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x21,
++               0x274F, 0},
++              /* Enable Auto Wake Forward to Wake_Out, ROSC on, Sleep,
++               * and Wake_In to wake PHY
++               */
++              {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x20,
++               0x80A7, 0},
++              /* Enable WUP Auto Fwd, Enable Wake on MDI, Wakeup Debouncer
++               * to 128 uS
++               */
++              {PHYACC_ATTR_MODE_WRITE, PHYACC_ATTR_BANK_MISC, 0x24,
++               0xF110, 0},
++              /* Enable HW Init */
++              {PHYACC_ATTR_MODE_MODIFY, PHYACC_ATTR_BANK_SMI, 0x1A,
++               0x0100, 0x0100},
++      };
++      int rc, i;
++
++      /* Start manual initialization procedures in Managed Mode */
++      rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
++                                      0x1a, 0x0000, 0x0100);
++      if (rc < 0)
++              return rc;
++
++      /* Soft Reset the SMI block */
++      rc = access_ereg_modify_changed(phydev, PHYACC_ATTR_BANK_SMI,
++                                      0x00, 0x8000, 0x8000);
++      if (rc < 0)
++              return rc;
++
++      /* Check to see if the self-clearing bit is cleared */
++      usleep_range(1000, 2000);
++      rc = access_ereg(phydev, PHYACC_ATTR_MODE_READ,
++                       PHYACC_ATTR_BANK_SMI, 0x00, 0);
++      if (rc < 0)
++              return rc;
++      if ((rc & 0x8000) != 0)
++              return -ETIMEDOUT;
++
++      /* PHY Initialization */
++      for (i = 0; i < ARRAY_SIZE(init); i++) {
++              if (init[i].mode == PHYACC_ATTR_MODE_MODIFY) {
++                      rc = access_ereg_modify_changed(phydev, init[i].bank,
++                                                      init[i].offset,
++                                                      init[i].val,
++                                                      init[i].mask);
++              } else {
++                      rc = access_ereg(phydev, init[i].mode, init[i].bank,
++                                       init[i].offset, init[i].val);
++              }
++              if (rc < 0)
++                      return rc;
++      }
++
++      return 0;
++}
++
+ static int lan87xx_phy_config_intr(struct phy_device *phydev)
+ {
+       int rc, val = 0;
+@@ -40,6 +203,13 @@ static int lan87xx_phy_ack_interrupt(struct phy_device *phydev)
+       return rc < 0 ? rc : 0;
+ }
++static int lan87xx_config_init(struct phy_device *phydev)
++{
++      int rc = lan87xx_phy_init(phydev);
++
++      return rc < 0 ? rc : 0;
++}
++
+ static struct phy_driver microchip_t1_phy_driver[] = {
+       {
+               .phy_id         = 0x0007c150,
+@@ -48,6 +218,7 @@ static struct phy_driver microchip_t1_phy_driver[] = {
+               .features       = PHY_BASIC_T1_FEATURES,
++              .config_init    = lan87xx_config_init,
+               .config_aneg    = genphy_config_aneg,
+               .ack_interrupt  = lan87xx_phy_ack_interrupt,
+-- 
+2.20.1
+
diff --git a/queue-5.4/net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch b/queue-5.4/net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch
new file mode 100644 (file)
index 0000000..b60149a
--- /dev/null
@@ -0,0 +1,50 @@
+From 15464178ccd55b7feccf0be584a6396dabdd4e93 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Apr 2020 08:18:03 +0200
+Subject: net/sonic: Fix a resource leak in an error handling path in
+ 'jazz_sonic_probe()'
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 10e3cc180e64385edc9890c6855acf5ed9ca1339 ]
+
+A call to 'dma_alloc_coherent()' is hidden in 'sonic_alloc_descriptors()',
+called from 'sonic_probe1()'.
+
+This is correctly freed in the remove function, but not in the error
+handling path of the probe function.
+Fix it and add the missing 'dma_free_coherent()' call.
+
+While at it, rename a label in order to be slightly more informative.
+
+Fixes: efcce839360f ("[PATCH] macsonic/jazzsonic network drivers update")
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/natsemi/jazzsonic.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/ethernet/natsemi/jazzsonic.c b/drivers/net/ethernet/natsemi/jazzsonic.c
+index 51fa82b429a3c..40970352d2082 100644
+--- a/drivers/net/ethernet/natsemi/jazzsonic.c
++++ b/drivers/net/ethernet/natsemi/jazzsonic.c
+@@ -235,11 +235,13 @@ static int jazz_sonic_probe(struct platform_device *pdev)
+       err = register_netdev(dev);
+       if (err)
+-              goto out1;
++              goto undo_probe1;
+       return 0;
+-out1:
++undo_probe1:
++      dma_free_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode),
++                        lp->descriptors, lp->descriptors_laddr);
+       release_mem_region(dev->base_addr, SONIC_MEM_SIZE);
+ out:
+       free_netdev(dev);
+-- 
+2.20.1
+
diff --git a/queue-5.4/net_sched-fix-tcm_parent-in-tc-filter-dump.patch b/queue-5.4/net_sched-fix-tcm_parent-in-tc-filter-dump.patch
new file mode 100644 (file)
index 0000000..adf5edc
--- /dev/null
@@ -0,0 +1,114 @@
+From 1ed2f21bc55d1499cefd000672af28be1d446c57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2020 20:53:49 -0700
+Subject: net_sched: fix tcm_parent in tc filter dump
+
+From: Cong Wang <xiyou.wangcong@gmail.com>
+
+[ Upstream commit a7df4870d79b00742da6cc93ca2f336a71db77f7 ]
+
+When we tell kernel to dump filters from root (ffff:ffff),
+those filters on ingress (ffff:0000) are matched, but their
+true parents must be dumped as they are. However, kernel
+dumps just whatever we tell it, that is either ffff:ffff
+or ffff:0000:
+
+ $ nl-cls-list --dev=dummy0 --parent=root
+ cls basic dev dummy0 id none parent root prio 49152 protocol ip match-all
+ cls basic dev dummy0 id :1 parent root prio 49152 protocol ip match-all
+ $ nl-cls-list --dev=dummy0 --parent=ffff:
+ cls basic dev dummy0 id none parent ffff: prio 49152 protocol ip match-all
+ cls basic dev dummy0 id :1 parent ffff: prio 49152 protocol ip match-all
+
+This is confusing and misleading, more importantly this is
+a regression since 4.15, so the old behavior must be restored.
+
+And, when tc filters are installed on a tc class, the parent
+should be the classid, rather than the qdisc handle. Commit
+edf6711c9840 ("net: sched: remove classid and q fields from tcf_proto")
+removed the classid we save for filters, we can just restore
+this classid in tcf_block.
+
+Steps to reproduce this:
+ ip li set dev dummy0 up
+ tc qd add dev dummy0 ingress
+ tc filter add dev dummy0 parent ffff: protocol arp basic action pass
+ tc filter show dev dummy0 root
+
+Before this patch:
+ filter protocol arp pref 49152 basic
+ filter protocol arp pref 49152 basic handle 0x1
+       action order 1: gact action pass
+        random type none pass val 0
+        index 1 ref 1 bind 1
+
+After this patch:
+ filter parent ffff: protocol arp pref 49152 basic
+ filter parent ffff: protocol arp pref 49152 basic handle 0x1
+       action order 1: gact action pass
+        random type none pass val 0
+        index 1 ref 1 bind 1
+
+Fixes: a10fa20101ae ("net: sched: propagate q and parent from caller down to tcf_fill_node")
+Fixes: edf6711c9840 ("net: sched: remove classid and q fields from tcf_proto")
+Cc: Jamal Hadi Salim <jhs@mojatatu.com>
+Cc: Jiri Pirko <jiri@resnulli.us>
+Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
+Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/sch_generic.h | 1 +
+ net/sched/cls_api.c       | 8 ++++----
+ 2 files changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
+index 9fb7cf1cdf36c..3d03756e10699 100644
+--- a/include/net/sch_generic.h
++++ b/include/net/sch_generic.h
+@@ -407,6 +407,7 @@ struct tcf_block {
+       struct mutex lock;
+       struct list_head chain_list;
+       u32 index; /* block index for shared blocks */
++      u32 classid; /* which class this block belongs to */
+       refcount_t refcnt;
+       struct net *net;
+       struct Qdisc *q;
+diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c
+index c2cdd0fc2e709..68c8fc6f535c7 100644
+--- a/net/sched/cls_api.c
++++ b/net/sched/cls_api.c
+@@ -2005,6 +2005,7 @@ static int tc_new_tfilter(struct sk_buff *skb, struct nlmsghdr *n,
+               err = PTR_ERR(block);
+               goto errout;
+       }
++      block->classid = parent;
+       chain_index = tca[TCA_CHAIN] ? nla_get_u32(tca[TCA_CHAIN]) : 0;
+       if (chain_index > TC_ACT_EXT_VAL_MASK) {
+@@ -2547,12 +2548,10 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
+                       return skb->len;
+               parent = tcm->tcm_parent;
+-              if (!parent) {
++              if (!parent)
+                       q = dev->qdisc;
+-                      parent = q->handle;
+-              } else {
++              else
+                       q = qdisc_lookup(dev, TC_H_MAJ(tcm->tcm_parent));
+-              }
+               if (!q)
+                       goto out;
+               cops = q->ops->cl_ops;
+@@ -2568,6 +2567,7 @@ static int tc_dump_tfilter(struct sk_buff *skb, struct netlink_callback *cb)
+               block = cops->tcf_block(q, cl, NULL);
+               if (!block)
+                       goto out;
++              parent = block->classid;
+               if (tcf_block_shared(block))
+                       q = NULL;
+       }
+-- 
+2.20.1
+
index 131a7a00efbc97225b16a734b74dbc64fe9ef1a1..785ea49661e5acfa689bf7324f59fef471499dae 100644 (file)
@@ -1 +1,14 @@
 net-dsa-do-not-make-user-port-errors-fatal.patch
+shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch
+net-phy-microchip_t1-add-lan87xx_phy_init-to-initial.patch
+kvm-arm-vgic-synchronize-the-whole-guest-on-gic-d-r-.patch
+gpio-pca953x-fix-pca953x_gpio_set_config.patch
+sunrpc-add-len-parameter-to-gss_unwrap.patch
+sunrpc-fix-gss-privacy-computation-of-auth-au_ralign.patch
+net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch
+net-moxa-fix-a-potential-double-free_irq.patch
+ftrace-selftests-workaround-cgroup-rt-scheduling-iss.patch
+drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch
+virtio-blk-handle-block_device_operations-callbacks-.patch
+sun6i-dsi-fix-gcc-4.8.patch
+net_sched-fix-tcm_parent-in-tc-filter-dump.patch
diff --git a/queue-5.4/shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch b/queue-5.4/shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch
new file mode 100644 (file)
index 0000000..340771f
--- /dev/null
@@ -0,0 +1,80 @@
+From cdb813cf84b1a7d2a981b54940370e38ed2697c4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Apr 2020 18:14:14 -0700
+Subject: shmem: fix possible deadlocks on shmlock_user_lock
+
+From: Hugh Dickins <hughd@google.com>
+
+[ Upstream commit ea0dfeb4209b4eab954d6e00ed136bc6b48b380d ]
+
+Recent commit 71725ed10c40 ("mm: huge tmpfs: try to split_huge_page()
+when punching hole") has allowed syzkaller to probe deeper, uncovering a
+long-standing lockdep issue between the irq-unsafe shmlock_user_lock,
+the irq-safe xa_lock on mapping->i_pages, and shmem inode's info->lock
+which nests inside xa_lock (or tree_lock) since 4.8's shmem_uncharge().
+
+user_shm_lock(), servicing SysV shmctl(SHM_LOCK), wants
+shmlock_user_lock while its caller shmem_lock() holds info->lock with
+interrupts disabled; but hugetlbfs_file_setup() calls user_shm_lock()
+with interrupts enabled, and might be interrupted by a writeback endio
+wanting xa_lock on i_pages.
+
+This may not risk an actual deadlock, since shmem inodes do not take
+part in writeback accounting, but there are several easy ways to avoid
+it.
+
+Requiring interrupts disabled for shmlock_user_lock would be easy, but
+it's a high-level global lock for which that seems inappropriate.
+Instead, recall that the use of info->lock to guard info->flags in
+shmem_lock() dates from pre-3.1 days, when races with SHMEM_PAGEIN and
+SHMEM_TRUNCATE could occur: nowadays it serves no purpose, the only flag
+added or removed is VM_LOCKED itself, and calls to shmem_lock() an inode
+are already serialized by the caller.
+
+Take info->lock out of the chain and the possibility of deadlock or
+lockdep warning goes away.
+
+Fixes: 4595ef88d136 ("shmem: make shmem_inode_info::lock irq-safe")
+Reported-by: syzbot+c8a8197c8852f566b9d9@syzkaller.appspotmail.com
+Reported-by: syzbot+40b71e145e73f78f81ad@syzkaller.appspotmail.com
+Signed-off-by: Hugh Dickins <hughd@google.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Acked-by: Yang Shi <yang.shi@linux.alibaba.com>
+Cc: Yang Shi <yang.shi@linux.alibaba.com>
+Link: http://lkml.kernel.org/r/alpine.LSU.2.11.2004161707410.16322@eggly.anvils
+Link: https://lore.kernel.org/lkml/000000000000e5838c05a3152f53@google.com/
+Link: https://lore.kernel.org/lkml/0000000000003712b305a331d3b1@google.com/
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/shmem.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/mm/shmem.c b/mm/shmem.c
+index e71b15da19854..98802ca76a5c3 100644
+--- a/mm/shmem.c
++++ b/mm/shmem.c
+@@ -2183,7 +2183,11 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
+       struct shmem_inode_info *info = SHMEM_I(inode);
+       int retval = -ENOMEM;
+-      spin_lock_irq(&info->lock);
++      /*
++       * What serializes the accesses to info->flags?
++       * ipc_lock_object() when called from shmctl_do_lock(),
++       * no serialization needed when called from shm_destroy().
++       */
+       if (lock && !(info->flags & VM_LOCKED)) {
+               if (!user_shm_lock(inode->i_size, user))
+                       goto out_nomem;
+@@ -2198,7 +2202,6 @@ int shmem_lock(struct file *file, int lock, struct user_struct *user)
+       retval = 0;
+ out_nomem:
+-      spin_unlock_irq(&info->lock);
+       return retval;
+ }
+-- 
+2.20.1
+
diff --git a/queue-5.4/sun6i-dsi-fix-gcc-4.8.patch b/queue-5.4/sun6i-dsi-fix-gcc-4.8.patch
new file mode 100644 (file)
index 0000000..83eb3fe
--- /dev/null
@@ -0,0 +1,46 @@
+From 601d96f9061bfff89990c1211dad4c3700577aca Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Apr 2020 23:50:51 +0200
+Subject: sun6i: dsi: fix gcc-4.8
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 3a3a71f97c30983f1627c2c550d43566e9b634d2 ]
+
+Older compilers warn about initializers with incorrect curly
+braces:
+
+drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c: In function 'sun6i_dsi_encoder_enable':
+drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c:720:8: error: missing braces around initializer [-Werror=missing-braces]
+  union phy_configure_opts opts = { 0 };
+        ^
+drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c:720:8: error: (near initialization for 'opts.mipi_dphy') [-Werror=missing-braces]
+
+Use the GNU empty initializer extension to avoid this.
+
+Fixes: bb3b6fcb6849 ("sun6i: dsi: Convert to generic phy handling")
+Reviewed-by: Paul Kocialkowski <paul.kocialkowski@bootlin.com>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Link: https://patchwork.freedesktop.org/patch/msgid/20200428215105.3928459-1-arnd@arndb.de
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+index f83522717488a..4f944ace665d5 100644
+--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
++++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+@@ -718,7 +718,7 @@ static void sun6i_dsi_encoder_enable(struct drm_encoder *encoder)
+       struct drm_display_mode *mode = &encoder->crtc->state->adjusted_mode;
+       struct sun6i_dsi *dsi = encoder_to_sun6i_dsi(encoder);
+       struct mipi_dsi_device *device = dsi->device;
+-      union phy_configure_opts opts = { 0 };
++      union phy_configure_opts opts = { };
+       struct phy_configure_opts_mipi_dphy *cfg = &opts.mipi_dphy;
+       u16 delay;
+-- 
+2.20.1
+
diff --git a/queue-5.4/sunrpc-add-len-parameter-to-gss_unwrap.patch b/queue-5.4/sunrpc-add-len-parameter-to-gss_unwrap.patch
new file mode 100644 (file)
index 0000000..d390495
--- /dev/null
@@ -0,0 +1,284 @@
+From 020038556a356839799d2014ab0e0aebdc733c4f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Apr 2020 21:06:23 -0400
+Subject: SUNRPC: Add "@len" parameter to gss_unwrap()
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit 31c9590ae468478fe47dc0f5f0d3562b2f69450e ]
+
+Refactor: This is a pre-requisite to fixing the client-side ralign
+computation in gss_unwrap_resp_priv().
+
+The length value is passed in explicitly rather that as the value
+of buf->len. This will subsequently allow gss_unwrap_kerberos_v1()
+to compute a slack and align value, instead of computing it in
+gss_unwrap_resp_priv().
+
+Fixes: 35e77d21baa0 ("SUNRPC: Add rpc_auth::au_ralign field")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/sunrpc/gss_api.h        |  2 ++
+ include/linux/sunrpc/gss_krb5.h       |  6 +++---
+ net/sunrpc/auth_gss/auth_gss.c        |  4 ++--
+ net/sunrpc/auth_gss/gss_krb5_crypto.c |  8 ++++----
+ net/sunrpc/auth_gss/gss_krb5_wrap.c   | 26 +++++++++++++++-----------
+ net/sunrpc/auth_gss/gss_mech_switch.c |  3 ++-
+ net/sunrpc/auth_gss/svcauth_gss.c     |  8 ++------
+ 7 files changed, 30 insertions(+), 27 deletions(-)
+
+diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
+index 5ac5db4d295f9..d1c6f65de76e7 100644
+--- a/include/linux/sunrpc/gss_api.h
++++ b/include/linux/sunrpc/gss_api.h
+@@ -67,6 +67,7 @@ u32 gss_wrap(
+ u32 gss_unwrap(
+               struct gss_ctx          *ctx_id,
+               int                     offset,
++              int                     len,
+               struct xdr_buf          *inbuf);
+ u32 gss_delete_sec_context(
+               struct gss_ctx          **ctx_id);
+@@ -127,6 +128,7 @@ struct gss_api_ops {
+       u32 (*gss_unwrap)(
+                       struct gss_ctx          *ctx_id,
+                       int                     offset,
++                      int                     len,
+                       struct xdr_buf          *buf);
+       void (*gss_delete_sec_context)(
+                       void                    *internal_ctx_id);
+diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h
+index 02c0412e368cc..07930bc9ad604 100644
+--- a/include/linux/sunrpc/gss_krb5.h
++++ b/include/linux/sunrpc/gss_krb5.h
+@@ -83,7 +83,7 @@ struct gss_krb5_enctype {
+       u32 (*encrypt_v2) (struct krb5_ctx *kctx, u32 offset,
+                          struct xdr_buf *buf,
+                          struct page **pages); /* v2 encryption function */
+-      u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset,
++      u32 (*decrypt_v2) (struct krb5_ctx *kctx, u32 offset, u32 len,
+                          struct xdr_buf *buf, u32 *headskip,
+                          u32 *tailskip);      /* v2 decryption function */
+ };
+@@ -255,7 +255,7 @@ gss_wrap_kerberos(struct gss_ctx *ctx_id, int offset,
+               struct xdr_buf *outbuf, struct page **pages);
+ u32
+-gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset,
++gss_unwrap_kerberos(struct gss_ctx *ctx_id, int offset, int len,
+               struct xdr_buf *buf);
+@@ -312,7 +312,7 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+                    struct page **pages);
+ u32
+-gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset,
++gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
+                    struct xdr_buf *buf, u32 *plainoffset,
+                    u32 *plainlen);
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index ff5fcb3e12084..c8782f4e20ec2 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -2041,9 +2041,9 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
+       offset = (u8 *)(p) - (u8 *)head->iov_base;
+       if (offset + opaque_len > rcv_buf->len)
+               goto unwrap_failed;
+-      rcv_buf->len = offset + opaque_len;
+-      maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset, rcv_buf);
++      maj_stat = gss_unwrap(ctx->gc_gss_ctx, offset,
++                            offset + opaque_len, rcv_buf);
+       if (maj_stat == GSS_S_CONTEXT_EXPIRED)
+               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       if (maj_stat != GSS_S_COMPLETE)
+diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+index 6f2d30d7b766d..e7180da1fc6a1 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_crypto.c
++++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c
+@@ -851,8 +851,8 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset,
+ }
+ u32
+-gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+-                   u32 *headskip, u32 *tailskip)
++gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, u32 len,
++                   struct xdr_buf *buf, u32 *headskip, u32 *tailskip)
+ {
+       struct xdr_buf subbuf;
+       u32 ret = 0;
+@@ -881,7 +881,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+       /* create a segment skipping the header and leaving out the checksum */
+       xdr_buf_subsegment(buf, &subbuf, offset + GSS_KRB5_TOK_HDR_LEN,
+-                                  (buf->len - offset - GSS_KRB5_TOK_HDR_LEN -
++                                  (len - offset - GSS_KRB5_TOK_HDR_LEN -
+                                    kctx->gk5e->cksumlength));
+       nblocks = (subbuf.len + blocksize - 1) / blocksize;
+@@ -926,7 +926,7 @@ gss_krb5_aes_decrypt(struct krb5_ctx *kctx, u32 offset, struct xdr_buf *buf,
+               goto out_err;
+       /* Get the packet's hmac value */
+-      ret = read_bytes_from_xdr_buf(buf, buf->len - kctx->gk5e->cksumlength,
++      ret = read_bytes_from_xdr_buf(buf, len - kctx->gk5e->cksumlength,
+                                     pkt_hmac, kctx->gk5e->cksumlength);
+       if (ret)
+               goto out_err;
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index 14a0aff0cd84c..a7cafc29d61ee 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -261,7 +261,8 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ }
+ static u32
+-gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
++gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len,
++                     struct xdr_buf *buf)
+ {
+       int                     signalg;
+       int                     sealalg;
+@@ -284,7 +285,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+       ptr = (u8 *)buf->head[0].iov_base + offset;
+       if (g_verify_token_header(&kctx->mech_used, &bodysize, &ptr,
+-                                      buf->len - offset))
++                                      len - offset))
+               return GSS_S_DEFECTIVE_TOKEN;
+       if ((ptr[0] != ((KG_TOK_WRAP_MSG >> 8) & 0xff)) ||
+@@ -324,6 +325,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+           (!kctx->initiate && direction != 0))
+               return GSS_S_BAD_SIG;
++      buf->len = len;
+       if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC) {
+               struct crypto_sync_skcipher *cipher;
+               int err;
+@@ -376,7 +378,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+       data_len = (buf->head[0].iov_base + buf->head[0].iov_len) - data_start;
+       memmove(orig_start, data_start, data_len);
+       buf->head[0].iov_len -= (data_start - orig_start);
+-      buf->len -= (data_start - orig_start);
++      buf->len = len - (data_start - orig_start);
+       if (gss_krb5_remove_padding(buf, blocksize))
+               return GSS_S_DEFECTIVE_TOKEN;
+@@ -486,7 +488,8 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
+ }
+ static u32
+-gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
++gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len,
++                     struct xdr_buf *buf)
+ {
+       s32             now;
+       u8              *ptr;
+@@ -532,7 +535,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+       if (rrc != 0)
+               rotate_left(offset + 16, buf, rrc);
+-      err = (*kctx->gk5e->decrypt_v2)(kctx, offset, buf,
++      err = (*kctx->gk5e->decrypt_v2)(kctx, offset, len, buf,
+                                       &headskip, &tailskip);
+       if (err)
+               return GSS_S_FAILURE;
+@@ -542,7 +545,7 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+        * it against the original
+        */
+       err = read_bytes_from_xdr_buf(buf,
+-                              buf->len - GSS_KRB5_TOK_HDR_LEN - tailskip,
++                              len - GSS_KRB5_TOK_HDR_LEN - tailskip,
+                               decrypted_hdr, GSS_KRB5_TOK_HDR_LEN);
+       if (err) {
+               dprintk("%s: error %u getting decrypted_hdr\n", __func__, err);
+@@ -568,14 +571,14 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, struct xdr_buf *buf)
+        * Note that buf->head[0].iov_len may indicate the available
+        * head buffer space rather than that actually occupied.
+        */
+-      movelen = min_t(unsigned int, buf->head[0].iov_len, buf->len);
++      movelen = min_t(unsigned int, buf->head[0].iov_len, len);
+       movelen -= offset + GSS_KRB5_TOK_HDR_LEN + headskip;
+       if (offset + GSS_KRB5_TOK_HDR_LEN + headskip + movelen >
+           buf->head[0].iov_len)
+               return GSS_S_FAILURE;
+       memmove(ptr, ptr + GSS_KRB5_TOK_HDR_LEN + headskip, movelen);
+       buf->head[0].iov_len -= GSS_KRB5_TOK_HDR_LEN + headskip;
+-      buf->len -= GSS_KRB5_TOK_HDR_LEN + headskip;
++      buf->len = len - GSS_KRB5_TOK_HDR_LEN + headskip;
+       /* Trim off the trailing "extra count" and checksum blob */
+       buf->len -= ec + GSS_KRB5_TOK_HDR_LEN + tailskip;
+@@ -603,7 +606,8 @@ gss_wrap_kerberos(struct gss_ctx *gctx, int offset,
+ }
+ u32
+-gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
++gss_unwrap_kerberos(struct gss_ctx *gctx, int offset,
++                  int len, struct xdr_buf *buf)
+ {
+       struct krb5_ctx *kctx = gctx->internal_ctx_id;
+@@ -613,9 +617,9 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset, struct xdr_buf *buf)
+       case ENCTYPE_DES_CBC_RAW:
+       case ENCTYPE_DES3_CBC_RAW:
+       case ENCTYPE_ARCFOUR_HMAC:
+-              return gss_unwrap_kerberos_v1(kctx, offset, buf);
++              return gss_unwrap_kerberos_v1(kctx, offset, len, buf);
+       case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+       case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+-              return gss_unwrap_kerberos_v2(kctx, offset, buf);
++              return gss_unwrap_kerberos_v2(kctx, offset, len, buf);
+       }
+ }
+diff --git a/net/sunrpc/auth_gss/gss_mech_switch.c b/net/sunrpc/auth_gss/gss_mech_switch.c
+index 82060099a4291..8fa924c8e282c 100644
+--- a/net/sunrpc/auth_gss/gss_mech_switch.c
++++ b/net/sunrpc/auth_gss/gss_mech_switch.c
+@@ -438,10 +438,11 @@ gss_wrap(struct gss_ctx  *ctx_id,
+ u32
+ gss_unwrap(struct gss_ctx     *ctx_id,
+          int                  offset,
++         int                  len,
+          struct xdr_buf       *buf)
+ {
+       return ctx_id->mech_type->gm_ops
+-              ->gss_unwrap(ctx_id, offset, buf);
++              ->gss_unwrap(ctx_id, offset, len, buf);
+ }
+diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c
+index ed20fa8a6f707..ab3a9c49a859a 100644
+--- a/net/sunrpc/auth_gss/svcauth_gss.c
++++ b/net/sunrpc/auth_gss/svcauth_gss.c
+@@ -925,7 +925,7 @@ static int
+ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gss_ctx *ctx)
+ {
+       u32 priv_len, maj_stat;
+-      int pad, saved_len, remaining_len, offset;
++      int pad, remaining_len, offset;
+       clear_bit(RQ_SPLICE_OK, &rqstp->rq_flags);
+@@ -945,12 +945,8 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs
+       buf->len -= pad;
+       fix_priv_head(buf, pad);
+-      /* Maybe it would be better to give gss_unwrap a length parameter: */
+-      saved_len = buf->len;
+-      buf->len = priv_len;
+-      maj_stat = gss_unwrap(ctx, 0, buf);
++      maj_stat = gss_unwrap(ctx, 0, priv_len, buf);
+       pad = priv_len - buf->len;
+-      buf->len = saved_len;
+       buf->len -= pad;
+       /* The upper layers assume the buffer is aligned on 4-byte boundaries.
+        * In the krb5p case, at least, the data ends up offset, so we need to
+-- 
+2.20.1
+
diff --git a/queue-5.4/sunrpc-fix-gss-privacy-computation-of-auth-au_ralign.patch b/queue-5.4/sunrpc-fix-gss-privacy-computation-of-auth-au_ralign.patch
new file mode 100644 (file)
index 0000000..93b26c7
--- /dev/null
@@ -0,0 +1,142 @@
+From 6658b77c5e9b44cf28b567ccf796735427a7e488 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 18 Apr 2020 14:38:19 -0400
+Subject: SUNRPC: Fix GSS privacy computation of auth->au_ralign
+
+From: Chuck Lever <chuck.lever@oracle.com>
+
+[ Upstream commit a7e429a6fa6d612d1dacde96c885dc1bb4a9f400 ]
+
+When the au_ralign field was added to gss_unwrap_resp_priv, the
+wrong calculation was used. Setting au_rslack == au_ralign is
+probably correct for kerberos_v1 privacy, but kerberos_v2 privacy
+adds additional GSS data after the clear text RPC message.
+au_ralign needs to be smaller than au_rslack in that fairly common
+case.
+
+When xdr_buf_trim() is restored to gss_unwrap_kerberos_v2(), it does
+exactly what I feared it would: it trims off part of the clear text
+RPC message. However, that's because rpc_prepare_reply_pages() does
+not set up the rq_rcv_buf's tail correctly because au_ralign is too
+large.
+
+Fixing the au_ralign computation also corrects the alignment of
+rq_rcv_buf->pages so that the client does not have to shift reply
+data payloads after they are received.
+
+Fixes: 35e77d21baa0 ("SUNRPC: Add rpc_auth::au_ralign field")
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/sunrpc/gss_api.h      |  1 +
+ net/sunrpc/auth_gss/auth_gss.c      |  8 +++-----
+ net/sunrpc/auth_gss/gss_krb5_wrap.c | 19 +++++++++++++++----
+ 3 files changed, 19 insertions(+), 9 deletions(-)
+
+diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h
+index d1c6f65de76e7..d4326d6662a44 100644
+--- a/include/linux/sunrpc/gss_api.h
++++ b/include/linux/sunrpc/gss_api.h
+@@ -22,6 +22,7 @@
+ struct gss_ctx {
+       struct gss_api_mech     *mech_type;
+       void                    *internal_ctx_id;
++      unsigned int            slack, align;
+ };
+ #define GSS_C_NO_BUFFER               ((struct xdr_netobj) 0)
+diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
+index c8782f4e20ec2..5fc6c028f89c0 100644
+--- a/net/sunrpc/auth_gss/auth_gss.c
++++ b/net/sunrpc/auth_gss/auth_gss.c
+@@ -2030,7 +2030,6 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
+       struct xdr_buf *rcv_buf = &rqstp->rq_rcv_buf;
+       struct kvec *head = rqstp->rq_rcv_buf.head;
+       struct rpc_auth *auth = cred->cr_auth;
+-      unsigned int savedlen = rcv_buf->len;
+       u32 offset, opaque_len, maj_stat;
+       __be32 *p;
+@@ -2057,10 +2056,9 @@ gss_unwrap_resp_priv(struct rpc_task *task, struct rpc_cred *cred,
+        */
+       xdr_init_decode(xdr, rcv_buf, p, rqstp);
+-      auth->au_rslack = auth->au_verfsize + 2 +
+-                        XDR_QUADLEN(savedlen - rcv_buf->len);
+-      auth->au_ralign = auth->au_verfsize + 2 +
+-                        XDR_QUADLEN(savedlen - rcv_buf->len);
++      auth->au_rslack = auth->au_verfsize + 2 + ctx->gc_gss_ctx->slack;
++      auth->au_ralign = auth->au_verfsize + 2 + ctx->gc_gss_ctx->align;
++
+       return 0;
+ unwrap_failed:
+       trace_rpcgss_unwrap_failed(task);
+diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+index a7cafc29d61ee..644ecb26100aa 100644
+--- a/net/sunrpc/auth_gss/gss_krb5_wrap.c
++++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c
+@@ -262,7 +262,8 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset,
+ static u32
+ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len,
+-                     struct xdr_buf *buf)
++                     struct xdr_buf *buf, unsigned int *slack,
++                     unsigned int *align)
+ {
+       int                     signalg;
+       int                     sealalg;
+@@ -280,6 +281,7 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len,
+       u32                     conflen = kctx->gk5e->conflen;
+       int                     crypt_offset;
+       u8                      *cksumkey;
++      unsigned int            saved_len = buf->len;
+       dprintk("RPC:       gss_unwrap_kerberos\n");
+@@ -383,6 +385,10 @@ gss_unwrap_kerberos_v1(struct krb5_ctx *kctx, int offset, int len,
+       if (gss_krb5_remove_padding(buf, blocksize))
+               return GSS_S_DEFECTIVE_TOKEN;
++      /* slack must include room for krb5 padding */
++      *slack = XDR_QUADLEN(saved_len - buf->len);
++      /* The GSS blob always precedes the RPC message payload */
++      *align = *slack;
+       return GSS_S_COMPLETE;
+ }
+@@ -489,7 +495,8 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset,
+ static u32
+ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len,
+-                     struct xdr_buf *buf)
++                     struct xdr_buf *buf, unsigned int *slack,
++                     unsigned int *align)
+ {
+       s32             now;
+       u8              *ptr;
+@@ -583,6 +590,8 @@ gss_unwrap_kerberos_v2(struct krb5_ctx *kctx, int offset, int len,
+       /* Trim off the trailing "extra count" and checksum blob */
+       buf->len -= ec + GSS_KRB5_TOK_HDR_LEN + tailskip;
++      *align = XDR_QUADLEN(GSS_KRB5_TOK_HDR_LEN + headskip);
++      *slack = *align + XDR_QUADLEN(ec + GSS_KRB5_TOK_HDR_LEN + tailskip);
+       return GSS_S_COMPLETE;
+ }
+@@ -617,9 +626,11 @@ gss_unwrap_kerberos(struct gss_ctx *gctx, int offset,
+       case ENCTYPE_DES_CBC_RAW:
+       case ENCTYPE_DES3_CBC_RAW:
+       case ENCTYPE_ARCFOUR_HMAC:
+-              return gss_unwrap_kerberos_v1(kctx, offset, len, buf);
++              return gss_unwrap_kerberos_v1(kctx, offset, len, buf,
++                                            &gctx->slack, &gctx->align);
+       case ENCTYPE_AES128_CTS_HMAC_SHA1_96:
+       case ENCTYPE_AES256_CTS_HMAC_SHA1_96:
+-              return gss_unwrap_kerberos_v2(kctx, offset, len, buf);
++              return gss_unwrap_kerberos_v2(kctx, offset, len, buf,
++                                            &gctx->slack, &gctx->align);
+       }
+ }
+-- 
+2.20.1
+
diff --git a/queue-5.4/virtio-blk-handle-block_device_operations-callbacks-.patch b/queue-5.4/virtio-blk-handle-block_device_operations-callbacks-.patch
new file mode 100644 (file)
index 0000000..47c763c
--- /dev/null
@@ -0,0 +1,217 @@
+From dfe41089f85b6450f36e364e8ff9ba361f230472 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Apr 2020 15:04:42 +0100
+Subject: virtio-blk: handle block_device_operations callbacks after hot unplug
+
+From: Stefan Hajnoczi <stefanha@redhat.com>
+
+[ Upstream commit 90b5feb8c4bebc76c27fcaf3e1a0e5ca2d319e9e ]
+
+A userspace process holding a file descriptor to a virtio_blk device can
+still invoke block_device_operations after hot unplug.  This leads to a
+use-after-free accessing vblk->vdev in virtblk_getgeo() when
+ioctl(HDIO_GETGEO) is invoked:
+
+  BUG: unable to handle kernel NULL pointer dereference at 0000000000000090
+  IP: [<ffffffffc00e5450>] virtio_check_driver_offered_feature+0x10/0x90 [virtio]
+  PGD 800000003a92f067 PUD 3a930067 PMD 0
+  Oops: 0000 [#1] SMP
+  CPU: 0 PID: 1310 Comm: hdio-getgeo Tainted: G           OE  ------------   3.10.0-1062.el7.x86_64 #1
+  Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.13.0-0-gf21b5a4aeb02-prebuilt.qemu.org 04/01/2014
+  task: ffff9be5fbfb8000 ti: ffff9be5fa890000 task.ti: ffff9be5fa890000
+  RIP: 0010:[<ffffffffc00e5450>]  [<ffffffffc00e5450>] virtio_check_driver_offered_feature+0x10/0x90 [virtio]
+  RSP: 0018:ffff9be5fa893dc8  EFLAGS: 00010246
+  RAX: ffff9be5fc3f3400 RBX: ffff9be5fa893e30 RCX: 0000000000000000
+  RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffff9be5fbc10b40
+  RBP: ffff9be5fa893dc8 R08: 0000000000000301 R09: 0000000000000301
+  R10: 0000000000000000 R11: 0000000000000000 R12: ffff9be5fdc24680
+  R13: ffff9be5fbc10b40 R14: ffff9be5fbc10480 R15: 0000000000000000
+  FS:  00007f1bfb968740(0000) GS:ffff9be5ffc00000(0000) knlGS:0000000000000000
+  CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+  CR2: 0000000000000090 CR3: 000000003a894000 CR4: 0000000000360ff0
+  DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+  DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+  Call Trace:
+   [<ffffffffc016ac37>] virtblk_getgeo+0x47/0x110 [virtio_blk]
+   [<ffffffff8d3f200d>] ? handle_mm_fault+0x39d/0x9b0
+   [<ffffffff8d561265>] blkdev_ioctl+0x1f5/0xa20
+   [<ffffffff8d488771>] block_ioctl+0x41/0x50
+   [<ffffffff8d45d9e0>] do_vfs_ioctl+0x3a0/0x5a0
+   [<ffffffff8d45dc81>] SyS_ioctl+0xa1/0xc0
+
+A related problem is that virtblk_remove() leaks the vd_index_ida index
+when something still holds a reference to vblk->disk during hot unplug.
+This causes virtio-blk device names to be lost (vda, vdb, etc).
+
+Fix these issues by protecting vblk->vdev with a mutex and reference
+counting vblk so the vd_index_ida index can be removed in all cases.
+
+Fixes: 48e4043d4529 ("virtio: add virtio disk geometry feature")
+Reported-by: Lance Digby <ldigby@redhat.com>
+Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
+Link: https://lore.kernel.org/r/20200430140442.171016-1-stefanha@redhat.com
+Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
+Reviewed-by: Stefano Garzarella <sgarzare@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/block/virtio_blk.c | 86 ++++++++++++++++++++++++++++++++++----
+ 1 file changed, 78 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
+index a55383b139df9..0cf2fe2902307 100644
+--- a/drivers/block/virtio_blk.c
++++ b/drivers/block/virtio_blk.c
+@@ -33,6 +33,15 @@ struct virtio_blk_vq {
+ } ____cacheline_aligned_in_smp;
+ struct virtio_blk {
++      /*
++       * This mutex must be held by anything that may run after
++       * virtblk_remove() sets vblk->vdev to NULL.
++       *
++       * blk-mq, virtqueue processing, and sysfs attribute code paths are
++       * shut down before vblk->vdev is set to NULL and therefore do not need
++       * to hold this mutex.
++       */
++      struct mutex vdev_mutex;
+       struct virtio_device *vdev;
+       /* The disk structure for the kernel. */
+@@ -44,6 +53,13 @@ struct virtio_blk {
+       /* Process context for config space updates */
+       struct work_struct config_work;
++      /*
++       * Tracks references from block_device_operations open/release and
++       * virtio_driver probe/remove so this object can be freed once no
++       * longer in use.
++       */
++      refcount_t refs;
++
+       /* What host tells us, plus 2 for header & tailer. */
+       unsigned int sg_elems;
+@@ -388,10 +404,55 @@ static int virtblk_get_id(struct gendisk *disk, char *id_str)
+       return err;
+ }
++static void virtblk_get(struct virtio_blk *vblk)
++{
++      refcount_inc(&vblk->refs);
++}
++
++static void virtblk_put(struct virtio_blk *vblk)
++{
++      if (refcount_dec_and_test(&vblk->refs)) {
++              ida_simple_remove(&vd_index_ida, vblk->index);
++              mutex_destroy(&vblk->vdev_mutex);
++              kfree(vblk);
++      }
++}
++
++static int virtblk_open(struct block_device *bd, fmode_t mode)
++{
++      struct virtio_blk *vblk = bd->bd_disk->private_data;
++      int ret = 0;
++
++      mutex_lock(&vblk->vdev_mutex);
++
++      if (vblk->vdev)
++              virtblk_get(vblk);
++      else
++              ret = -ENXIO;
++
++      mutex_unlock(&vblk->vdev_mutex);
++      return ret;
++}
++
++static void virtblk_release(struct gendisk *disk, fmode_t mode)
++{
++      struct virtio_blk *vblk = disk->private_data;
++
++      virtblk_put(vblk);
++}
++
+ /* We provide getgeo only to please some old bootloader/partitioning tools */
+ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
+ {
+       struct virtio_blk *vblk = bd->bd_disk->private_data;
++      int ret = 0;
++
++      mutex_lock(&vblk->vdev_mutex);
++
++      if (!vblk->vdev) {
++              ret = -ENXIO;
++              goto out;
++      }
+       /* see if the host passed in geometry config */
+       if (virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_GEOMETRY)) {
+@@ -407,12 +468,16 @@ static int virtblk_getgeo(struct block_device *bd, struct hd_geometry *geo)
+               geo->sectors = 1 << 5;
+               geo->cylinders = get_capacity(bd->bd_disk) >> 11;
+       }
+-      return 0;
++out:
++      mutex_unlock(&vblk->vdev_mutex);
++      return ret;
+ }
+ static const struct block_device_operations virtblk_fops = {
+       .ioctl  = virtblk_ioctl,
+       .owner  = THIS_MODULE,
++      .open = virtblk_open,
++      .release = virtblk_release,
+       .getgeo = virtblk_getgeo,
+ };
+@@ -767,6 +832,10 @@ static int virtblk_probe(struct virtio_device *vdev)
+               goto out_free_index;
+       }
++      /* This reference is dropped in virtblk_remove(). */
++      refcount_set(&vblk->refs, 1);
++      mutex_init(&vblk->vdev_mutex);
++
+       vblk->vdev = vdev;
+       vblk->sg_elems = sg_elems;
+@@ -932,8 +1001,6 @@ static int virtblk_probe(struct virtio_device *vdev)
+ static void virtblk_remove(struct virtio_device *vdev)
+ {
+       struct virtio_blk *vblk = vdev->priv;
+-      int index = vblk->index;
+-      int refc;
+       /* Make sure no work handler is accessing the device. */
+       flush_work(&vblk->config_work);
+@@ -943,18 +1010,21 @@ static void virtblk_remove(struct virtio_device *vdev)
+       blk_mq_free_tag_set(&vblk->tag_set);
++      mutex_lock(&vblk->vdev_mutex);
++
+       /* Stop all the virtqueues. */
+       vdev->config->reset(vdev);
+-      refc = kref_read(&disk_to_dev(vblk->disk)->kobj.kref);
++      /* Virtqueues are stopped, nothing can use vblk->vdev anymore. */
++      vblk->vdev = NULL;
++
+       put_disk(vblk->disk);
+       vdev->config->del_vqs(vdev);
+       kfree(vblk->vqs);
+-      kfree(vblk);
+-      /* Only free device id if we don't have any users */
+-      if (refc == 1)
+-              ida_simple_remove(&vd_index_ida, index);
++      mutex_unlock(&vblk->vdev_mutex);
++
++      virtblk_put(vblk);
+ }
+ #ifdef CONFIG_PM_SLEEP
+-- 
+2.20.1
+