From: Greg Kroah-Hartman Date: Thu, 13 Sep 2018 12:53:46 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.4.156~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=544239eb438d3ac7eec98c5391b34fb649122189;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: asoc-wm8994-fix-missing-break-in-switch.patch btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch genirq-delay-incrementing-interrupt-count-if-it-s-disabled-pending.patch irqchip-gic-make-interrupt-id-1020-invalid.patch irqchip-gic-v3-add-missing-barrier-to-32bit-version-of-gic_read_iar.patch irqchip-gic-v3-its-recompute-the-number-of-pages-on-page-size-change.patch irqchip-gicv3-its-avoid-cache-flush-beyond-its_basern-memory-size.patch irqchip-gicv3-its-fix-memory-leak-in-its_free_tables.patch mei-me-allow-runtime-pm-for-platform-with-d0i3.patch ovl-override-creds-with-the-ones-from-the-superblock-mounter.patch ovl-proper-cleanup-of-workdir.patch ovl-rename-is_merge-to-is_lowest.patch s390-lib-use-expoline-for-all-bcr-instructions.patch sch_hhf-fix-null-pointer-dereference-on-init-failure.patch sch_htb-fix-crash-on-init-failure.patch sch_multiq-fix-double-free-on-init-failure.patch sch_netem-avoid-null-pointer-deref-on-init-failure.patch sch_tbf-fix-two-null-pointer-dereferences-on-init-failure.patch --- diff --git a/queue-4.4/asoc-wm8994-fix-missing-break-in-switch.patch b/queue-4.4/asoc-wm8994-fix-missing-break-in-switch.patch new file mode 100644 index 00000000000..2d149d2c084 --- /dev/null +++ b/queue-4.4/asoc-wm8994-fix-missing-break-in-switch.patch @@ -0,0 +1,35 @@ +From ad0eaee6195db1db1749dd46b9e6f4466793d178 Mon Sep 17 00:00:00 2001 +From: "Gustavo A. R. Silva" +Date: Mon, 6 Aug 2018 07:14:51 -0500 +Subject: ASoC: wm8994: Fix missing break in switch + +From: Gustavo A. R. Silva + +commit ad0eaee6195db1db1749dd46b9e6f4466793d178 upstream. + +Add missing break statement in order to prevent the code from falling +through to the default case. + +Addresses-Coverity-ID: 115050 ("Missing break in switch") +Reported-by: Valdis Kletnieks +Signed-off-by: Gustavo A. R. Silva +Acked-by: Charles Keepax +Signed-off-by: Mark Brown +Cc: stable@vger.kernel.org +[Gustavo: Backported to 3.16..4.18 - Remove code comment removal] +Signed-off-by: Gustavo A. R. Silva +Signed-off-by: Greg Kroah-Hartman +--- + sound/soc/codecs/wm8994.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/sound/soc/codecs/wm8994.c ++++ b/sound/soc/codecs/wm8994.c +@@ -2431,6 +2431,7 @@ static int wm8994_set_dai_sysclk(struct + snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_2, + WM8994_OPCLK_ENA, 0); + } ++ break; + + default: + return -EINVAL; diff --git a/queue-4.4/btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch b/queue-4.4/btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch new file mode 100644 index 00000000000..c3666484af4 --- /dev/null +++ b/queue-4.4/btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch @@ -0,0 +1,52 @@ +From d814a49198eafa6163698bdd93961302f3a877a4 Mon Sep 17 00:00:00 2001 +From: Ethan Lien +Date: Mon, 2 Jul 2018 15:44:58 +0800 +Subject: btrfs: use correct compare function of dirty_metadata_bytes + +From: Ethan Lien + +commit d814a49198eafa6163698bdd93961302f3a877a4 upstream. + +We use customized, nodesize batch value to update dirty_metadata_bytes. +We should also use batch version of compare function or we will easily +goto fast path and get false result from percpu_counter_compare(). + +Fixes: e2d845211eda ("Btrfs: use percpu counter for dirty metadata count") +CC: stable@vger.kernel.org # 4.4+ +Signed-off-by: Ethan Lien +Reviewed-by: Nikolay Borisov +Signed-off-by: David Sterba +nb: Rebased on 4.4.y ] +Signed-off-by: Nikolay Borisov +Signed-off-by: Greg Kroah-Hartman + +--- + fs/btrfs/disk-io.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/fs/btrfs/disk-io.c ++++ b/fs/btrfs/disk-io.c +@@ -1011,8 +1011,9 @@ static int btree_writepages(struct addre + + fs_info = BTRFS_I(mapping->host)->root->fs_info; + /* this is a bit racy, but that's ok */ +- ret = percpu_counter_compare(&fs_info->dirty_metadata_bytes, +- BTRFS_DIRTY_METADATA_THRESH); ++ ret = __percpu_counter_compare(&fs_info->dirty_metadata_bytes, ++ BTRFS_DIRTY_METADATA_THRESH, ++ fs_info->dirty_metadata_batch); + if (ret < 0) + return 0; + } +@@ -3987,8 +3988,9 @@ static void __btrfs_btree_balance_dirty( + if (flush_delayed) + btrfs_balance_delayed_items(root); + +- ret = percpu_counter_compare(&root->fs_info->dirty_metadata_bytes, +- BTRFS_DIRTY_METADATA_THRESH); ++ ret = __percpu_counter_compare(&root->fs_info->dirty_metadata_bytes, ++ BTRFS_DIRTY_METADATA_THRESH, ++ root->fs_info->dirty_metadata_batch); + if (ret > 0) { + balance_dirty_pages_ratelimited( + root->fs_info->btree_inode->i_mapping); diff --git a/queue-4.4/genirq-delay-incrementing-interrupt-count-if-it-s-disabled-pending.patch b/queue-4.4/genirq-delay-incrementing-interrupt-count-if-it-s-disabled-pending.patch new file mode 100644 index 00000000000..23f5c3abdfa --- /dev/null +++ b/queue-4.4/genirq-delay-incrementing-interrupt-count-if-it-s-disabled-pending.patch @@ -0,0 +1,99 @@ +From a946e8c717f9355d1abd5408ed0adc0002d1aed1 Mon Sep 17 00:00:00 2001 +From: Sudeep Holla +Date: Wed, 4 Nov 2015 18:32:37 +0000 +Subject: genirq: Delay incrementing interrupt count if it's disabled/pending + +From: Sudeep Holla + +commit a946e8c717f9355d1abd5408ed0adc0002d1aed1 upstream. + +In case of a wakeup interrupt, irq_pm_check_wakeup disables the interrupt +and marks it pending and suspended, disables it and notifies the pm core +about the wake event. The interrupt gets handled later once the system +is resumed. + +However the irq stats is updated twice: once when it's disabled waiting +for the system to resume and later when it's handled, resulting in wrong +counting of the wakeup interrupt when waking up the system. + +This patch updates the interrupt count so that it's updated only when +the interrupt gets handled. It's already handled correctly in +handle_edge_irq and handle_edge_eoi_irq. + +Reported-by: Manoil Claudiu +Signed-off-by: Sudeep Holla +Cc: Marc Zyngier +Link: http://lkml.kernel.org/r/1446661957-1019-1-git-send-email-sudeep.holla@arm.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Hanjun Guo +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/irq/chip.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +--- a/kernel/irq/chip.c ++++ b/kernel/irq/chip.c +@@ -338,7 +338,6 @@ void handle_nested_irq(unsigned int irq) + raw_spin_lock_irq(&desc->lock); + + desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); +- kstat_incr_irqs_this_cpu(desc); + + action = desc->action; + if (unlikely(!action || irqd_irq_disabled(&desc->irq_data))) { +@@ -346,6 +345,7 @@ void handle_nested_irq(unsigned int irq) + goto out_unlock; + } + ++ kstat_incr_irqs_this_cpu(desc); + irqd_set(&desc->irq_data, IRQD_IRQ_INPROGRESS); + raw_spin_unlock_irq(&desc->lock); + +@@ -412,13 +412,13 @@ void handle_simple_irq(struct irq_desc * + goto out_unlock; + + desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); +- kstat_incr_irqs_this_cpu(desc); + + if (unlikely(!desc->action || irqd_irq_disabled(&desc->irq_data))) { + desc->istate |= IRQS_PENDING; + goto out_unlock; + } + ++ kstat_incr_irqs_this_cpu(desc); + handle_irq_event(desc); + + out_unlock: +@@ -462,7 +462,6 @@ void handle_level_irq(struct irq_desc *d + goto out_unlock; + + desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); +- kstat_incr_irqs_this_cpu(desc); + + /* + * If its disabled or no action available +@@ -473,6 +472,7 @@ void handle_level_irq(struct irq_desc *d + goto out_unlock; + } + ++ kstat_incr_irqs_this_cpu(desc); + handle_irq_event(desc); + + cond_unmask_irq(desc); +@@ -532,7 +532,6 @@ void handle_fasteoi_irq(struct irq_desc + goto out; + + desc->istate &= ~(IRQS_REPLAY | IRQS_WAITING); +- kstat_incr_irqs_this_cpu(desc); + + /* + * If its disabled or no action available +@@ -544,6 +543,7 @@ void handle_fasteoi_irq(struct irq_desc + goto out; + } + ++ kstat_incr_irqs_this_cpu(desc); + if (desc->istate & IRQS_ONESHOT) + mask_irq(desc); + diff --git a/queue-4.4/irqchip-gic-make-interrupt-id-1020-invalid.patch b/queue-4.4/irqchip-gic-make-interrupt-id-1020-invalid.patch new file mode 100644 index 00000000000..f169f1a5445 --- /dev/null +++ b/queue-4.4/irqchip-gic-make-interrupt-id-1020-invalid.patch @@ -0,0 +1,38 @@ +From 327ebe1f3a9b7e20e298b39d0cff627169a28012 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Wed, 16 Dec 2015 14:11:22 +0000 +Subject: irqchip/gic: Make interrupt ID 1020 invalid + +From: Marc Zyngier + +commit 327ebe1f3a9b7e20e298b39d0cff627169a28012 upstream. + +The GIC has no such thing as interrupt 1020: the last valid ID is +1019, and the range 1020-1023 is reserved - 1023 indicating that +no interrupt is pending. So let's make sure we don't try to handle +this ID. + +This bug has been in since the initial GIC code was introduced in +8ad68bbf7a06 ("[ARM] Add support for ARM RealView board"). + +Reported-by: Eric Auger +Cc: Catalin Marinas +Signed-off-by: Marc Zyngier +Signed-off-by: Hanjun Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/irqchip/irq-gic.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/irqchip/irq-gic.c ++++ b/drivers/irqchip/irq-gic.c +@@ -336,7 +336,7 @@ static void __exception_irq_entry gic_ha + irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK); + irqnr = irqstat & GICC_IAR_INT_ID_MASK; + +- if (likely(irqnr > 15 && irqnr < 1021)) { ++ if (likely(irqnr > 15 && irqnr < 1020)) { + if (static_key_true(&supports_deactivate)) + writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI); + handle_domain_irq(gic->domain, irqnr, regs); diff --git a/queue-4.4/irqchip-gic-v3-add-missing-barrier-to-32bit-version-of-gic_read_iar.patch b/queue-4.4/irqchip-gic-v3-add-missing-barrier-to-32bit-version-of-gic_read_iar.patch new file mode 100644 index 00000000000..6243f24e086 --- /dev/null +++ b/queue-4.4/irqchip-gic-v3-add-missing-barrier-to-32bit-version-of-gic_read_iar.patch @@ -0,0 +1,33 @@ +From 8f318526a292c5e7cebb82f3f766b83c22343293 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Thu, 18 Feb 2016 19:15:45 +0000 +Subject: irqchip/gic-v3: Add missing barrier to 32bit version of gic_read_iar() + +From: Marc Zyngier + +commit 8f318526a292c5e7cebb82f3f766b83c22343293 upstream. + +Commit 1a1ebd5 ("irqchip/gic-v3: Make sure read from ICC_IAR1_EL1 is +visible on redestributor") fixed the missing barrier on arm64, but +forgot to update the 32bit counterpart, which has the same requirements. +Let's fix it. + +Fixes: 1a1ebd5 ("irqchip/gic-v3: Make sure read from ICC_IAR1_EL1 is visible on redestributor") +Signed-off-by: Marc Zyngier +Signed-off-by: Hanjun Guo +Signed-off-by: Greg Kroah-Hartman + +--- + arch/arm/include/asm/arch_gicv3.h | 1 + + 1 file changed, 1 insertion(+) + +--- a/arch/arm/include/asm/arch_gicv3.h ++++ b/arch/arm/include/asm/arch_gicv3.h +@@ -117,6 +117,7 @@ static inline u32 gic_read_iar(void) + u32 irqstat; + + asm volatile("mrc " __stringify(ICC_IAR1) : "=r" (irqstat)); ++ dsb(sy); + return irqstat; + } + diff --git a/queue-4.4/irqchip-gic-v3-its-recompute-the-number-of-pages-on-page-size-change.patch b/queue-4.4/irqchip-gic-v3-its-recompute-the-number-of-pages-on-page-size-change.patch new file mode 100644 index 00000000000..6cfa55c9698 --- /dev/null +++ b/queue-4.4/irqchip-gic-v3-its-recompute-the-number-of-pages-on-page-size-change.patch @@ -0,0 +1,62 @@ +From 18aa60ce2751c95d3412ed06a58b8b6cfb6f88f2 Mon Sep 17 00:00:00 2001 +From: Marc Zyngier +Date: Tue, 26 Jan 2016 14:24:15 +0000 +Subject: irqchip/gic-v3-its: Recompute the number of pages on page size change + +From: Marc Zyngier + +commit 18aa60ce2751c95d3412ed06a58b8b6cfb6f88f2 upstream. + +When the programming of a GITS_BASERn register fails because of +an unsupported ITS page size, we retry it with a smaller page size. +Unfortunately, we don't recompute the number of allocated ITS pages, +indicating the wrong value computed in the original allocation. + +A convenient fix is to free the pages we allocated, update the +page size, and restart the allocation. This will ensure that +we always allocate the right amount in the case of a device +table, specially if we have to reduce the allocation order +to stay within the boundaries of the ITS maximum allocation. + +Reported-and-tested-by: Ma Jun +Signed-off-by: Marc Zyngier +Cc: linux-arm-kernel@lists.infradead.org +Cc: Jason Cooper +Link: http://lkml.kernel.org/r/1453818255-1289-1-git-send-email-marc.zyngier@arm.com +Signed-off-by: Thomas Gleixner +Signed-off-by: Hanjun Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/irqchip/irq-gic-v3-its.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -884,6 +884,7 @@ static int its_alloc_tables(const char * + } + + alloc_size = (1 << order) * PAGE_SIZE; ++retry_alloc_baser: + alloc_pages = (alloc_size / psz); + if (alloc_pages > GITS_BASER_PAGES_MAX) { + alloc_pages = GITS_BASER_PAGES_MAX; +@@ -947,13 +948,16 @@ retry_baser: + * size and retry. If we reach 4K, then + * something is horribly wrong... + */ ++ free_pages((unsigned long)base, order); ++ its->tables[i] = NULL; ++ + switch (psz) { + case SZ_16K: + psz = SZ_4K; +- goto retry_baser; ++ goto retry_alloc_baser; + case SZ_64K: + psz = SZ_16K; +- goto retry_baser; ++ goto retry_alloc_baser; + } + } + diff --git a/queue-4.4/irqchip-gicv3-its-avoid-cache-flush-beyond-its_basern-memory-size.patch b/queue-4.4/irqchip-gicv3-its-avoid-cache-flush-beyond-its_basern-memory-size.patch new file mode 100644 index 00000000000..e8978321460 --- /dev/null +++ b/queue-4.4/irqchip-gicv3-its-avoid-cache-flush-beyond-its_basern-memory-size.patch @@ -0,0 +1,79 @@ +From 2eca0d6ceea1f108b2d3ac81fb34698c4fd41006 Mon Sep 17 00:00:00 2001 +From: Shanker Donthineni +Date: Tue, 16 Feb 2016 18:00:36 -0600 +Subject: irqchip/gicv3-its: Avoid cache flush beyond ITS_BASERn memory size + +From: Shanker Donthineni + +commit 2eca0d6ceea1f108b2d3ac81fb34698c4fd41006 upstream. + +Function its_alloc_tables() maintains two local variables, "order" and +and "alloc_size", to hold memory size that has been allocated to +ITS_BASEn. We don't always refresh the variable alloc_size whenever +value of the variable order changes, causing the following two +problems. + + - Cache flush operation with size more than required. + - Information reported by pr_info is not correct. + +Use a helper macro that converts page order to size in bytes instead of +variable "alloc_size" to fix both the problems. + +Signed-off-by: Shanker Donthineni +Signed-off-by: Marc Zyngier +Signed-off-by: Hanjun Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/irqchip/irq-gic-v3-its.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -80,6 +80,9 @@ struct its_node { + + #define ITS_ITT_ALIGN SZ_256 + ++/* Convert page order to size in bytes */ ++#define PAGE_ORDER_TO_SIZE(o) (PAGE_SIZE << (o)) ++ + struct event_lpi_map { + unsigned long *lpi_map; + u16 *col_map; +@@ -855,7 +858,6 @@ static int its_alloc_tables(const char * + u64 type = GITS_BASER_TYPE(val); + u64 entry_size = GITS_BASER_ENTRY_SIZE(val); + int order = get_order(psz); +- int alloc_size; + int alloc_pages; + u64 tmp; + void *base; +@@ -887,9 +889,8 @@ static int its_alloc_tables(const char * + } + } + +- alloc_size = (1 << order) * PAGE_SIZE; + retry_alloc_baser: +- alloc_pages = (alloc_size / psz); ++ alloc_pages = (PAGE_ORDER_TO_SIZE(order) / psz); + if (alloc_pages > GITS_BASER_PAGES_MAX) { + alloc_pages = GITS_BASER_PAGES_MAX; + order = get_order(GITS_BASER_PAGES_MAX * psz); +@@ -942,7 +943,7 @@ retry_baser: + shr = tmp & GITS_BASER_SHAREABILITY_MASK; + if (!shr) { + cache = GITS_BASER_nC; +- __flush_dcache_area(base, alloc_size); ++ __flush_dcache_area(base, PAGE_ORDER_TO_SIZE(order)); + } + goto retry_baser; + } +@@ -975,7 +976,7 @@ retry_baser: + } + + pr_info("ITS: allocated %d %s @%lx (psz %dK, shr %d)\n", +- (int)(alloc_size / entry_size), ++ (int)(PAGE_ORDER_TO_SIZE(order) / entry_size), + its_base_type_string[type], + (unsigned long)virt_to_phys(base), + psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT); diff --git a/queue-4.4/irqchip-gicv3-its-fix-memory-leak-in-its_free_tables.patch b/queue-4.4/irqchip-gicv3-its-fix-memory-leak-in-its_free_tables.patch new file mode 100644 index 00000000000..8f1ef03c2a6 --- /dev/null +++ b/queue-4.4/irqchip-gicv3-its-fix-memory-leak-in-its_free_tables.patch @@ -0,0 +1,79 @@ +From 1a485f4d2e28efd77075b2952926683d6c245633 Mon Sep 17 00:00:00 2001 +From: Shanker Donthineni +Date: Mon, 1 Feb 2016 20:19:44 -0600 +Subject: irqchip/gicv3-its: Fix memory leak in its_free_tables() + +From: Shanker Donthineni + +commit 1a485f4d2e28efd77075b2952926683d6c245633 upstream. + +The current ITS driver has a memory leak in its_free_tables(). It +happens on tear down path of the driver when its_probe() call fails. +its_free_tables() should free the exact number of pages that have +been allocated, not just a single page as current code does. + +This patch records the memory size for each ITS_BASERn at the time of +page allocation and uses the same size information when freeing pages +to fix the issue. + +Signed-off-by: Shanker Donthineni +Acked-by: Marc Zyngier +Cc: Jason Cooper +Cc: Vikram Sethi +Cc: linux-arm-kernel@lists.infradead.org +Link: http://lkml.kernel.org/r/1454379584-21772-1-git-send-email-shankerd@codeaurora.org +Signed-off-by: Thomas Gleixner +Signed-off-by: Hanjun Guo +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/irqchip/irq-gic-v3-its.c | 17 +++++++++++------ + 1 file changed, 11 insertions(+), 6 deletions(-) + +--- a/drivers/irqchip/irq-gic-v3-its.c ++++ b/drivers/irqchip/irq-gic-v3-its.c +@@ -67,7 +67,10 @@ struct its_node { + unsigned long phys_base; + struct its_cmd_block *cmd_base; + struct its_cmd_block *cmd_write; +- void *tables[GITS_BASER_NR_REGS]; ++ struct { ++ void *base; ++ u32 order; ++ } tables[GITS_BASER_NR_REGS]; + struct its_collection *collections; + struct list_head its_device_list; + u64 flags; +@@ -816,9 +819,10 @@ static void its_free_tables(struct its_n + int i; + + for (i = 0; i < GITS_BASER_NR_REGS; i++) { +- if (its->tables[i]) { +- free_page((unsigned long)its->tables[i]); +- its->tables[i] = NULL; ++ if (its->tables[i].base) { ++ free_pages((unsigned long)its->tables[i].base, ++ its->tables[i].order); ++ its->tables[i].base = NULL; + } + } + } +@@ -899,7 +903,8 @@ retry_alloc_baser: + goto out_free; + } + +- its->tables[i] = base; ++ its->tables[i].base = base; ++ its->tables[i].order = order; + + retry_baser: + val = (virt_to_phys(base) | +@@ -949,7 +954,7 @@ retry_baser: + * something is horribly wrong... + */ + free_pages((unsigned long)base, order); +- its->tables[i] = NULL; ++ its->tables[i].base = NULL; + + switch (psz) { + case SZ_16K: diff --git a/queue-4.4/mei-me-allow-runtime-pm-for-platform-with-d0i3.patch b/queue-4.4/mei-me-allow-runtime-pm-for-platform-with-d0i3.patch new file mode 100644 index 00000000000..b5343441255 --- /dev/null +++ b/queue-4.4/mei-me-allow-runtime-pm-for-platform-with-d0i3.patch @@ -0,0 +1,46 @@ +From cc365dcf0e56271bedf3de95f88922abe248e951 Mon Sep 17 00:00:00 2001 +From: Tomas Winkler +Date: Tue, 2 Jan 2018 12:01:41 +0200 +Subject: mei: me: allow runtime pm for platform with D0i3 + +From: Tomas Winkler + +commit cc365dcf0e56271bedf3de95f88922abe248e951 upstream. + +>From the pci power documentation: +"The driver itself should not call pm_runtime_allow(), though. Instead, +it should let user space or some platform-specific code do that (user space +can do it via sysfs as stated above)..." + +However, the S0ix residency cannot be reached without MEI device getting +into low power state. Hence, for mei devices that support D0i3, it's better +to make runtime power management mandatory and not rely on the system +integration such as udev rules. +This policy cannot be applied globally as some older platforms +were found to have broken power management. + +Cc: v4.13+ +Cc: Rafael J. Wysocki +Signed-off-by: Tomas Winkler +Reviewed-by: Alexander Usyskin +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/misc/mei/pci-me.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/drivers/misc/mei/pci-me.c ++++ b/drivers/misc/mei/pci-me.c +@@ -230,8 +230,11 @@ static int mei_me_probe(struct pci_dev * + if (!pci_dev_run_wake(pdev)) + mei_me_set_pm_domain(dev); + +- if (mei_pg_is_enabled(dev)) ++ if (mei_pg_is_enabled(dev)) { + pm_runtime_put_noidle(&pdev->dev); ++ if (hw->d0i3_supported) ++ pm_runtime_allow(&pdev->dev); ++ } + + dev_dbg(&pdev->dev, "initialization successful.\n"); + diff --git a/queue-4.4/ovl-override-creds-with-the-ones-from-the-superblock-mounter.patch b/queue-4.4/ovl-override-creds-with-the-ones-from-the-superblock-mounter.patch new file mode 100644 index 00000000000..b8e25b5a1ed --- /dev/null +++ b/queue-4.4/ovl-override-creds-with-the-ones-from-the-superblock-mounter.patch @@ -0,0 +1,343 @@ +From 3fe6e52f062643676eb4518d68cee3bc1272091b Mon Sep 17 00:00:00 2001 +From: Antonio Murdaca +Date: Thu, 7 Apr 2016 15:48:25 +0200 +Subject: ovl: override creds with the ones from the superblock mounter + +From: Antonio Murdaca + +commit 3fe6e52f062643676eb4518d68cee3bc1272091b upstream. + +In user namespace the whiteout creation fails with -EPERM because the +current process isn't capable(CAP_SYS_ADMIN) when setting xattr. + +A simple reproducer: + +$ mkdir upper lower work merged lower/dir +$ sudo mount -t overlay overlay -olowerdir=lower,upperdir=upper,workdir=work merged +$ unshare -m -p -f -U -r bash + +Now as root in the user namespace: + +\# touch merged/dir/{1,2,3} # this will force a copy up of lower/dir +\# rm -fR merged/* + +This ends up failing with -EPERM after the files in dir has been +correctly deleted: + +unlinkat(4, "2", 0) = 0 +unlinkat(4, "1", 0) = 0 +unlinkat(4, "3", 0) = 0 +close(4) = 0 +unlinkat(AT_FDCWD, "merged/dir", AT_REMOVEDIR) = -1 EPERM (Operation not +permitted) + +Interestingly, if you don't place files in merged/dir you can remove it, +meaning if upper/dir does not exist, creating the char device file works +properly in that same location. + +This patch uses ovl_sb_creator_cred() to get the cred struct from the +superblock mounter and override the old cred with these new ones so that +the whiteout creation is possible because overlay is wrong in assuming that +the creds it will get with prepare_creds will be in the initial user +namespace. The old cap_raise game is removed in favor of just overriding +the old cred struct. + +This patch also drops from ovl_copy_up_one() the following two lines: + +override_cred->fsuid = stat->uid; +override_cred->fsgid = stat->gid; + +This is because the correct uid and gid are taken directly with the stat +struct and correctly set with ovl_set_attr(). + +Signed-off-by: Antonio Murdaca +Signed-off-by: Miklos Szeredi +Signed-off-by: SZ Lin (林上智) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/copy_up.c | 26 ------------------ + fs/overlayfs/dir.c | 67 +++-------------------------------------------- + fs/overlayfs/overlayfs.h | 1 + fs/overlayfs/readdir.c | 14 ++------- + fs/overlayfs/super.c | 18 +++++++++++- + 5 files changed, 27 insertions(+), 99 deletions(-) + +--- a/fs/overlayfs/copy_up.c ++++ b/fs/overlayfs/copy_up.c +@@ -317,7 +317,6 @@ int ovl_copy_up_one(struct dentry *paren + struct dentry *upperdir; + struct dentry *upperdentry; + const struct cred *old_cred; +- struct cred *override_cred; + char *link = NULL; + + if (WARN_ON(!workdir)) +@@ -336,28 +335,7 @@ int ovl_copy_up_one(struct dentry *paren + return PTR_ERR(link); + } + +- err = -ENOMEM; +- override_cred = prepare_creds(); +- if (!override_cred) +- goto out_free_link; +- +- override_cred->fsuid = stat->uid; +- override_cred->fsgid = stat->gid; +- /* +- * CAP_SYS_ADMIN for copying up extended attributes +- * CAP_DAC_OVERRIDE for create +- * CAP_FOWNER for chmod, timestamp update +- * CAP_FSETID for chmod +- * CAP_CHOWN for chown +- * CAP_MKNOD for mknod +- */ +- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); +- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); +- cap_raise(override_cred->cap_effective, CAP_FOWNER); +- cap_raise(override_cred->cap_effective, CAP_FSETID); +- cap_raise(override_cred->cap_effective, CAP_CHOWN); +- cap_raise(override_cred->cap_effective, CAP_MKNOD); +- old_cred = override_creds(override_cred); ++ old_cred = ovl_override_creds(dentry->d_sb); + + err = -EIO; + if (lock_rename(workdir, upperdir) != NULL) { +@@ -380,9 +358,7 @@ int ovl_copy_up_one(struct dentry *paren + out_unlock: + unlock_rename(workdir, upperdir); + revert_creds(old_cred); +- put_cred(override_cred); + +-out_free_link: + if (link) + free_page((unsigned long) link); + +--- a/fs/overlayfs/dir.c ++++ b/fs/overlayfs/dir.c +@@ -408,28 +408,13 @@ static int ovl_create_or_link(struct den + err = ovl_create_upper(dentry, inode, &stat, link, hardlink); + } else { + const struct cred *old_cred; +- struct cred *override_cred; + +- err = -ENOMEM; +- override_cred = prepare_creds(); +- if (!override_cred) +- goto out_iput; +- +- /* +- * CAP_SYS_ADMIN for setting opaque xattr +- * CAP_DAC_OVERRIDE for create in workdir, rename +- * CAP_FOWNER for removing whiteout from sticky dir +- */ +- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); +- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); +- cap_raise(override_cred->cap_effective, CAP_FOWNER); +- old_cred = override_creds(override_cred); ++ old_cred = ovl_override_creds(dentry->d_sb); + + err = ovl_create_over_whiteout(dentry, inode, &stat, link, + hardlink); + + revert_creds(old_cred); +- put_cred(override_cred); + } + + if (!err) +@@ -659,32 +644,11 @@ static int ovl_do_remove(struct dentry * + if (OVL_TYPE_PURE_UPPER(type)) { + err = ovl_remove_upper(dentry, is_dir); + } else { +- const struct cred *old_cred; +- struct cred *override_cred; +- +- err = -ENOMEM; +- override_cred = prepare_creds(); +- if (!override_cred) +- goto out_drop_write; +- +- /* +- * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir +- * CAP_DAC_OVERRIDE for create in workdir, rename +- * CAP_FOWNER for removing whiteout from sticky dir +- * CAP_FSETID for chmod of opaque dir +- * CAP_CHOWN for chown of opaque dir +- */ +- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); +- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); +- cap_raise(override_cred->cap_effective, CAP_FOWNER); +- cap_raise(override_cred->cap_effective, CAP_FSETID); +- cap_raise(override_cred->cap_effective, CAP_CHOWN); +- old_cred = override_creds(override_cred); ++ const struct cred *old_cred = ovl_override_creds(dentry->d_sb); + + err = ovl_remove_and_whiteout(dentry, is_dir); + + revert_creds(old_cred); +- put_cred(override_cred); + } + out_drop_write: + ovl_drop_write(dentry); +@@ -723,7 +687,6 @@ static int ovl_rename2(struct inode *old + bool new_is_dir = false; + struct dentry *opaquedir = NULL; + const struct cred *old_cred = NULL; +- struct cred *override_cred = NULL; + + err = -EINVAL; + if (flags & ~(RENAME_EXCHANGE | RENAME_NOREPLACE)) +@@ -792,26 +755,8 @@ static int ovl_rename2(struct inode *old + old_opaque = !OVL_TYPE_PURE_UPPER(old_type); + new_opaque = !OVL_TYPE_PURE_UPPER(new_type); + +- if (old_opaque || new_opaque) { +- err = -ENOMEM; +- override_cred = prepare_creds(); +- if (!override_cred) +- goto out_drop_write; +- +- /* +- * CAP_SYS_ADMIN for setting xattr on whiteout, opaque dir +- * CAP_DAC_OVERRIDE for create in workdir +- * CAP_FOWNER for removing whiteout from sticky dir +- * CAP_FSETID for chmod of opaque dir +- * CAP_CHOWN for chown of opaque dir +- */ +- cap_raise(override_cred->cap_effective, CAP_SYS_ADMIN); +- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); +- cap_raise(override_cred->cap_effective, CAP_FOWNER); +- cap_raise(override_cred->cap_effective, CAP_FSETID); +- cap_raise(override_cred->cap_effective, CAP_CHOWN); +- old_cred = override_creds(override_cred); +- } ++ if (old_opaque || new_opaque) ++ old_cred = ovl_override_creds(old->d_sb); + + if (overwrite && OVL_TYPE_MERGE_OR_LOWER(new_type) && new_is_dir) { + opaquedir = ovl_check_empty_and_clear(new); +@@ -942,10 +887,8 @@ out_dput_old: + out_unlock: + unlock_rename(new_upperdir, old_upperdir); + out_revert_creds: +- if (old_opaque || new_opaque) { ++ if (old_opaque || new_opaque) + revert_creds(old_cred); +- put_cred(override_cred); +- } + out_drop_write: + ovl_drop_write(old); + out: +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -150,6 +150,7 @@ void ovl_drop_write(struct dentry *dentr + bool ovl_dentry_is_opaque(struct dentry *dentry); + void ovl_dentry_set_opaque(struct dentry *dentry, bool opaque); + bool ovl_is_whiteout(struct dentry *dentry); ++const struct cred *ovl_override_creds(struct super_block *sb); + void ovl_dentry_update(struct dentry *dentry, struct dentry *upperdentry); + struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, + unsigned int flags); +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -36,6 +36,7 @@ struct ovl_dir_cache { + + struct ovl_readdir_data { + struct dir_context ctx; ++ struct dentry *dentry; + bool is_lowest; + struct rb_root root; + struct list_head *list; +@@ -206,17 +207,8 @@ static int ovl_check_whiteouts(struct de + struct ovl_cache_entry *p; + struct dentry *dentry; + const struct cred *old_cred; +- struct cred *override_cred; +- +- override_cred = prepare_creds(); +- if (!override_cred) +- return -ENOMEM; + +- /* +- * CAP_DAC_OVERRIDE for lookup +- */ +- cap_raise(override_cred->cap_effective, CAP_DAC_OVERRIDE); +- old_cred = override_creds(override_cred); ++ old_cred = ovl_override_creds(rdd->dentry->d_sb); + + err = mutex_lock_killable(&dir->d_inode->i_mutex); + if (!err) { +@@ -232,7 +224,6 @@ static int ovl_check_whiteouts(struct de + mutex_unlock(&dir->d_inode->i_mutex); + } + revert_creds(old_cred); +- put_cred(override_cred); + + return err; + } +@@ -288,6 +279,7 @@ static int ovl_dir_read_merged(struct de + struct path realpath; + struct ovl_readdir_data rdd = { + .ctx.actor = ovl_fill_merge, ++ .dentry = dentry, + .list = list, + .root = RB_ROOT, + .is_lowest = false, +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -42,6 +42,8 @@ struct ovl_fs { + long lower_namelen; + /* pathnames of lower and upper dirs, for show_options */ + struct ovl_config config; ++ /* creds of process who forced instantiation of super block */ ++ const struct cred *creator_cred; + }; + + struct ovl_dir_cache; +@@ -246,6 +248,13 @@ bool ovl_is_whiteout(struct dentry *dent + return inode && IS_WHITEOUT(inode); + } + ++const struct cred *ovl_override_creds(struct super_block *sb) ++{ ++ struct ovl_fs *ofs = sb->s_fs_info; ++ ++ return override_creds(ofs->creator_cred); ++} ++ + static bool ovl_is_opaquedir(struct dentry *dentry) + { + int res; +@@ -587,6 +596,7 @@ static void ovl_put_super(struct super_b + kfree(ufs->config.lowerdir); + kfree(ufs->config.upperdir); + kfree(ufs->config.workdir); ++ put_cred(ufs->creator_cred); + kfree(ufs); + } + +@@ -1107,10 +1117,14 @@ static int ovl_fill_super(struct super_b + else + sb->s_d_op = &ovl_dentry_operations; + ++ ufs->creator_cred = prepare_creds(); ++ if (!ufs->creator_cred) ++ goto out_put_lower_mnt; ++ + err = -ENOMEM; + oe = ovl_alloc_entry(numlower); + if (!oe) +- goto out_put_lower_mnt; ++ goto out_put_cred; + + root_dentry = d_make_root(ovl_new_inode(sb, S_IFDIR, oe)); + if (!root_dentry) +@@ -1143,6 +1157,8 @@ static int ovl_fill_super(struct super_b + + out_free_oe: + kfree(oe); ++out_put_cred: ++ put_cred(ufs->creator_cred); + out_put_lower_mnt: + for (i = 0; i < ufs->numlower; i++) + mntput(ufs->lower_mnt[i]); diff --git a/queue-4.4/ovl-proper-cleanup-of-workdir.patch b/queue-4.4/ovl-proper-cleanup-of-workdir.patch new file mode 100644 index 00000000000..fedbbca3bb7 --- /dev/null +++ b/queue-4.4/ovl-proper-cleanup-of-workdir.patch @@ -0,0 +1,138 @@ +From eea2fb4851e9dcbab6b991aaf47e2e024f1f55a0 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Thu, 1 Sep 2016 11:11:59 +0200 +Subject: ovl: proper cleanup of workdir + +From: Miklos Szeredi + +commit eea2fb4851e9dcbab6b991aaf47e2e024f1f55a0 upstream. + +When mounting overlayfs it needs a clean "work" directory under the +supplied workdir. + +Previously the mount code removed this directory if it already existed and +created a new one. If the removal failed (e.g. directory was not empty) +then it fell back to a read-only mount not using the workdir. + +While this has never been reported, it is possible to get a non-empty +"work" dir from a previous mount of overlayfs in case of crash in the +middle of an operation using the work directory. + +In this case the left over state should be discarded and the overlay +filesystem will be consistent, guaranteed by the atomicity of operations on +moving to/from the workdir to the upper layer. + +This patch implements cleaning out any files left in workdir. It is +implemented using real recursion for simplicity, but the depth is limited +to 2, because the worst case is that of a directory containing whiteouts +under "work". + +Signed-off-by: Miklos Szeredi +Cc: +Signed-off-by: SZ Lin (林上智) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/overlayfs.h | 2 + + fs/overlayfs/readdir.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++- + fs/overlayfs/super.c | 2 - + 3 files changed, 65 insertions(+), 2 deletions(-) + +--- a/fs/overlayfs/overlayfs.h ++++ b/fs/overlayfs/overlayfs.h +@@ -165,6 +165,8 @@ int ovl_check_empty_dir(struct dentry *d + void ovl_cleanup_whiteouts(struct dentry *upper, struct list_head *list); + void ovl_cache_free(struct list_head *list); + int ovl_check_d_type_supported(struct path *realpath); ++void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, ++ struct dentry *dentry, int level); + + /* inode.c */ + int ovl_setattr(struct dentry *dentry, struct iattr *attr); +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -248,7 +248,7 @@ static inline int ovl_dir_read(struct pa + err = rdd->err; + } while (!err && rdd->count); + +- if (!err && rdd->first_maybe_whiteout) ++ if (!err && rdd->first_maybe_whiteout && rdd->dentry) + err = ovl_check_whiteouts(realpath->dentry, rdd); + + fput(realfile); +@@ -610,3 +610,64 @@ int ovl_check_d_type_supported(struct pa + + return rdd.d_type_supported; + } ++ ++static void ovl_workdir_cleanup_recurse(struct path *path, int level) ++{ ++ int err; ++ struct inode *dir = path->dentry->d_inode; ++ LIST_HEAD(list); ++ struct ovl_cache_entry *p; ++ struct ovl_readdir_data rdd = { ++ .ctx.actor = ovl_fill_merge, ++ .dentry = NULL, ++ .list = &list, ++ .root = RB_ROOT, ++ .is_lowest = false, ++ }; ++ ++ err = ovl_dir_read(path, &rdd); ++ if (err) ++ goto out; ++ ++ inode_lock_nested(dir, I_MUTEX_PARENT); ++ list_for_each_entry(p, &list, l_node) { ++ struct dentry *dentry; ++ ++ if (p->name[0] == '.') { ++ if (p->len == 1) ++ continue; ++ if (p->len == 2 && p->name[1] == '.') ++ continue; ++ } ++ dentry = lookup_one_len(p->name, path->dentry, p->len); ++ if (IS_ERR(dentry)) ++ continue; ++ if (dentry->d_inode) ++ ovl_workdir_cleanup(dir, path->mnt, dentry, level); ++ dput(dentry); ++ } ++ inode_unlock(dir); ++out: ++ ovl_cache_free(&list); ++} ++ ++void ovl_workdir_cleanup(struct inode *dir, struct vfsmount *mnt, ++ struct dentry *dentry, int level) ++{ ++ int err; ++ ++ if (!d_is_dir(dentry) || level > 1) { ++ ovl_cleanup(dir, dentry); ++ return; ++ } ++ ++ err = ovl_do_rmdir(dir, dentry); ++ if (err) { ++ struct path path = { .mnt = mnt, .dentry = dentry }; ++ ++ inode_unlock(dir); ++ ovl_workdir_cleanup_recurse(&path, level + 1); ++ inode_lock_nested(dir, I_MUTEX_PARENT); ++ ovl_cleanup(dir, dentry); ++ } ++} +--- a/fs/overlayfs/super.c ++++ b/fs/overlayfs/super.c +@@ -784,7 +784,7 @@ retry: + goto out_dput; + + retried = true; +- ovl_cleanup(dir, work); ++ ovl_workdir_cleanup(dir, mnt, work, 0); + dput(work); + goto retry; + } diff --git a/queue-4.4/ovl-rename-is_merge-to-is_lowest.patch b/queue-4.4/ovl-rename-is_merge-to-is_lowest.patch new file mode 100644 index 00000000000..ba17971e17b --- /dev/null +++ b/queue-4.4/ovl-rename-is_merge-to-is_lowest.patch @@ -0,0 +1,79 @@ +From 56656e960b555cb98bc414382566dcb59aae99a2 Mon Sep 17 00:00:00 2001 +From: Miklos Szeredi +Date: Mon, 21 Mar 2016 17:31:46 +0100 +Subject: ovl: rename is_merge to is_lowest + +From: Miklos Szeredi + +commit 56656e960b555cb98bc414382566dcb59aae99a2 upstream. + +The 'is_merge' is an historical naming from when only a single lower layer +could exist. With the introduction of multiple lower layers the meaning of +this flag was changed to mean only the "lowest layer" (while all lower +layers were being merged). + +So now 'is_merge' is inaccurate and hence renaming to 'is_lowest' + +Signed-off-by: Miklos Szeredi +Signed-off-by: SZ Lin (林上智) +Signed-off-by: Greg Kroah-Hartman + +--- + fs/overlayfs/readdir.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +--- a/fs/overlayfs/readdir.c ++++ b/fs/overlayfs/readdir.c +@@ -36,7 +36,7 @@ struct ovl_dir_cache { + + struct ovl_readdir_data { + struct dir_context ctx; +- bool is_merge; ++ bool is_lowest; + struct rb_root root; + struct list_head *list; + struct list_head middle; +@@ -140,9 +140,9 @@ static int ovl_cache_entry_add_rb(struct + return 0; + } + +-static int ovl_fill_lower(struct ovl_readdir_data *rdd, +- const char *name, int namelen, +- loff_t offset, u64 ino, unsigned int d_type) ++static int ovl_fill_lowest(struct ovl_readdir_data *rdd, ++ const char *name, int namelen, ++ loff_t offset, u64 ino, unsigned int d_type) + { + struct ovl_cache_entry *p; + +@@ -194,10 +194,10 @@ static int ovl_fill_merge(struct dir_con + container_of(ctx, struct ovl_readdir_data, ctx); + + rdd->count++; +- if (!rdd->is_merge) ++ if (!rdd->is_lowest) + return ovl_cache_entry_add_rb(rdd, name, namelen, ino, d_type); + else +- return ovl_fill_lower(rdd, name, namelen, offset, ino, d_type); ++ return ovl_fill_lowest(rdd, name, namelen, offset, ino, d_type); + } + + static int ovl_check_whiteouts(struct dentry *dir, struct ovl_readdir_data *rdd) +@@ -290,7 +290,7 @@ static int ovl_dir_read_merged(struct de + .ctx.actor = ovl_fill_merge, + .list = list, + .root = RB_ROOT, +- .is_merge = false, ++ .is_lowest = false, + }; + int idx, next; + +@@ -307,7 +307,7 @@ static int ovl_dir_read_merged(struct de + * allows offsets to be reasonably constant + */ + list_add(&rdd.middle, rdd.list); +- rdd.is_merge = true; ++ rdd.is_lowest = true; + err = ovl_dir_read(&realpath, &rdd); + list_del(&rdd.middle); + } diff --git a/queue-4.4/s390-lib-use-expoline-for-all-bcr-instructions.patch b/queue-4.4/s390-lib-use-expoline-for-all-bcr-instructions.patch new file mode 100644 index 00000000000..b060e730515 --- /dev/null +++ b/queue-4.4/s390-lib-use-expoline-for-all-bcr-instructions.patch @@ -0,0 +1,75 @@ +From 5eda25b10297684c1f46a14199ec00210f3c346e Mon Sep 17 00:00:00 2001 +From: Martin Schwidefsky +Date: Mon, 6 Aug 2018 13:49:47 +0200 +Subject: s390/lib: use expoline for all bcr instructions + +From: Martin Schwidefsky + +commit 5eda25b10297684c1f46a14199ec00210f3c346e upstream. + +The memove, memset, memcpy, __memset16, __memset32 and __memset64 +function have an additional indirect return branch in form of a +"bzr" instruction. These need to use expolines as well. + +Cc: # v4.17+ +Fixes: 97489e0663 ("s390/lib: use expoline for indirect branches") +Reviewed-by: Heiko Carstens +Signed-off-by: Martin Schwidefsky +Signed-off-by: Greg Kroah-Hartman + + +--- + arch/s390/lib/mem.S | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +--- a/arch/s390/lib/mem.S ++++ b/arch/s390/lib/mem.S +@@ -26,7 +26,7 @@ + */ + ENTRY(memset) + ltgr %r4,%r4 +- bzr %r14 ++ jz .Lmemset_exit + ltgr %r3,%r3 + jnz .Lmemset_fill + aghi %r4,-1 +@@ -41,12 +41,13 @@ ENTRY(memset) + .Lmemset_clear_rest: + larl %r3,.Lmemset_xc + ex %r4,0(%r3) ++.Lmemset_exit: + BR_EX %r14 + .Lmemset_fill: + stc %r3,0(%r2) + cghi %r4,1 + lgr %r1,%r2 +- ber %r14 ++ je .Lmemset_fill_exit + aghi %r4,-2 + srlg %r3,%r4,8 + ltgr %r3,%r3 +@@ -58,6 +59,7 @@ ENTRY(memset) + .Lmemset_fill_rest: + larl %r3,.Lmemset_mvc + ex %r4,0(%r3) ++.Lmemset_fill_exit: + BR_EX %r14 + .Lmemset_xc: + xc 0(1,%r1),0(%r1) +@@ -71,7 +73,7 @@ ENTRY(memset) + */ + ENTRY(memcpy) + ltgr %r4,%r4 +- bzr %r14 ++ jz .Lmemcpy_exit + aghi %r4,-1 + srlg %r5,%r4,8 + ltgr %r5,%r5 +@@ -80,6 +82,7 @@ ENTRY(memcpy) + .Lmemcpy_rest: + larl %r5,.Lmemcpy_mvc + ex %r4,0(%r5) ++.Lmemcpy_exit: + BR_EX %r14 + .Lmemcpy_loop: + mvc 0(256,%r1),0(%r3) diff --git a/queue-4.4/sch_hhf-fix-null-pointer-dereference-on-init-failure.patch b/queue-4.4/sch_hhf-fix-null-pointer-dereference-on-init-failure.patch new file mode 100644 index 00000000000..f1ea7b9a5bd --- /dev/null +++ b/queue-4.4/sch_hhf-fix-null-pointer-dereference-on-init-failure.patch @@ -0,0 +1,96 @@ +From 32db864d33c21fd70a217ba53cb7224889354ffb Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Wed, 30 Aug 2017 12:48:59 +0300 +Subject: sch_hhf: fix null pointer dereference on init failure + +From: Nikolay Aleksandrov + +commit 32db864d33c21fd70a217ba53cb7224889354ffb upstream. + +If sch_hhf fails in its ->init() function (either due to wrong +user-space arguments as below or memory alloc failure of hh_flows) it +will do a null pointer deref of q->hh_flows in its ->destroy() function. + +To reproduce the crash: +$ tc qdisc add dev eth0 root hhf quantum 2000000 non_hh_weight 10000000 + +Crash log: +[ 690.654882] BUG: unable to handle kernel NULL pointer dereference at (null) +[ 690.655565] IP: hhf_destroy+0x48/0xbc +[ 690.655944] PGD 37345067 +[ 690.655948] P4D 37345067 +[ 690.656252] PUD 58402067 +[ 690.656554] PMD 0 +[ 690.656857] +[ 690.657362] Oops: 0000 [#1] SMP +[ 690.657696] Modules linked in: +[ 690.658032] CPU: 3 PID: 920 Comm: tc Not tainted 4.13.0-rc6+ #57 +[ 690.658525] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 690.659255] task: ffff880058578000 task.stack: ffff88005acbc000 +[ 690.659747] RIP: 0010:hhf_destroy+0x48/0xbc +[ 690.660146] RSP: 0018:ffff88005acbf9e0 EFLAGS: 00010246 +[ 690.660601] RAX: 0000000000000000 RBX: 0000000000000020 RCX: 0000000000000000 +[ 690.661155] RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffffffff821f63f0 +[ 690.661710] RBP: ffff88005acbfa08 R08: ffffffff81b10a90 R09: 0000000000000000 +[ 690.662267] R10: 00000000f42b7019 R11: ffff880058578000 R12: 00000000ffffffea +[ 690.662820] R13: ffff8800372f6400 R14: 0000000000000000 R15: 0000000000000000 +[ 690.663769] FS: 00007f8ae5e8b740(0000) GS:ffff88005d980000(0000) knlGS:0000000000000000 +[ 690.667069] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 690.667965] CR2: 0000000000000000 CR3: 0000000058523000 CR4: 00000000000406e0 +[ 690.668918] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 690.669945] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 690.671003] Call Trace: +[ 690.671743] qdisc_create+0x377/0x3fd +[ 690.672534] tc_modify_qdisc+0x4d2/0x4fd +[ 690.673324] rtnetlink_rcv_msg+0x188/0x197 +[ 690.674204] ? rcu_read_unlock+0x3e/0x5f +[ 690.675091] ? rtnl_newlink+0x729/0x729 +[ 690.675877] netlink_rcv_skb+0x6c/0xce +[ 690.676648] rtnetlink_rcv+0x23/0x2a +[ 690.677405] netlink_unicast+0x103/0x181 +[ 690.678179] netlink_sendmsg+0x326/0x337 +[ 690.678958] sock_sendmsg_nosec+0x14/0x3f +[ 690.679743] sock_sendmsg+0x29/0x2e +[ 690.680506] ___sys_sendmsg+0x209/0x28b +[ 690.681283] ? __handle_mm_fault+0xc7d/0xdb1 +[ 690.681915] ? check_chain_key+0xb0/0xfd +[ 690.682449] __sys_sendmsg+0x45/0x63 +[ 690.682954] ? __sys_sendmsg+0x45/0x63 +[ 690.683471] SyS_sendmsg+0x19/0x1b +[ 690.683974] entry_SYSCALL_64_fastpath+0x23/0xc2 +[ 690.684516] RIP: 0033:0x7f8ae529d690 +[ 690.685016] RSP: 002b:00007fff26d2d6b8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +[ 690.685931] RAX: ffffffffffffffda RBX: ffffffff810d278c RCX: 00007f8ae529d690 +[ 690.686573] RDX: 0000000000000000 RSI: 00007fff26d2d700 RDI: 0000000000000003 +[ 690.687047] RBP: ffff88005acbff98 R08: 0000000000000001 R09: 0000000000000000 +[ 690.687519] R10: 00007fff26d2d480 R11: 0000000000000246 R12: 0000000000000002 +[ 690.687996] R13: 0000000001258070 R14: 0000000000000001 R15: 0000000000000000 +[ 690.688475] ? trace_hardirqs_off_caller+0xa7/0xcf +[ 690.688887] Code: 00 00 e8 2a 02 ae ff 49 8b bc 1d 60 02 00 00 48 83 +c3 08 e8 19 02 ae ff 48 83 fb 20 75 dc 45 31 f6 4d 89 f7 4d 03 bd 20 02 +00 00 <49> 8b 07 49 39 c7 75 24 49 83 c6 10 49 81 fe 00 40 00 00 75 e1 +[ 690.690200] RIP: hhf_destroy+0x48/0xbc RSP: ffff88005acbf9e0 +[ 690.690636] CR2: 0000000000000000 + +Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") +Fixes: 10239edf86f1 ("net-qdisc-hhf: Heavy-Hitter Filter (HHF) qdisc") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_hhf.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sched/sch_hhf.c ++++ b/net/sched/sch_hhf.c +@@ -501,6 +501,9 @@ static void hhf_destroy(struct Qdisc *sc + hhf_free(q->hhf_valid_bits[i]); + } + ++ if (!q->hh_flows) ++ return; ++ + for (i = 0; i < HH_FLOWS_CNT; i++) { + struct hh_flow_state *flow, *next; + struct list_head *head = &q->hh_flows[i]; diff --git a/queue-4.4/sch_htb-fix-crash-on-init-failure.patch b/queue-4.4/sch_htb-fix-crash-on-init-failure.patch new file mode 100644 index 00000000000..d9d141043a1 --- /dev/null +++ b/queue-4.4/sch_htb-fix-crash-on-init-failure.patch @@ -0,0 +1,106 @@ +From 88c2ace69dbef696edba77712882af03879abc9c Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Wed, 30 Aug 2017 12:48:57 +0300 +Subject: sch_htb: fix crash on init failure + +From: Nikolay Aleksandrov + +commit 88c2ace69dbef696edba77712882af03879abc9c upstream. + +The commit below added a call to the ->destroy() callback for all qdiscs +which failed in their ->init(), but some were not prepared for such +change and can't handle partially initialized qdisc. HTB is one of them +and if any error occurs before the qdisc watchdog timer and qdisc work are +initialized then we can hit either a null ptr deref (timer->base) when +canceling in ->destroy or lockdep error info about trying to register +a non-static key and a stack dump. So to fix these two move the watchdog +timer and workqueue init before anything that can err out. +To reproduce userspace needs to send broken htb qdisc create request, +tested with a modified tc (q_htb.c). + +Trace log: +[ 2710.897602] BUG: unable to handle kernel NULL pointer dereference at (null) +[ 2710.897977] IP: hrtimer_active+0x17/0x8a +[ 2710.898174] PGD 58fab067 +[ 2710.898175] P4D 58fab067 +[ 2710.898353] PUD 586c0067 +[ 2710.898531] PMD 0 +[ 2710.898710] +[ 2710.899045] Oops: 0000 [#1] SMP +[ 2710.899232] Modules linked in: +[ 2710.899419] CPU: 1 PID: 950 Comm: tc Not tainted 4.13.0-rc6+ #54 +[ 2710.899646] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 2710.900035] task: ffff880059ed2700 task.stack: ffff88005ad4c000 +[ 2710.900262] RIP: 0010:hrtimer_active+0x17/0x8a +[ 2710.900467] RSP: 0018:ffff88005ad4f960 EFLAGS: 00010246 +[ 2710.900684] RAX: 0000000000000000 RBX: ffff88003701e298 RCX: 0000000000000000 +[ 2710.900933] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88003701e298 +[ 2710.901177] RBP: ffff88005ad4f980 R08: 0000000000000001 R09: 0000000000000001 +[ 2710.901419] R10: ffff88005ad4f800 R11: 0000000000000400 R12: 0000000000000000 +[ 2710.901663] R13: ffff88003701e298 R14: ffffffff822a4540 R15: ffff88005ad4fac0 +[ 2710.901907] FS: 00007f2f5e90f740(0000) GS:ffff88005d880000(0000) knlGS:0000000000000000 +[ 2710.902277] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 2710.902500] CR2: 0000000000000000 CR3: 0000000058ca3000 CR4: 00000000000406e0 +[ 2710.902744] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 2710.902977] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 2710.903180] Call Trace: +[ 2710.903332] hrtimer_try_to_cancel+0x1a/0x93 +[ 2710.903504] hrtimer_cancel+0x15/0x20 +[ 2710.903667] qdisc_watchdog_cancel+0x12/0x14 +[ 2710.903866] htb_destroy+0x2e/0xf7 +[ 2710.904097] qdisc_create+0x377/0x3fd +[ 2710.904330] tc_modify_qdisc+0x4d2/0x4fd +[ 2710.904511] rtnetlink_rcv_msg+0x188/0x197 +[ 2710.904682] ? rcu_read_unlock+0x3e/0x5f +[ 2710.904849] ? rtnl_newlink+0x729/0x729 +[ 2710.905017] netlink_rcv_skb+0x6c/0xce +[ 2710.905183] rtnetlink_rcv+0x23/0x2a +[ 2710.905345] netlink_unicast+0x103/0x181 +[ 2710.905511] netlink_sendmsg+0x326/0x337 +[ 2710.905679] sock_sendmsg_nosec+0x14/0x3f +[ 2710.905847] sock_sendmsg+0x29/0x2e +[ 2710.906010] ___sys_sendmsg+0x209/0x28b +[ 2710.906176] ? do_raw_spin_unlock+0xcd/0xf8 +[ 2710.906346] ? _raw_spin_unlock+0x27/0x31 +[ 2710.906514] ? __handle_mm_fault+0x651/0xdb1 +[ 2710.906685] ? check_chain_key+0xb0/0xfd +[ 2710.906855] __sys_sendmsg+0x45/0x63 +[ 2710.907018] ? __sys_sendmsg+0x45/0x63 +[ 2710.907185] SyS_sendmsg+0x19/0x1b +[ 2710.907344] entry_SYSCALL_64_fastpath+0x23/0xc2 + +Note that probably this bug goes further back because the default qdisc +handling always calls ->destroy on init failure too. + +Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") +Fixes: 0fbbeb1ba43b ("[PKT_SCHED]: Fix missing qdisc_destroy() in qdisc_create_dflt()") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +[AmitP: Rebased for linux-4.4.y] +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_htb.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/net/sched/sch_htb.c ++++ b/net/sched/sch_htb.c +@@ -1025,6 +1025,9 @@ static int htb_init(struct Qdisc *sch, s + int err; + int i; + ++ qdisc_watchdog_init(&q->watchdog, sch); ++ INIT_WORK(&q->work, htb_work_func); ++ + if (!opt) + return -EINVAL; + +@@ -1045,8 +1048,6 @@ static int htb_init(struct Qdisc *sch, s + for (i = 0; i < TC_HTB_NUMPRIO; i++) + INIT_LIST_HEAD(q->drops + i); + +- qdisc_watchdog_init(&q->watchdog, sch); +- INIT_WORK(&q->work, htb_work_func); + __skb_queue_head_init(&q->direct_queue); + + if (tb[TCA_HTB_DIRECT_QLEN]) diff --git a/queue-4.4/sch_multiq-fix-double-free-on-init-failure.patch b/queue-4.4/sch_multiq-fix-double-free-on-init-failure.patch new file mode 100644 index 00000000000..a99765d35f0 --- /dev/null +++ b/queue-4.4/sch_multiq-fix-double-free-on-init-failure.patch @@ -0,0 +1,118 @@ +From e89d469e3be3ed3d7124a803211a463ff83d0964 Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Wed, 30 Aug 2017 12:48:58 +0300 +Subject: sch_multiq: fix double free on init failure + +From: Nikolay Aleksandrov + +commit e89d469e3be3ed3d7124a803211a463ff83d0964 upstream. + +The below commit added a call to ->destroy() on init failure, but multiq +still frees ->queues on error in init, but ->queues is also freed by +->destroy() thus we get double free and corrupted memory. + +Very easy to reproduce (eth0 not multiqueue): +$ tc qdisc add dev eth0 root multiq +RTNETLINK answers: Operation not supported +$ ip l add dumdum type dummy +(crash) + +Trace log: +[ 3929.467747] general protection fault: 0000 [#1] SMP +[ 3929.468083] Modules linked in: +[ 3929.468302] CPU: 3 PID: 967 Comm: ip Not tainted 4.13.0-rc6+ #56 +[ 3929.468625] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 3929.469124] task: ffff88003716a700 task.stack: ffff88005872c000 +[ 3929.469449] RIP: 0010:__kmalloc_track_caller+0x117/0x1be +[ 3929.469746] RSP: 0018:ffff88005872f6a0 EFLAGS: 00010246 +[ 3929.470042] RAX: 00000000000002de RBX: 0000000058a59000 RCX: 00000000000002df +[ 3929.470406] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff821f7020 +[ 3929.470770] RBP: ffff88005872f6e8 R08: 000000000001f010 R09: 0000000000000000 +[ 3929.471133] R10: ffff88005872f730 R11: 0000000000008cdd R12: ff006d75646d7564 +[ 3929.471496] R13: 00000000014000c0 R14: ffff88005b403c00 R15: ffff88005b403c00 +[ 3929.471869] FS: 00007f0b70480740(0000) GS:ffff88005d980000(0000) knlGS:0000000000000000 +[ 3929.472286] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 3929.472677] CR2: 00007ffcee4f3000 CR3: 0000000059d45000 CR4: 00000000000406e0 +[ 3929.473209] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 3929.474109] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 3929.474873] Call Trace: +[ 3929.475337] ? kstrdup_const+0x23/0x25 +[ 3929.475863] kstrdup+0x2e/0x4b +[ 3929.476338] kstrdup_const+0x23/0x25 +[ 3929.478084] __kernfs_new_node+0x28/0xbc +[ 3929.478478] kernfs_new_node+0x35/0x55 +[ 3929.478929] kernfs_create_link+0x23/0x76 +[ 3929.479478] sysfs_do_create_link_sd.isra.2+0x85/0xd7 +[ 3929.480096] sysfs_create_link+0x33/0x35 +[ 3929.480649] device_add+0x200/0x589 +[ 3929.481184] netdev_register_kobject+0x7c/0x12f +[ 3929.481711] register_netdevice+0x373/0x471 +[ 3929.482174] rtnl_newlink+0x614/0x729 +[ 3929.482610] ? rtnl_newlink+0x17f/0x729 +[ 3929.483080] rtnetlink_rcv_msg+0x188/0x197 +[ 3929.483533] ? rcu_read_unlock+0x3e/0x5f +[ 3929.483984] ? rtnl_newlink+0x729/0x729 +[ 3929.484420] netlink_rcv_skb+0x6c/0xce +[ 3929.484858] rtnetlink_rcv+0x23/0x2a +[ 3929.485291] netlink_unicast+0x103/0x181 +[ 3929.485735] netlink_sendmsg+0x326/0x337 +[ 3929.486181] sock_sendmsg_nosec+0x14/0x3f +[ 3929.486614] sock_sendmsg+0x29/0x2e +[ 3929.486973] ___sys_sendmsg+0x209/0x28b +[ 3929.487340] ? do_raw_spin_unlock+0xcd/0xf8 +[ 3929.487719] ? _raw_spin_unlock+0x27/0x31 +[ 3929.488092] ? __handle_mm_fault+0x651/0xdb1 +[ 3929.488471] ? check_chain_key+0xb0/0xfd +[ 3929.488847] __sys_sendmsg+0x45/0x63 +[ 3929.489206] ? __sys_sendmsg+0x45/0x63 +[ 3929.489576] SyS_sendmsg+0x19/0x1b +[ 3929.489901] entry_SYSCALL_64_fastpath+0x23/0xc2 +[ 3929.490172] RIP: 0033:0x7f0b6fb93690 +[ 3929.490423] RSP: 002b:00007ffcee4ed588 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +[ 3929.490881] RAX: ffffffffffffffda RBX: ffffffff810d278c RCX: 00007f0b6fb93690 +[ 3929.491198] RDX: 0000000000000000 RSI: 00007ffcee4ed5d0 RDI: 0000000000000003 +[ 3929.491521] RBP: ffff88005872ff98 R08: 0000000000000001 R09: 0000000000000000 +[ 3929.491801] R10: 00007ffcee4ed350 R11: 0000000000000246 R12: 0000000000000002 +[ 3929.492075] R13: 000000000066f1a0 R14: 00007ffcee4f5680 R15: 0000000000000000 +[ 3929.492352] ? trace_hardirqs_off_caller+0xa7/0xcf +[ 3929.492590] Code: 8b 45 c0 48 8b 45 b8 74 17 48 8b 4d c8 83 ca ff 44 +89 ee 4c 89 f7 e8 83 ca ff ff 49 89 c4 eb 49 49 63 56 20 48 8d 48 01 4d +8b 06 <49> 8b 1c 14 48 89 c2 4c 89 e0 65 49 0f c7 08 0f 94 c0 83 f0 01 +[ 3929.493335] RIP: __kmalloc_track_caller+0x117/0x1be RSP: ffff88005872f6a0 + +Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") +Fixes: f07d1501292b ("multiq: Further multiqueue cleanup") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +[AmitP: Removed unused variable 'err' in multiq_init()] +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_multiq.c | 9 ++------- + 1 file changed, 2 insertions(+), 7 deletions(-) + +--- a/net/sched/sch_multiq.c ++++ b/net/sched/sch_multiq.c +@@ -254,7 +254,7 @@ static int multiq_tune(struct Qdisc *sch + static int multiq_init(struct Qdisc *sch, struct nlattr *opt) + { + struct multiq_sched_data *q = qdisc_priv(sch); +- int i, err; ++ int i; + + q->queues = NULL; + +@@ -269,12 +269,7 @@ static int multiq_init(struct Qdisc *sch + for (i = 0; i < q->max_bands; i++) + q->queues[i] = &noop_qdisc; + +- err = multiq_tune(sch, opt); +- +- if (err) +- kfree(q->queues); +- +- return err; ++ return multiq_tune(sch, opt); + } + + static int multiq_dump(struct Qdisc *sch, struct sk_buff *skb) diff --git a/queue-4.4/sch_netem-avoid-null-pointer-deref-on-init-failure.patch b/queue-4.4/sch_netem-avoid-null-pointer-deref-on-init-failure.patch new file mode 100644 index 00000000000..190d64863ae --- /dev/null +++ b/queue-4.4/sch_netem-avoid-null-pointer-deref-on-init-failure.patch @@ -0,0 +1,122 @@ +From 634576a1844dba15bc5e6fc61d72f37e13a21615 Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Wed, 30 Aug 2017 12:49:03 +0300 +Subject: sch_netem: avoid null pointer deref on init failure + +From: Nikolay Aleksandrov + +commit 634576a1844dba15bc5e6fc61d72f37e13a21615 upstream. + +netem can fail in ->init due to missing options (either not supplied by +user-space or used as a default qdisc) causing a timer->base null +pointer deref in its ->destroy() and ->reset() callbacks. + +Reproduce: +$ sysctl net.core.default_qdisc=netem +$ ip l set ethX up + +Crash log: +[ 1814.846943] BUG: unable to handle kernel NULL pointer dereference at (null) +[ 1814.847181] IP: hrtimer_active+0x17/0x8a +[ 1814.847270] PGD 59c34067 +[ 1814.847271] P4D 59c34067 +[ 1814.847337] PUD 37374067 +[ 1814.847403] PMD 0 +[ 1814.847468] +[ 1814.847582] Oops: 0000 [#1] SMP +[ 1814.847655] Modules linked in: sch_netem(O) sch_fq_codel(O) +[ 1814.847761] CPU: 3 PID: 1573 Comm: ip Tainted: G O 4.13.0-rc6+ #62 +[ 1814.847884] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 1814.848043] task: ffff88003723a700 task.stack: ffff88005adc8000 +[ 1814.848235] RIP: 0010:hrtimer_active+0x17/0x8a +[ 1814.848407] RSP: 0018:ffff88005adcb590 EFLAGS: 00010246 +[ 1814.848590] RAX: 0000000000000000 RBX: ffff880058e359d8 RCX: 0000000000000000 +[ 1814.848793] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff880058e359d8 +[ 1814.848998] RBP: ffff88005adcb5b0 R08: 00000000014080c0 R09: 00000000ffffffff +[ 1814.849204] R10: ffff88005adcb660 R11: 0000000000000020 R12: 0000000000000000 +[ 1814.849410] R13: ffff880058e359d8 R14: 00000000ffffffff R15: 0000000000000001 +[ 1814.849616] FS: 00007f733bbca740(0000) GS:ffff88005d980000(0000) knlGS:0000000000000000 +[ 1814.849919] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 1814.850107] CR2: 0000000000000000 CR3: 0000000059f0d000 CR4: 00000000000406e0 +[ 1814.850313] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 1814.850518] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 1814.850723] Call Trace: +[ 1814.850875] hrtimer_try_to_cancel+0x1a/0x93 +[ 1814.851047] hrtimer_cancel+0x15/0x20 +[ 1814.851211] qdisc_watchdog_cancel+0x12/0x14 +[ 1814.851383] netem_reset+0xe6/0xed [sch_netem] +[ 1814.851561] qdisc_destroy+0x8b/0xe5 +[ 1814.851723] qdisc_create_dflt+0x86/0x94 +[ 1814.851890] ? dev_activate+0x129/0x129 +[ 1814.852057] attach_one_default_qdisc+0x36/0x63 +[ 1814.852232] netdev_for_each_tx_queue+0x3d/0x48 +[ 1814.852406] dev_activate+0x4b/0x129 +[ 1814.852569] __dev_open+0xe7/0x104 +[ 1814.852730] __dev_change_flags+0xc6/0x15c +[ 1814.852899] dev_change_flags+0x25/0x59 +[ 1814.853064] do_setlink+0x30c/0xb3f +[ 1814.853228] ? check_chain_key+0xb0/0xfd +[ 1814.853396] ? check_chain_key+0xb0/0xfd +[ 1814.853565] rtnl_newlink+0x3a4/0x729 +[ 1814.853728] ? rtnl_newlink+0x117/0x729 +[ 1814.853905] ? ns_capable_common+0xd/0xb1 +[ 1814.854072] ? ns_capable+0x13/0x15 +[ 1814.854234] rtnetlink_rcv_msg+0x188/0x197 +[ 1814.854404] ? rcu_read_unlock+0x3e/0x5f +[ 1814.854572] ? rtnl_newlink+0x729/0x729 +[ 1814.854737] netlink_rcv_skb+0x6c/0xce +[ 1814.854902] rtnetlink_rcv+0x23/0x2a +[ 1814.855064] netlink_unicast+0x103/0x181 +[ 1814.855230] netlink_sendmsg+0x326/0x337 +[ 1814.855398] sock_sendmsg_nosec+0x14/0x3f +[ 1814.855584] sock_sendmsg+0x29/0x2e +[ 1814.855747] ___sys_sendmsg+0x209/0x28b +[ 1814.855912] ? do_raw_spin_unlock+0xcd/0xf8 +[ 1814.856082] ? _raw_spin_unlock+0x27/0x31 +[ 1814.856251] ? __handle_mm_fault+0x651/0xdb1 +[ 1814.856421] ? check_chain_key+0xb0/0xfd +[ 1814.856592] __sys_sendmsg+0x45/0x63 +[ 1814.856755] ? __sys_sendmsg+0x45/0x63 +[ 1814.856923] SyS_sendmsg+0x19/0x1b +[ 1814.857083] entry_SYSCALL_64_fastpath+0x23/0xc2 +[ 1814.857256] RIP: 0033:0x7f733b2dd690 +[ 1814.857419] RSP: 002b:00007ffe1d3387d8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +[ 1814.858238] RAX: ffffffffffffffda RBX: ffffffff810d278c RCX: 00007f733b2dd690 +[ 1814.858445] RDX: 0000000000000000 RSI: 00007ffe1d338820 RDI: 0000000000000003 +[ 1814.858651] RBP: ffff88005adcbf98 R08: 0000000000000001 R09: 0000000000000003 +[ 1814.858856] R10: 00007ffe1d3385a0 R11: 0000000000000246 R12: 0000000000000002 +[ 1814.859060] R13: 000000000066f1a0 R14: 00007ffe1d3408d0 R15: 0000000000000000 +[ 1814.859267] ? trace_hardirqs_off_caller+0xa7/0xcf +[ 1814.859446] Code: 10 55 48 89 c7 48 89 e5 e8 45 a1 fb ff 31 c0 5d c3 +31 c0 c3 66 66 66 66 90 55 48 89 e5 41 56 41 55 41 54 53 49 89 fd 49 8b +45 30 <4c> 8b 20 41 8b 5c 24 38 31 c9 31 d2 48 c7 c7 50 8e 1d 82 41 89 +[ 1814.860022] RIP: hrtimer_active+0x17/0x8a RSP: ffff88005adcb590 +[ 1814.860214] CR2: 0000000000000000 + +Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") +Fixes: 0fbbeb1ba43b ("[PKT_SCHED]: Fix missing qdisc_destroy() in qdisc_create_dflt()") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman + +--- + net/sched/sch_netem.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/sched/sch_netem.c ++++ b/net/sched/sch_netem.c +@@ -943,11 +943,11 @@ static int netem_init(struct Qdisc *sch, + struct netem_sched_data *q = qdisc_priv(sch); + int ret; + ++ qdisc_watchdog_init(&q->watchdog, sch); ++ + if (!opt) + return -EINVAL; + +- qdisc_watchdog_init(&q->watchdog, sch); +- + q->loss_model = CLG_RANDOM; + ret = netem_change(sch, opt); + if (ret) diff --git a/queue-4.4/sch_tbf-fix-two-null-pointer-dereferences-on-init-failure.patch b/queue-4.4/sch_tbf-fix-two-null-pointer-dereferences-on-init-failure.patch new file mode 100644 index 00000000000..2a29799a1f3 --- /dev/null +++ b/queue-4.4/sch_tbf-fix-two-null-pointer-dereferences-on-init-failure.patch @@ -0,0 +1,120 @@ +From c2d6511e6a4f1f3673d711569c00c3849549e9b0 Mon Sep 17 00:00:00 2001 +From: Nikolay Aleksandrov +Date: Wed, 30 Aug 2017 12:49:05 +0300 +Subject: sch_tbf: fix two null pointer dereferences on init failure + +From: Nikolay Aleksandrov + +commit c2d6511e6a4f1f3673d711569c00c3849549e9b0 upstream. + +sch_tbf calls qdisc_watchdog_cancel() in both its ->reset and ->destroy +callbacks but it may fail before the timer is initialized due to missing +options (either not supplied by user-space or set as a default qdisc), +also q->qdisc is used by ->reset and ->destroy so we need it initialized. + +Reproduce: +$ sysctl net.core.default_qdisc=tbf +$ ip l set ethX up + +Crash log: +[ 959.160172] BUG: unable to handle kernel NULL pointer dereference at 0000000000000018 +[ 959.160323] IP: qdisc_reset+0xa/0x5c +[ 959.160400] PGD 59cdb067 +[ 959.160401] P4D 59cdb067 +[ 959.160466] PUD 59ccb067 +[ 959.160532] PMD 0 +[ 959.160597] +[ 959.160706] Oops: 0000 [#1] SMP +[ 959.160778] Modules linked in: sch_tbf sch_sfb sch_prio sch_netem +[ 959.160891] CPU: 2 PID: 1562 Comm: ip Not tainted 4.13.0-rc6+ #62 +[ 959.160998] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.7.5-20140531_083030-gandalf 04/01/2014 +[ 959.161157] task: ffff880059c9a700 task.stack: ffff8800376d0000 +[ 959.161263] RIP: 0010:qdisc_reset+0xa/0x5c +[ 959.161347] RSP: 0018:ffff8800376d3610 EFLAGS: 00010286 +[ 959.161531] RAX: ffffffffa001b1dd RBX: ffff8800373a2800 RCX: 0000000000000000 +[ 959.161733] RDX: ffffffff8215f160 RSI: ffffffff8215f160 RDI: 0000000000000000 +[ 959.161939] RBP: ffff8800376d3618 R08: 00000000014080c0 R09: 00000000ffffffff +[ 959.162141] R10: ffff8800376d3578 R11: 0000000000000020 R12: ffffffffa001d2c0 +[ 959.162343] R13: ffff880037538000 R14: 00000000ffffffff R15: 0000000000000001 +[ 959.162546] FS: 00007fcc5126b740(0000) GS:ffff88005d900000(0000) knlGS:0000000000000000 +[ 959.162844] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 959.163030] CR2: 0000000000000018 CR3: 000000005abc4000 CR4: 00000000000406e0 +[ 959.163233] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 959.163436] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 959.163638] Call Trace: +[ 959.163788] tbf_reset+0x19/0x64 [sch_tbf] +[ 959.163957] qdisc_destroy+0x8b/0xe5 +[ 959.164119] qdisc_create_dflt+0x86/0x94 +[ 959.164284] ? dev_activate+0x129/0x129 +[ 959.164449] attach_one_default_qdisc+0x36/0x63 +[ 959.164623] netdev_for_each_tx_queue+0x3d/0x48 +[ 959.164795] dev_activate+0x4b/0x129 +[ 959.164957] __dev_open+0xe7/0x104 +[ 959.165118] __dev_change_flags+0xc6/0x15c +[ 959.165287] dev_change_flags+0x25/0x59 +[ 959.165451] do_setlink+0x30c/0xb3f +[ 959.165613] ? check_chain_key+0xb0/0xfd +[ 959.165782] rtnl_newlink+0x3a4/0x729 +[ 959.165947] ? rtnl_newlink+0x117/0x729 +[ 959.166121] ? ns_capable_common+0xd/0xb1 +[ 959.166288] ? ns_capable+0x13/0x15 +[ 959.166450] rtnetlink_rcv_msg+0x188/0x197 +[ 959.166617] ? rcu_read_unlock+0x3e/0x5f +[ 959.166783] ? rtnl_newlink+0x729/0x729 +[ 959.166948] netlink_rcv_skb+0x6c/0xce +[ 959.167113] rtnetlink_rcv+0x23/0x2a +[ 959.167273] netlink_unicast+0x103/0x181 +[ 959.167439] netlink_sendmsg+0x326/0x337 +[ 959.167607] sock_sendmsg_nosec+0x14/0x3f +[ 959.167772] sock_sendmsg+0x29/0x2e +[ 959.167932] ___sys_sendmsg+0x209/0x28b +[ 959.168098] ? do_raw_spin_unlock+0xcd/0xf8 +[ 959.168267] ? _raw_spin_unlock+0x27/0x31 +[ 959.168432] ? __handle_mm_fault+0x651/0xdb1 +[ 959.168602] ? check_chain_key+0xb0/0xfd +[ 959.168773] __sys_sendmsg+0x45/0x63 +[ 959.168934] ? __sys_sendmsg+0x45/0x63 +[ 959.169100] SyS_sendmsg+0x19/0x1b +[ 959.169260] entry_SYSCALL_64_fastpath+0x23/0xc2 +[ 959.169432] RIP: 0033:0x7fcc5097e690 +[ 959.169592] RSP: 002b:00007ffd0d5c7b48 EFLAGS: 00000246 ORIG_RAX: 000000000000002e +[ 959.169887] RAX: ffffffffffffffda RBX: ffffffff810d278c RCX: 00007fcc5097e690 +[ 959.170089] RDX: 0000000000000000 RSI: 00007ffd0d5c7b90 RDI: 0000000000000003 +[ 959.170292] RBP: ffff8800376d3f98 R08: 0000000000000001 R09: 0000000000000003 +[ 959.170494] R10: 00007ffd0d5c7910 R11: 0000000000000246 R12: 0000000000000006 +[ 959.170697] R13: 000000000066f1a0 R14: 00007ffd0d5cfc40 R15: 0000000000000000 +[ 959.170900] ? trace_hardirqs_off_caller+0xa7/0xcf +[ 959.171076] Code: 00 41 c7 84 24 14 01 00 00 00 00 00 00 41 c7 84 24 +98 00 00 00 00 00 00 00 41 5c 41 5d 41 5e 5d c3 66 66 66 66 90 55 48 89 +e5 53 <48> 8b 47 18 48 89 fb 48 8b 40 48 48 85 c0 74 02 ff d0 48 8b bb +[ 959.171637] RIP: qdisc_reset+0xa/0x5c RSP: ffff8800376d3610 +[ 959.171821] CR2: 0000000000000018 + +Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") +Fixes: 0fbbeb1ba43b ("[PKT_SCHED]: Fix missing qdisc_destroy() in qdisc_create_dflt()") +Signed-off-by: Nikolay Aleksandrov +Signed-off-by: David S. Miller +Signed-off-by: Amit Pundir +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_tbf.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +--- a/net/sched/sch_tbf.c ++++ b/net/sched/sch_tbf.c +@@ -432,12 +432,13 @@ static int tbf_init(struct Qdisc *sch, s + { + struct tbf_sched_data *q = qdisc_priv(sch); + ++ qdisc_watchdog_init(&q->watchdog, sch); ++ q->qdisc = &noop_qdisc; ++ + if (opt == NULL) + return -EINVAL; + + q->t_c = ktime_get_ns(); +- qdisc_watchdog_init(&q->watchdog, sch); +- q->qdisc = &noop_qdisc; + + return tbf_change(sch, opt); + } diff --git a/queue-4.4/series b/queue-4.4/series index 6992e83eb1b..fc8e03af2bf 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -40,3 +40,21 @@ irda-only-insert-new-objects-into-the-global-database-via-setsockopt.patch revert-arm-imx_v6_v7_defconfig-select-ulpi-support.patch enic-do-not-call-enic_change_mtu-in-enic_probe.patch fixes-commit-cdbf92675fad-mm-numa-avoid-waiting-on-freed-migrated-pages.patch +genirq-delay-incrementing-interrupt-count-if-it-s-disabled-pending.patch +irqchip-gic-v3-its-recompute-the-number-of-pages-on-page-size-change.patch +irqchip-gicv3-its-fix-memory-leak-in-its_free_tables.patch +irqchip-gicv3-its-avoid-cache-flush-beyond-its_basern-memory-size.patch +irqchip-gic-v3-add-missing-barrier-to-32bit-version-of-gic_read_iar.patch +irqchip-gic-make-interrupt-id-1020-invalid.patch +ovl-rename-is_merge-to-is_lowest.patch +ovl-override-creds-with-the-ones-from-the-superblock-mounter.patch +ovl-proper-cleanup-of-workdir.patch +sch_htb-fix-crash-on-init-failure.patch +sch_multiq-fix-double-free-on-init-failure.patch +sch_hhf-fix-null-pointer-dereference-on-init-failure.patch +sch_netem-avoid-null-pointer-deref-on-init-failure.patch +sch_tbf-fix-two-null-pointer-dereferences-on-init-failure.patch +mei-me-allow-runtime-pm-for-platform-with-d0i3.patch +s390-lib-use-expoline-for-all-bcr-instructions.patch +asoc-wm8994-fix-missing-break-in-switch.patch +btrfs-use-correct-compare-function-of-dirty_metadata_bytes.patch