From b1a247cf197609dfb139a1e795a7ec53ab6ba4d8 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 14 May 2020 15:14:55 -0400 Subject: [PATCH] Fixes for 5.4 Signed-off-by: Sasha Levin --- ...k-around-gcc-10-stringop-overflow-wa.patch | 73 +++++ ...-workaround-cgroup-rt-scheduling-iss.patch | 87 ++++++ ...-pca953x-fix-pca953x_gpio_set_config.patch | 41 +++ ...chronize-the-whole-guest-on-gic-d-r-.patch | 255 ++++++++++++++++ ...moxa-fix-a-potential-double-free_irq.patch | 36 +++ ...p_t1-add-lan87xx_phy_init-to-initial.patch | 238 +++++++++++++++ ...resource-leak-in-an-error-handling-p.patch | 50 +++ ...hed-fix-tcm_parent-in-tc-filter-dump.patch | 114 +++++++ queue-5.4/series | 13 + ...sible-deadlocks-on-shmlock_user_lock.patch | 80 +++++ queue-5.4/sun6i-dsi-fix-gcc-4.8.patch | 46 +++ ...nrpc-add-len-parameter-to-gss_unwrap.patch | 284 ++++++++++++++++++ ...rivacy-computation-of-auth-au_ralign.patch | 142 +++++++++ ...e-block_device_operations-callbacks-.patch | 217 +++++++++++++ 14 files changed, 1676 insertions(+) create mode 100644 queue-5.4/drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch create mode 100644 queue-5.4/ftrace-selftests-workaround-cgroup-rt-scheduling-iss.patch create mode 100644 queue-5.4/gpio-pca953x-fix-pca953x_gpio_set_config.patch create mode 100644 queue-5.4/kvm-arm-vgic-synchronize-the-whole-guest-on-gic-d-r-.patch create mode 100644 queue-5.4/net-moxa-fix-a-potential-double-free_irq.patch create mode 100644 queue-5.4/net-phy-microchip_t1-add-lan87xx_phy_init-to-initial.patch create mode 100644 queue-5.4/net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch create mode 100644 queue-5.4/net_sched-fix-tcm_parent-in-tc-filter-dump.patch create mode 100644 queue-5.4/shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch create mode 100644 queue-5.4/sun6i-dsi-fix-gcc-4.8.patch create mode 100644 queue-5.4/sunrpc-add-len-parameter-to-gss_unwrap.patch create mode 100644 queue-5.4/sunrpc-fix-gss-privacy-computation-of-auth-au_ralign.patch create mode 100644 queue-5.4/virtio-blk-handle-block_device_operations-callbacks-.patch 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 index 00000000000..968d9025549 --- /dev/null +++ b/queue-5.4/drop_monitor-work-around-gcc-10-stringop-overflow-wa.patch @@ -0,0 +1,73 @@ +From f94c08450a7fc61ce9d5b73138686f392972aca1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2020 23:30:49 +0200 +Subject: drop_monitor: work around gcc-10 stringop-overflow warning + +From: Arnd Bergmann + +[ 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 +Acked-by: Neil Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a4d162d0e83 --- /dev/null +++ b/queue-5.4/ftrace-selftests-workaround-cgroup-rt-scheduling-iss.patch @@ -0,0 +1,87 @@ +From f8712def8793d045fd32d713486d61857043a29a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 19 Feb 2020 09:33:29 +0000 +Subject: ftrace/selftests: workaround cgroup RT scheduling issues + +From: Alan Maguire + +[ 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 +Acked-by: Steven Rostedt (VMware) +Signed-off-by: Shuah Khan +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d4ab27f02a2 --- /dev/null +++ b/queue-5.4/gpio-pca953x-fix-pca953x_gpio_set_config.patch @@ -0,0 +1,41 @@ +From 92d9a211d4c47a3139f17f122ec1ea0d0db6de0a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 11 Apr 2020 20:33:52 -0500 +Subject: gpio: pca953x: Fix pca953x_gpio_set_config + +From: Adam Ford + +[ 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 +Signed-off-by: Bartosz Golaszewski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ff261afff08 --- /dev/null +++ b/queue-5.4/kvm-arm-vgic-synchronize-the-whole-guest-on-gic-d-r-.patch @@ -0,0 +1,255 @@ +From 87db8c2f44ed59049f0a2d3715ff963359c86d90 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Andre Przywara +Signed-off-by: Marc Zyngier +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..6929def3689 --- /dev/null +++ b/queue-5.4/net-moxa-fix-a-potential-double-free_irq.patch @@ -0,0 +1,36 @@ +From 66fd85f33b897af477045731093a37708c125973 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 26 Apr 2020 22:59:21 +0200 +Subject: net: moxa: Fix a potential double 'free_irq()' + +From: Christophe JAILLET + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..02708df4a48 --- /dev/null +++ b/queue-5.4/net-phy-microchip_t1-add-lan87xx_phy_init-to-initial.patch @@ -0,0 +1,238 @@ +From 4965bcba67ef93ea732ce55a7e4cae79cfafbb15 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Signed-off-by: Sasha Levin +--- + 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 + #include ++#include + #include + #include + ++/* 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 " + #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 index 00000000000..b60149a6487 --- /dev/null +++ b/queue-5.4/net-sonic-fix-a-resource-leak-in-an-error-handling-p.patch @@ -0,0 +1,50 @@ +From 15464178ccd55b7feccf0be584a6396dabdd4e93 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..adf5edce7b0 --- /dev/null +++ b/queue-5.4/net_sched-fix-tcm_parent-in-tc-filter-dump.patch @@ -0,0 +1,114 @@ +From 1ed2f21bc55d1499cefd000672af28be1d446c57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2020 20:53:49 -0700 +Subject: net_sched: fix tcm_parent in tc filter dump + +From: Cong Wang + +[ 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 +Cc: Jiri Pirko +Signed-off-by: Cong Wang +Acked-by: Jamal Hadi Salim +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-5.4/series b/queue-5.4/series index 131a7a00efb..785ea49661e 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -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 index 00000000000..340771f2279 --- /dev/null +++ b/queue-5.4/shmem-fix-possible-deadlocks-on-shmlock_user_lock.patch @@ -0,0 +1,80 @@ +From cdb813cf84b1a7d2a981b54940370e38ed2697c4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Apr 2020 18:14:14 -0700 +Subject: shmem: fix possible deadlocks on shmlock_user_lock + +From: Hugh Dickins + +[ 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 +Signed-off-by: Andrew Morton +Acked-by: Yang Shi +Cc: Yang Shi +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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..83eb3fe7418 --- /dev/null +++ b/queue-5.4/sun6i-dsi-fix-gcc-4.8.patch @@ -0,0 +1,46 @@ +From 601d96f9061bfff89990c1211dad4c3700577aca Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 28 Apr 2020 23:50:51 +0200 +Subject: sun6i: dsi: fix gcc-4.8 + +From: Arnd Bergmann + +[ 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 +Signed-off-by: Arnd Bergmann +Signed-off-by: Maxime Ripard +Link: https://patchwork.freedesktop.org/patch/msgid/20200428215105.3928459-1-arnd@arndb.de +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..d3904959025 --- /dev/null +++ b/queue-5.4/sunrpc-add-len-parameter-to-gss_unwrap.patch @@ -0,0 +1,284 @@ +From 020038556a356839799d2014ab0e0aebdc733c4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Apr 2020 21:06:23 -0400 +Subject: SUNRPC: Add "@len" parameter to gss_unwrap() + +From: Chuck Lever + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..93b26c743b2 --- /dev/null +++ b/queue-5.4/sunrpc-fix-gss-privacy-computation-of-auth-au_ralign.patch @@ -0,0 +1,142 @@ +From 6658b77c5e9b44cf28b567ccf796735427a7e488 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 18 Apr 2020 14:38:19 -0400 +Subject: SUNRPC: Fix GSS privacy computation of auth->au_ralign + +From: Chuck Lever + +[ 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 +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..47c763c7032 --- /dev/null +++ b/queue-5.4/virtio-blk-handle-block_device_operations-callbacks-.patch @@ -0,0 +1,217 @@ +From dfe41089f85b6450f36e364e8ff9ba361f230472 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Apr 2020 15:04:42 +0100 +Subject: virtio-blk: handle block_device_operations callbacks after hot unplug + +From: Stefan Hajnoczi + +[ 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: [] 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:[] [] 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: + [] virtblk_getgeo+0x47/0x110 [virtio_blk] + [] ? handle_mm_fault+0x39d/0x9b0 + [] blkdev_ioctl+0x1f5/0xa20 + [] block_ioctl+0x41/0x50 + [] do_vfs_ioctl+0x3a0/0x5a0 + [] 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 +Signed-off-by: Stefan Hajnoczi +Link: https://lore.kernel.org/r/20200430140442.171016-1-stefanha@redhat.com +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Stefano Garzarella +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.3