]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.2-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Jul 2019 11:07:21 +0000 (13:07 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 23 Jul 2019 11:07:21 +0000 (13:07 +0200)
added patches:
arm64-fix-incorrect-irqflag-restore-for-priority-masking.patch
arm64-irqflags-add-condition-flags-to-inline-asm-clobber-list.patch
arm64-tegra-fix-agic-register-range.patch
fs-proc-proc_sysctl.c-fix-the-default-values-of-i_uid-i_gid-on-proc-sys-inodes.patch
i3c-fix-i2c-and-i3c-scl-rate-by-bus-mode.patch
intel_th-msu-fix-unused-variable-warning-on-arm64-platform.patch
signal-correct-namespace-fixups-of-si_pid-and-si_uid.patch
signal-usb-replace-kill_pid_info_as_cred-with-kill_pid_usb_asyncio.patch

queue-5.2/arm64-fix-incorrect-irqflag-restore-for-priority-masking.patch [new file with mode: 0644]
queue-5.2/arm64-irqflags-add-condition-flags-to-inline-asm-clobber-list.patch [new file with mode: 0644]
queue-5.2/arm64-tegra-fix-agic-register-range.patch [new file with mode: 0644]
queue-5.2/fs-proc-proc_sysctl.c-fix-the-default-values-of-i_uid-i_gid-on-proc-sys-inodes.patch [new file with mode: 0644]
queue-5.2/i3c-fix-i2c-and-i3c-scl-rate-by-bus-mode.patch [new file with mode: 0644]
queue-5.2/intel_th-msu-fix-unused-variable-warning-on-arm64-platform.patch [new file with mode: 0644]
queue-5.2/series
queue-5.2/signal-correct-namespace-fixups-of-si_pid-and-si_uid.patch [new file with mode: 0644]
queue-5.2/signal-usb-replace-kill_pid_info_as_cred-with-kill_pid_usb_asyncio.patch [new file with mode: 0644]

diff --git a/queue-5.2/arm64-fix-incorrect-irqflag-restore-for-priority-masking.patch b/queue-5.2/arm64-fix-incorrect-irqflag-restore-for-priority-masking.patch
new file mode 100644 (file)
index 0000000..8dfbfee
--- /dev/null
@@ -0,0 +1,479 @@
+From bd82d4bd21880b7c4d5f5756be435095d6ae07b5 Mon Sep 17 00:00:00 2001
+From: Julien Thierry <julien.thierry@arm.com>
+Date: Tue, 11 Jun 2019 10:38:10 +0100
+Subject: arm64: Fix incorrect irqflag restore for priority masking
+
+From: Julien Thierry <julien.thierry@arm.com>
+
+commit bd82d4bd21880b7c4d5f5756be435095d6ae07b5 upstream.
+
+When using IRQ priority masking to disable interrupts, in order to deal
+with the PSR.I state, local_irq_save() would convert the I bit into a
+PMR value (GIC_PRIO_IRQOFF). This resulted in local_irq_restore()
+potentially modifying the value of PMR in undesired location due to the
+state of PSR.I upon flag saving [1].
+
+In an attempt to solve this issue in a less hackish manner, introduce
+a bit (GIC_PRIO_IGNORE_PMR) for the PMR values that can represent
+whether PSR.I is being used to disable interrupts, in which case it
+takes precedence of the status of interrupt masking via PMR.
+
+GIC_PRIO_PSR_I_SET is chosen such that (<pmr_value> |
+GIC_PRIO_PSR_I_SET) does not mask more interrupts than <pmr_value> as
+some sections (e.g. arch_cpu_idle(), interrupt acknowledge path)
+requires PMR not to mask interrupts that could be signaled to the
+CPU when using only PSR.I.
+
+[1] https://www.spinics.net/lists/arm-kernel/msg716956.html
+
+Fixes: 4a503217ce37 ("arm64: irqflags: Use ICC_PMR_EL1 for interrupt masking")
+Cc: <stable@vger.kernel.org> # 5.1.x-
+Reported-by: Zenghui Yu <yuzenghui@huawei.com>
+Cc: Steven Rostedt <rostedt@goodmis.org>
+Cc: Wei Li <liwei391@huawei.com>
+Cc: Will Deacon <will.deacon@arm.com>
+Cc: Christoffer Dall <christoffer.dall@arm.com>
+Cc: James Morse <james.morse@arm.com>
+Cc: Suzuki K Pouloze <suzuki.poulose@arm.com>
+Cc: Oleg Nesterov <oleg@redhat.com>
+Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
+Signed-off-by: Julien Thierry <julien.thierry@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/arch_gicv3.h |    4 +-
+ arch/arm64/include/asm/daifflags.h  |   68 +++++++++++++++++++++---------------
+ arch/arm64/include/asm/irqflags.h   |   67 ++++++++++++++---------------------
+ arch/arm64/include/asm/kvm_host.h   |    7 ++-
+ arch/arm64/include/asm/ptrace.h     |   10 ++++-
+ arch/arm64/kernel/entry.S           |   38 +++++++++++++++++---
+ arch/arm64/kernel/process.c         |    2 -
+ arch/arm64/kernel/smp.c             |    8 ++--
+ arch/arm64/kvm/hyp/switch.c         |    2 -
+ 9 files changed, 123 insertions(+), 83 deletions(-)
+
+--- a/arch/arm64/include/asm/arch_gicv3.h
++++ b/arch/arm64/include/asm/arch_gicv3.h
+@@ -152,7 +152,9 @@ static inline bool gic_prio_masking_enab
+ static inline void gic_pmr_mask_irqs(void)
+ {
+-      BUILD_BUG_ON(GICD_INT_DEF_PRI <= GIC_PRIO_IRQOFF);
++      BUILD_BUG_ON(GICD_INT_DEF_PRI < (GIC_PRIO_IRQOFF |
++                                       GIC_PRIO_PSR_I_SET));
++      BUILD_BUG_ON(GICD_INT_DEF_PRI >= GIC_PRIO_IRQON);
+       gic_write_pmr(GIC_PRIO_IRQOFF);
+ }
+--- a/arch/arm64/include/asm/daifflags.h
++++ b/arch/arm64/include/asm/daifflags.h
+@@ -7,6 +7,7 @@
+ #include <linux/irqflags.h>
++#include <asm/arch_gicv3.h>
+ #include <asm/cpufeature.h>
+ #define DAIF_PROCCTX          0
+@@ -21,6 +22,11 @@ static inline void local_daif_mask(void)
+               :
+               :
+               : "memory");
++
++      /* Don't really care for a dsb here, we don't intend to enable IRQs */
++      if (system_uses_irq_prio_masking())
++              gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
++
+       trace_hardirqs_off();
+ }
+@@ -32,7 +38,7 @@ static inline unsigned long local_daif_s
+       if (system_uses_irq_prio_masking()) {
+               /* If IRQs are masked with PMR, reflect it in the flags */
+-              if (read_sysreg_s(SYS_ICC_PMR_EL1) <= GIC_PRIO_IRQOFF)
++              if (read_sysreg_s(SYS_ICC_PMR_EL1) != GIC_PRIO_IRQON)
+                       flags |= PSR_I_BIT;
+       }
+@@ -48,36 +54,44 @@ static inline void local_daif_restore(un
+       if (!irq_disabled) {
+               trace_hardirqs_on();
+-              if (system_uses_irq_prio_masking())
+-                      arch_local_irq_enable();
+-      } else if (!(flags & PSR_A_BIT)) {
+-              /*
+-               * If interrupts are disabled but we can take
+-               * asynchronous errors, we can take NMIs
+-               */
+               if (system_uses_irq_prio_masking()) {
+-                      flags &= ~PSR_I_BIT;
++                      gic_write_pmr(GIC_PRIO_IRQON);
++                      dsb(sy);
++              }
++      } else if (system_uses_irq_prio_masking()) {
++              u64 pmr;
++
++              if (!(flags & PSR_A_BIT)) {
+                       /*
+-                       * There has been concern that the write to daif
+-                       * might be reordered before this write to PMR.
+-                       * From the ARM ARM DDI 0487D.a, section D1.7.1
+-                       * "Accessing PSTATE fields":
+-                       *   Writes to the PSTATE fields have side-effects on
+-                       *   various aspects of the PE operation. All of these
+-                       *   side-effects are guaranteed:
+-                       *     - Not to be visible to earlier instructions in
+-                       *       the execution stream.
+-                       *     - To be visible to later instructions in the
+-                       *       execution stream
+-                       *
+-                       * Also, writes to PMR are self-synchronizing, so no
+-                       * interrupts with a lower priority than PMR is signaled
+-                       * to the PE after the write.
+-                       *
+-                       * So we don't need additional synchronization here.
++                       * If interrupts are disabled but we can take
++                       * asynchronous errors, we can take NMIs
+                        */
+-                      arch_local_irq_disable();
++                      flags &= ~PSR_I_BIT;
++                      pmr = GIC_PRIO_IRQOFF;
++              } else {
++                      pmr = GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET;
+               }
++
++              /*
++               * There has been concern that the write to daif
++               * might be reordered before this write to PMR.
++               * From the ARM ARM DDI 0487D.a, section D1.7.1
++               * "Accessing PSTATE fields":
++               *   Writes to the PSTATE fields have side-effects on
++               *   various aspects of the PE operation. All of these
++               *   side-effects are guaranteed:
++               *     - Not to be visible to earlier instructions in
++               *       the execution stream.
++               *     - To be visible to later instructions in the
++               *       execution stream
++               *
++               * Also, writes to PMR are self-synchronizing, so no
++               * interrupts with a lower priority than PMR is signaled
++               * to the PE after the write.
++               *
++               * So we don't need additional synchronization here.
++               */
++              gic_write_pmr(pmr);
+       }
+       write_sysreg(flags, daif);
+--- a/arch/arm64/include/asm/irqflags.h
++++ b/arch/arm64/include/asm/irqflags.h
+@@ -56,43 +56,46 @@ static inline void arch_local_irq_disabl
+  */
+ static inline unsigned long arch_local_save_flags(void)
+ {
+-      unsigned long daif_bits;
+       unsigned long flags;
+-      daif_bits = read_sysreg(daif);
+-
+-      /*
+-       * The asm is logically equivalent to:
+-       *
+-       * if (system_uses_irq_prio_masking())
+-       *      flags = (daif_bits & PSR_I_BIT) ?
+-       *                      GIC_PRIO_IRQOFF :
+-       *                      read_sysreg_s(SYS_ICC_PMR_EL1);
+-       * else
+-       *      flags = daif_bits;
+-       */
+       asm volatile(ALTERNATIVE(
+-                      "mov    %0, %1\n"
+-                      "nop\n"
+-                      "nop",
+-                      __mrs_s("%0", SYS_ICC_PMR_EL1)
+-                      "ands   %1, %1, " __stringify(PSR_I_BIT) "\n"
+-                      "csel   %0, %0, %2, eq",
+-                      ARM64_HAS_IRQ_PRIO_MASKING)
+-              : "=&r" (flags), "+r" (daif_bits)
+-              : "r" ((unsigned long) GIC_PRIO_IRQOFF)
+-              : "cc", "memory");
++              "mrs    %0, daif",
++              __mrs_s("%0", SYS_ICC_PMR_EL1),
++              ARM64_HAS_IRQ_PRIO_MASKING)
++              : "=&r" (flags)
++              :
++              : "memory");
+       return flags;
+ }
++static inline int arch_irqs_disabled_flags(unsigned long flags)
++{
++      int res;
++
++      asm volatile(ALTERNATIVE(
++              "and    %w0, %w1, #" __stringify(PSR_I_BIT),
++              "eor    %w0, %w1, #" __stringify(GIC_PRIO_IRQON),
++              ARM64_HAS_IRQ_PRIO_MASKING)
++              : "=&r" (res)
++              : "r" ((int) flags)
++              : "memory");
++
++      return res;
++}
++
+ static inline unsigned long arch_local_irq_save(void)
+ {
+       unsigned long flags;
+       flags = arch_local_save_flags();
+-      arch_local_irq_disable();
++      /*
++       * There are too many states with IRQs disabled, just keep the current
++       * state if interrupts are already disabled/masked.
++       */
++      if (!arch_irqs_disabled_flags(flags))
++              arch_local_irq_disable();
+       return flags;
+ }
+@@ -113,21 +116,5 @@ static inline void arch_local_irq_restor
+               : "memory");
+ }
+-static inline int arch_irqs_disabled_flags(unsigned long flags)
+-{
+-      int res;
+-
+-      asm volatile(ALTERNATIVE(
+-                      "and    %w0, %w1, #" __stringify(PSR_I_BIT) "\n"
+-                      "nop",
+-                      "cmp    %w1, #" __stringify(GIC_PRIO_IRQOFF) "\n"
+-                      "cset   %w0, ls",
+-                      ARM64_HAS_IRQ_PRIO_MASKING)
+-              : "=&r" (res)
+-              : "r" ((int) flags)
+-              : "cc", "memory");
+-
+-      return res;
+-}
+ #endif
+ #endif
+--- a/arch/arm64/include/asm/kvm_host.h
++++ b/arch/arm64/include/asm/kvm_host.h
+@@ -597,11 +597,12 @@ static inline void kvm_arm_vhe_guest_ent
+        * will not signal the CPU of interrupts of lower priority, and the
+        * only way to get out will be via guest exceptions.
+        * Naturally, we want to avoid this.
++       *
++       * local_daif_mask() already sets GIC_PRIO_PSR_I_SET, we just need a
++       * dsb to ensure the redistributor is forwards EL2 IRQs to the CPU.
+        */
+-      if (system_uses_irq_prio_masking()) {
+-              gic_write_pmr(GIC_PRIO_IRQON);
++      if (system_uses_irq_prio_masking())
+               dsb(sy);
+-      }
+ }
+ static inline void kvm_arm_vhe_guest_exit(void)
+--- a/arch/arm64/include/asm/ptrace.h
++++ b/arch/arm64/include/asm/ptrace.h
+@@ -24,9 +24,15 @@
+  * means masking more IRQs (or at least that the same IRQs remain masked).
+  *
+  * To mask interrupts, we clear the most significant bit of PMR.
++ *
++ * Some code sections either automatically switch back to PSR.I or explicitly
++ * require to not use priority masking. If bit GIC_PRIO_PSR_I_SET is included
++ * in the  the priority mask, it indicates that PSR.I should be set and
++ * interrupt disabling temporarily does not rely on IRQ priorities.
+  */
+-#define GIC_PRIO_IRQON                0xf0
+-#define GIC_PRIO_IRQOFF               (GIC_PRIO_IRQON & ~0x80)
++#define GIC_PRIO_IRQON                        0xc0
++#define GIC_PRIO_IRQOFF                       (GIC_PRIO_IRQON & ~0x80)
++#define GIC_PRIO_PSR_I_SET            (1 << 4)
+ /* Additional SPSR bits not exposed in the UABI */
+ #define PSR_IL_BIT            (1 << 20)
+--- a/arch/arm64/kernel/entry.S
++++ b/arch/arm64/kernel/entry.S
+@@ -247,6 +247,7 @@ alternative_else_nop_endif
+       /*
+        * Registers that may be useful after this macro is invoked:
+        *
++       * x20 - ICC_PMR_EL1
+        * x21 - aborted SP
+        * x22 - aborted PC
+        * x23 - aborted PSTATE
+@@ -438,6 +439,24 @@ alternative_endif
+       .endm
+ #endif
++      .macro  gic_prio_kentry_setup, tmp:req
++#ifdef CONFIG_ARM64_PSEUDO_NMI
++      alternative_if ARM64_HAS_IRQ_PRIO_MASKING
++      mov     \tmp, #(GIC_PRIO_PSR_I_SET | GIC_PRIO_IRQON)
++      msr_s   SYS_ICC_PMR_EL1, \tmp
++      alternative_else_nop_endif
++#endif
++      .endm
++
++      .macro  gic_prio_irq_setup, pmr:req, tmp:req
++#ifdef CONFIG_ARM64_PSEUDO_NMI
++      alternative_if ARM64_HAS_IRQ_PRIO_MASKING
++      orr     \tmp, \pmr, #GIC_PRIO_PSR_I_SET
++      msr_s   SYS_ICC_PMR_EL1, \tmp
++      alternative_else_nop_endif
++#endif
++      .endm
++
+       .text
+ /*
+@@ -616,6 +635,7 @@ el1_dbg:
+       cmp     x24, #ESR_ELx_EC_BRK64          // if BRK64
+       cinc    x24, x24, eq                    // set bit '0'
+       tbz     x24, #0, el1_inv                // EL1 only
++      gic_prio_kentry_setup tmp=x3
+       mrs     x0, far_el1
+       mov     x2, sp                          // struct pt_regs
+       bl      do_debug_exception
+@@ -633,12 +653,10 @@ ENDPROC(el1_sync)
+       .align  6
+ el1_irq:
+       kernel_entry 1
++      gic_prio_irq_setup pmr=x20, tmp=x1
+       enable_da_f
+ #ifdef CONFIG_ARM64_PSEUDO_NMI
+-alternative_if ARM64_HAS_IRQ_PRIO_MASKING
+-      ldr     x20, [sp, #S_PMR_SAVE]
+-alternative_else_nop_endif
+       test_irqs_unmasked      res=x0, pmr=x20
+       cbz     x0, 1f
+       bl      asm_nmi_enter
+@@ -668,8 +686,9 @@ alternative_else_nop_endif
+ #ifdef CONFIG_ARM64_PSEUDO_NMI
+       /*
+-       * if IRQs were disabled when we received the interrupt, we have an NMI
+-       * and we are not re-enabling interrupt upon eret. Skip tracing.
++       * When using IRQ priority masking, we can get spurious interrupts while
++       * PMR is set to GIC_PRIO_IRQOFF. An NMI might also have occurred in a
++       * section with interrupts disabled. Skip tracing in those cases.
+        */
+       test_irqs_unmasked      res=x0, pmr=x20
+       cbz     x0, 1f
+@@ -798,6 +817,7 @@ el0_ia:
+        * Instruction abort handling
+        */
+       mrs     x26, far_el1
++      gic_prio_kentry_setup tmp=x0
+       enable_da_f
+ #ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+@@ -843,6 +863,7 @@ el0_sp_pc:
+        * Stack or PC alignment exception handling
+        */
+       mrs     x26, far_el1
++      gic_prio_kentry_setup tmp=x0
+       enable_da_f
+ #ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+@@ -877,6 +898,7 @@ el0_dbg:
+        * Debug exception handling
+        */
+       tbnz    x24, #0, el0_inv                // EL0 only
++      gic_prio_kentry_setup tmp=x3
+       mrs     x0, far_el1
+       mov     x1, x25
+       mov     x2, sp
+@@ -898,7 +920,9 @@ ENDPROC(el0_sync)
+ el0_irq:
+       kernel_entry 0
+ el0_irq_naked:
++      gic_prio_irq_setup pmr=x20, tmp=x0
+       enable_da_f
++
+ #ifdef CONFIG_TRACE_IRQFLAGS
+       bl      trace_hardirqs_off
+ #endif
+@@ -920,6 +944,7 @@ ENDPROC(el0_irq)
+ el1_error:
+       kernel_entry 1
+       mrs     x1, esr_el1
++      gic_prio_kentry_setup tmp=x2
+       enable_dbg
+       mov     x0, sp
+       bl      do_serror
+@@ -930,6 +955,7 @@ el0_error:
+       kernel_entry 0
+ el0_error_naked:
+       mrs     x1, esr_el1
++      gic_prio_kentry_setup tmp=x2
+       enable_dbg
+       mov     x0, sp
+       bl      do_serror
+@@ -954,6 +980,7 @@ work_pending:
+  */
+ ret_to_user:
+       disable_daif
++      gic_prio_kentry_setup tmp=x3
+       ldr     x1, [tsk, #TSK_TI_FLAGS]
+       and     x2, x1, #_TIF_WORK_MASK
+       cbnz    x2, work_pending
+@@ -970,6 +997,7 @@ ENDPROC(ret_to_user)
+  */
+       .align  6
+ el0_svc:
++      gic_prio_kentry_setup tmp=x1
+       mov     x0, sp
+       bl      el0_svc_handler
+       b       ret_to_user
+--- a/arch/arm64/kernel/process.c
++++ b/arch/arm64/kernel/process.c
+@@ -83,7 +83,7 @@ static void __cpu_do_idle_irqprio(void)
+        * be raised.
+        */
+       pmr = gic_read_pmr();
+-      gic_write_pmr(GIC_PRIO_IRQON);
++      gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
+       __cpu_do_idle();
+--- a/arch/arm64/kernel/smp.c
++++ b/arch/arm64/kernel/smp.c
+@@ -181,11 +181,13 @@ static void init_gic_priority_masking(vo
+       WARN_ON(!(cpuflags & PSR_I_BIT));
+-      gic_write_pmr(GIC_PRIO_IRQOFF);
+-
+       /* We can only unmask PSR.I if we can take aborts */
+-      if (!(cpuflags & PSR_A_BIT))
++      if (!(cpuflags & PSR_A_BIT)) {
++              gic_write_pmr(GIC_PRIO_IRQOFF);
+               write_sysreg(cpuflags & ~PSR_I_BIT, daif);
++      } else {
++              gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
++      }
+ }
+ /*
+--- a/arch/arm64/kvm/hyp/switch.c
++++ b/arch/arm64/kvm/hyp/switch.c
+@@ -604,7 +604,7 @@ int __hyp_text __kvm_vcpu_run_nvhe(struc
+        * Naturally, we want to avoid this.
+        */
+       if (system_uses_irq_prio_masking()) {
+-              gic_write_pmr(GIC_PRIO_IRQON);
++              gic_write_pmr(GIC_PRIO_IRQON | GIC_PRIO_PSR_I_SET);
+               dsb(sy);
+       }
diff --git a/queue-5.2/arm64-irqflags-add-condition-flags-to-inline-asm-clobber-list.patch b/queue-5.2/arm64-irqflags-add-condition-flags-to-inline-asm-clobber-list.patch
new file mode 100644 (file)
index 0000000..a7e71e0
--- /dev/null
@@ -0,0 +1,46 @@
+From f57065782f245ca96f1472209a485073bbc11247 Mon Sep 17 00:00:00 2001
+From: Julien Thierry <julien.thierry@arm.com>
+Date: Tue, 11 Jun 2019 10:38:08 +0100
+Subject: arm64: irqflags: Add condition flags to inline asm clobber list
+
+From: Julien Thierry <julien.thierry@arm.com>
+
+commit f57065782f245ca96f1472209a485073bbc11247 upstream.
+
+Some of the inline assembly instruction use the condition flags and need
+to include "cc" in the clobber list.
+
+Fixes: 4a503217ce37 ("arm64: irqflags: Use ICC_PMR_EL1 for interrupt masking")
+Cc: <stable@vger.kernel.org> # 5.1.x-
+Suggested-by: Marc Zyngier <marc.zyngier@arm.com>
+Cc: Will Deacon <will.deacon@arm.com>
+Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
+Acked-by: Mark Rutland <mark.rutland@arm.com>
+Signed-off-by: Julien Thierry <julien.thierry@arm.com>
+Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/include/asm/irqflags.h |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/arch/arm64/include/asm/irqflags.h
++++ b/arch/arm64/include/asm/irqflags.h
+@@ -81,7 +81,7 @@ static inline unsigned long arch_local_s
+                       ARM64_HAS_IRQ_PRIO_MASKING)
+               : "=&r" (flags), "+r" (daif_bits)
+               : "r" ((unsigned long) GIC_PRIO_IRQOFF)
+-              : "memory");
++              : "cc", "memory");
+       return flags;
+ }
+@@ -125,7 +125,7 @@ static inline int arch_irqs_disabled_fla
+                       ARM64_HAS_IRQ_PRIO_MASKING)
+               : "=&r" (res)
+               : "r" ((int) flags)
+-              : "memory");
++              : "cc", "memory");
+       return res;
+ }
diff --git a/queue-5.2/arm64-tegra-fix-agic-register-range.patch b/queue-5.2/arm64-tegra-fix-agic-register-range.patch
new file mode 100644 (file)
index 0000000..a329a9b
--- /dev/null
@@ -0,0 +1,38 @@
+From ba24eee6686f6ed3738602b54d959253316a9541 Mon Sep 17 00:00:00 2001
+From: Jon Hunter <jonathanh@nvidia.com>
+Date: Thu, 20 Jun 2019 09:17:00 +0100
+Subject: arm64: tegra: Fix AGIC register range
+
+From: Jon Hunter <jonathanh@nvidia.com>
+
+commit ba24eee6686f6ed3738602b54d959253316a9541 upstream.
+
+The Tegra AGIC interrupt controller is an ARM GIC400 interrupt
+controller. Per the ARM GIC device-tree binding, the first address
+region is for the GIC distributor registers and the second address
+region is for the GIC CPU interface registers. The address space for
+the distributor registers is 4kB, but currently this is incorrectly
+defined as 8kB for the Tegra AGIC and overlaps with the CPU interface
+registers. Correct the address space for the distributor to be 4kB.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
+Fixes: bcdbde433542 ("arm64: tegra: Add AGIC node for Tegra210")
+Signed-off-by: Thierry Reding <treding@nvidia.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arm64/boot/dts/nvidia/tegra210.dtsi |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/arch/arm64/boot/dts/nvidia/tegra210.dtsi
++++ b/arch/arm64/boot/dts/nvidia/tegra210.dtsi
+@@ -1258,7 +1258,7 @@
+                       compatible = "nvidia,tegra210-agic";
+                       #interrupt-cells = <3>;
+                       interrupt-controller;
+-                      reg = <0x702f9000 0x2000>,
++                      reg = <0x702f9000 0x1000>,
+                             <0x702fa000 0x2000>;
+                       interrupts = <GIC_SPI 102 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+                       clocks = <&tegra_car TEGRA210_CLK_APE>;
diff --git a/queue-5.2/fs-proc-proc_sysctl.c-fix-the-default-values-of-i_uid-i_gid-on-proc-sys-inodes.patch b/queue-5.2/fs-proc-proc_sysctl.c-fix-the-default-values-of-i_uid-i_gid-on-proc-sys-inodes.patch
new file mode 100644 (file)
index 0000000..583c2c0
--- /dev/null
@@ -0,0 +1,87 @@
+From 5ec27ec735ba0477d48c80561cc5e856f0c5dfaf Mon Sep 17 00:00:00 2001
+From: Radoslaw Burny <rburny@google.com>
+Date: Tue, 16 Jul 2019 16:26:51 -0700
+Subject: fs/proc/proc_sysctl.c: fix the default values of i_uid/i_gid on /proc/sys inodes.
+
+From: Radoslaw Burny <rburny@google.com>
+
+commit 5ec27ec735ba0477d48c80561cc5e856f0c5dfaf upstream.
+
+Normally, the inode's i_uid/i_gid are translated relative to s_user_ns,
+but this is not a correct behavior for proc.  Since sysctl permission
+check in test_perm is done against GLOBAL_ROOT_[UG]ID, it makes more
+sense to use these values in u_[ug]id of proc inodes.  In other words:
+although uid/gid in the inode is not read during test_perm, the inode
+logically belongs to the root of the namespace.  I have confirmed this
+with Eric Biederman at LPC and in this thread:
+  https://lore.kernel.org/lkml/87k1kzjdff.fsf@xmission.com
+
+Consequences
+============
+
+Since the i_[ug]id values of proc nodes are not used for permissions
+checks, this change usually makes no functional difference.  However, it
+causes an issue in a setup where:
+
+ * a namespace container is created without root user in container -
+   hence the i_[ug]id of proc nodes are set to INVALID_[UG]ID
+
+ * container creator tries to configure it by writing /proc/sys files,
+   e.g. writing /proc/sys/kernel/shmmax to configure shared memory limit
+
+Kernel does not allow to open an inode for writing if its i_[ug]id are
+invalid, making it impossible to write shmmax and thus - configure the
+container.
+
+Using a container with no root mapping is apparently rare, but we do use
+this configuration at Google.  Also, we use a generic tool to configure
+the container limits, and the inability to write any of them causes a
+failure.
+
+History
+=======
+
+The invalid uids/gids in inodes first appeared due to 81754357770e (fs:
+Update i_[ug]id_(read|write) to translate relative to s_user_ns).
+However, AFAIK, this did not immediately cause any issues.  The
+inability to write to these "invalid" inodes was only caused by a later
+commit 0bd23d09b874 (vfs: Don't modify inodes with a uid or gid unknown
+to the vfs).
+
+Tested: Used a repro program that creates a user namespace without any
+mapping and stat'ed /proc/$PID/root/proc/sys/kernel/shmmax from outside.
+Before the change, it shows the overflow uid, with the change it's 0.
+The overflow uid indicates that the uid in the inode is not correct and
+thus it is not possible to open the file for writing.
+
+Link: http://lkml.kernel.org/r/20190708115130.250149-1-rburny@google.com
+Fixes: 0bd23d09b874 ("vfs: Don't modify inodes with a uid or gid unknown to the vfs")
+Signed-off-by: Radoslaw Burny <rburny@google.com>
+Acked-by: Luis Chamberlain <mcgrof@kernel.org>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: "Eric W . Biederman" <ebiederm@xmission.com>
+Cc: Seth Forshee <seth.forshee@canonical.com>
+Cc: John Sperbeck <jsperbeck@google.com>
+Cc: Alexey Dobriyan <adobriyan@gmail.com>
+Cc: <stable@vger.kernel.org>   [4.8+]
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/proc/proc_sysctl.c |    4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/fs/proc/proc_sysctl.c
++++ b/fs/proc/proc_sysctl.c
+@@ -499,6 +499,10 @@ static struct inode *proc_sys_make_inode
+       if (root->set_ownership)
+               root->set_ownership(head, table, &inode->i_uid, &inode->i_gid);
++      else {
++              inode->i_uid = GLOBAL_ROOT_UID;
++              inode->i_gid = GLOBAL_ROOT_GID;
++      }
+       return inode;
+ }
diff --git a/queue-5.2/i3c-fix-i2c-and-i3c-scl-rate-by-bus-mode.patch b/queue-5.2/i3c-fix-i2c-and-i3c-scl-rate-by-bus-mode.patch
new file mode 100644 (file)
index 0000000..7f5a31e
--- /dev/null
@@ -0,0 +1,123 @@
+From ecc8fb54bd443bf69996d9d5ddb8d90a50f14936 Mon Sep 17 00:00:00 2001
+From: Vitor Soares <Vitor.Soares@synopsys.com>
+Date: Wed, 19 Jun 2019 20:36:31 +0200
+Subject: i3c: fix i2c and i3c scl rate by bus mode
+
+From: Vitor Soares <Vitor.Soares@synopsys.com>
+
+commit ecc8fb54bd443bf69996d9d5ddb8d90a50f14936 upstream.
+
+Currently the I3C framework limits SCL frequency to FM speed when
+dealing with a mixed slow bus, even if all I2C devices are FM+ capable.
+
+The core was also not accounting for I3C speed limitations when
+operating in mixed slow mode and was erroneously using FM+ speed as the
+max I2C speed when operating in mixed fast mode.
+
+Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
+Signed-off-by: Vitor Soares <vitor.soares@synopsys.com>
+Cc: Boris Brezillon <bbrezillon@kernel.org>
+Cc: <stable@vger.kernel.org>
+Cc: <linux-kernel@vger.kernel.org>
+Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/i3c/master.c |   51 ++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 38 insertions(+), 13 deletions(-)
+
+--- a/drivers/i3c/master.c
++++ b/drivers/i3c/master.c
+@@ -91,6 +91,12 @@ void i3c_bus_normaluse_unlock(struct i3c
+       up_read(&bus->lock);
+ }
++static struct i3c_master_controller *
++i3c_bus_to_i3c_master(struct i3c_bus *i3cbus)
++{
++      return container_of(i3cbus, struct i3c_master_controller, bus);
++}
++
+ static struct i3c_master_controller *dev_to_i3cmaster(struct device *dev)
+ {
+       return container_of(dev, struct i3c_master_controller, dev);
+@@ -565,20 +571,38 @@ static const struct device_type i3c_mast
+       .groups = i3c_masterdev_groups,
+ };
+-int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode)
++int i3c_bus_set_mode(struct i3c_bus *i3cbus, enum i3c_bus_mode mode,
++                   unsigned long max_i2c_scl_rate)
+ {
+-      i3cbus->mode = mode;
++      struct i3c_master_controller *master = i3c_bus_to_i3c_master(i3cbus);
+-      if (!i3cbus->scl_rate.i3c)
+-              i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
++      i3cbus->mode = mode;
+-      if (!i3cbus->scl_rate.i2c) {
+-              if (i3cbus->mode == I3C_BUS_MODE_MIXED_SLOW)
+-                      i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE;
+-              else
+-                      i3cbus->scl_rate.i2c = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
++      switch (i3cbus->mode) {
++      case I3C_BUS_MODE_PURE:
++              if (!i3cbus->scl_rate.i3c)
++                      i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
++              break;
++      case I3C_BUS_MODE_MIXED_FAST:
++              if (!i3cbus->scl_rate.i3c)
++                      i3cbus->scl_rate.i3c = I3C_BUS_TYP_I3C_SCL_RATE;
++              if (!i3cbus->scl_rate.i2c)
++                      i3cbus->scl_rate.i2c = max_i2c_scl_rate;
++              break;
++      case I3C_BUS_MODE_MIXED_SLOW:
++              if (!i3cbus->scl_rate.i2c)
++                      i3cbus->scl_rate.i2c = max_i2c_scl_rate;
++              if (!i3cbus->scl_rate.i3c ||
++                  i3cbus->scl_rate.i3c > i3cbus->scl_rate.i2c)
++                      i3cbus->scl_rate.i3c = i3cbus->scl_rate.i2c;
++              break;
++      default:
++              return -EINVAL;
+       }
++      dev_dbg(&master->dev, "i2c-scl = %ld Hz i3c-scl = %ld Hz\n",
++              i3cbus->scl_rate.i2c, i3cbus->scl_rate.i3c);
++
+       /*
+        * I3C/I2C frequency may have been overridden, check that user-provided
+        * values are not exceeding max possible frequency.
+@@ -1966,9 +1990,6 @@ of_i3c_master_add_i2c_boardinfo(struct i
+       /* LVR is encoded in reg[2]. */
+       boardinfo->lvr = reg[2];
+-      if (boardinfo->lvr & I3C_LVR_I2C_FM_MODE)
+-              master->bus.scl_rate.i2c = I3C_BUS_I2C_FM_SCL_RATE;
+-
+       list_add_tail(&boardinfo->node, &master->boardinfo.i2c);
+       of_node_get(node);
+@@ -2417,6 +2438,7 @@ int i3c_master_register(struct i3c_maste
+                       const struct i3c_master_controller_ops *ops,
+                       bool secondary)
+ {
++      unsigned long i2c_scl_rate = I3C_BUS_I2C_FM_PLUS_SCL_RATE;
+       struct i3c_bus *i3cbus = i3c_master_get_bus(master);
+       enum i3c_bus_mode mode = I3C_BUS_MODE_PURE;
+       struct i2c_dev_boardinfo *i2cbi;
+@@ -2466,9 +2488,12 @@ int i3c_master_register(struct i3c_maste
+                       ret = -EINVAL;
+                       goto err_put_dev;
+               }
++
++              if (i2cbi->lvr & I3C_LVR_I2C_FM_MODE)
++                      i2c_scl_rate = I3C_BUS_I2C_FM_SCL_RATE;
+       }
+-      ret = i3c_bus_set_mode(i3cbus, mode);
++      ret = i3c_bus_set_mode(i3cbus, mode, i2c_scl_rate);
+       if (ret)
+               goto err_put_dev;
diff --git a/queue-5.2/intel_th-msu-fix-unused-variable-warning-on-arm64-platform.patch b/queue-5.2/intel_th-msu-fix-unused-variable-warning-on-arm64-platform.patch
new file mode 100644 (file)
index 0000000..580434f
--- /dev/null
@@ -0,0 +1,120 @@
+From b96fb368b08f1637cbf780a6b83e36c2c5ed4ff5 Mon Sep 17 00:00:00 2001
+From: Shaokun Zhang <zhangshaokun@hisilicon.com>
+Date: Fri, 21 Jun 2019 19:19:27 +0300
+Subject: intel_th: msu: Fix unused variable warning on arm64 platform
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Shaokun Zhang <zhangshaokun@hisilicon.com>
+
+commit b96fb368b08f1637cbf780a6b83e36c2c5ed4ff5 upstream.
+
+Commit ba39bd8306057 ("intel_th: msu: Switch over to scatterlist")
+introduced the following warnings on non-x86 architectures, as a result
+of reordering the multi mode buffer allocation sequence:
+
+> drivers/hwtracing/intel_th/msu.c: In function â€˜msc_buffer_win_alloc’:
+> drivers/hwtracing/intel_th/msu.c:783:21: warning: unused variable â€˜i’
+> [-Wunused-variable]
+> int ret = -ENOMEM, i;
+>                    ^
+> drivers/hwtracing/intel_th/msu.c: In function â€˜msc_buffer_win_free’:
+> drivers/hwtracing/intel_th/msu.c:863:6: warning: unused variable â€˜i’
+> [-Wunused-variable]
+> int i;
+>     ^
+
+Fix this compiler warning by factoring out set_memory sequences and making
+them x86-only.
+
+Suggested-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Signed-off-by: Shaokun Zhang <zhangshaokun@hisilicon.com>
+Fixes: ba39bd8306057 ("intel_th: msu: Switch over to scatterlist")
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20190621161930.60785-2-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hwtracing/intel_th/msu.c |   40 ++++++++++++++++++++++++++-------------
+ 1 file changed, 27 insertions(+), 13 deletions(-)
+
+--- a/drivers/hwtracing/intel_th/msu.c
++++ b/drivers/hwtracing/intel_th/msu.c
+@@ -767,6 +767,30 @@ err_nomem:
+       return -ENOMEM;
+ }
++#ifdef CONFIG_X86
++static void msc_buffer_set_uc(struct msc_window *win, unsigned int nr_blocks)
++{
++      int i;
++
++      for (i = 0; i < nr_blocks; i++)
++              /* Set the page as uncached */
++              set_memory_uc((unsigned long)msc_win_block(win, i), 1);
++}
++
++static void msc_buffer_set_wb(struct msc_window *win)
++{
++      int i;
++
++      for (i = 0; i < win->nr_blocks; i++)
++              /* Reset the page to write-back */
++              set_memory_wb((unsigned long)msc_win_block(win, i), 1);
++}
++#else /* !X86 */
++static inline void
++msc_buffer_set_uc(struct msc_window *win, unsigned int nr_blocks) {}
++static inline void msc_buffer_set_wb(struct msc_window *win) {}
++#endif /* CONFIG_X86 */
++
+ /**
+  * msc_buffer_win_alloc() - alloc a window for a multiblock mode
+  * @msc:      MSC device
+@@ -780,7 +804,7 @@ err_nomem:
+ static int msc_buffer_win_alloc(struct msc *msc, unsigned int nr_blocks)
+ {
+       struct msc_window *win;
+-      int ret = -ENOMEM, i;
++      int ret = -ENOMEM;
+       if (!nr_blocks)
+               return 0;
+@@ -811,11 +835,7 @@ static int msc_buffer_win_alloc(struct m
+       if (ret < 0)
+               goto err_nomem;
+-#ifdef CONFIG_X86
+-      for (i = 0; i < ret; i++)
+-              /* Set the page as uncached */
+-              set_memory_uc((unsigned long)msc_win_block(win, i), 1);
+-#endif
++      msc_buffer_set_uc(win, ret);
+       win->nr_blocks = ret;
+@@ -860,8 +880,6 @@ static void __msc_buffer_win_free(struct
+  */
+ static void msc_buffer_win_free(struct msc *msc, struct msc_window *win)
+ {
+-      int i;
+-
+       msc->nr_pages -= win->nr_blocks;
+       list_del(&win->entry);
+@@ -870,11 +888,7 @@ static void msc_buffer_win_free(struct m
+               msc->base_addr = 0;
+       }
+-#ifdef CONFIG_X86
+-      for (i = 0; i < win->nr_blocks; i++)
+-              /* Reset the page to write-back */
+-              set_memory_wb((unsigned long)msc_win_block(win, i), 1);
+-#endif
++      msc_buffer_set_wb(win);
+       __msc_buffer_win_free(msc, win);
index bbaee68bdbd7536a54577cb5ee7a5b619821e093..e06409bfb3cb13f2d0513f7a4f9a13c35e2a2347 100644 (file)
@@ -333,3 +333,11 @@ kvm-ppc-book3s-hv-signed-extend-decrementer-value-if-not-using-large-decrementer
 kvm-ppc-book3s-hv-clear-pending-decrementer-exceptions-on-nested-guest-entry.patch
 kvm-ppc-book3s-hv-fix-cr0-setting-in-tm-emulation.patch
 kvm-x86-vpmu-refine-kvm_pmu-err-msg-when-event-creation-failed.patch
+arm64-tegra-fix-agic-register-range.patch
+arm64-irqflags-add-condition-flags-to-inline-asm-clobber-list.patch
+arm64-fix-incorrect-irqflag-restore-for-priority-masking.patch
+intel_th-msu-fix-unused-variable-warning-on-arm64-platform.patch
+signal-usb-replace-kill_pid_info_as_cred-with-kill_pid_usb_asyncio.patch
+signal-correct-namespace-fixups-of-si_pid-and-si_uid.patch
+fs-proc-proc_sysctl.c-fix-the-default-values-of-i_uid-i_gid-on-proc-sys-inodes.patch
+i3c-fix-i2c-and-i3c-scl-rate-by-bus-mode.patch
diff --git a/queue-5.2/signal-correct-namespace-fixups-of-si_pid-and-si_uid.patch b/queue-5.2/signal-correct-namespace-fixups-of-si_pid-and-si_uid.patch
new file mode 100644 (file)
index 0000000..b4e95aa
--- /dev/null
@@ -0,0 +1,142 @@
+From 7a0cf094944e2540758b7f957eb6846d5126f535 Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Wed, 15 May 2019 22:54:56 -0500
+Subject: signal: Correct namespace fixups of si_pid and si_uid
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 7a0cf094944e2540758b7f957eb6846d5126f535 upstream.
+
+The function send_signal was split from __send_signal so that it would
+be possible to bypass the namespace logic based upon current[1].  As it
+turns out the si_pid and the si_uid fixup are both inappropriate in
+the case of kill_pid_usb_asyncio so move that logic into send_signal.
+
+It is difficult to arrange but possible for a signal with an si_code
+of SI_TIMER or SI_SIGIO to be sent across namespace boundaries.  In
+which case tests for when it is ok to change si_pid and si_uid based
+on SI_FROMUSER are incorrect.  Replace the use of SI_FROMUSER with a
+new test has_si_pid_and_used based on siginfo_layout.
+
+Now that the uid fixup is no longer present after expanding
+SEND_SIG_NOINFO properly calculate the si_uid that the target
+task needs to read.
+
+[1] 7978b567d315 ("signals: add from_ancestor_ns parameter to send_signal()")
+Cc: stable@vger.kernel.org
+Fixes: 6588c1e3ff01 ("signals: SI_USER: Masquerade si_pid when crossing pid ns boundary")
+Fixes: 6b550f949594 ("user namespace: make signal.c respect user namespaces")
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/signal.c |   67 +++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 40 insertions(+), 27 deletions(-)
+
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1057,27 +1057,6 @@ static inline bool legacy_queue(struct s
+       return (sig < SIGRTMIN) && sigismember(&signals->signal, sig);
+ }
+-#ifdef CONFIG_USER_NS
+-static inline void userns_fixup_signal_uid(struct kernel_siginfo *info, struct task_struct *t)
+-{
+-      if (current_user_ns() == task_cred_xxx(t, user_ns))
+-              return;
+-
+-      if (SI_FROMKERNEL(info))
+-              return;
+-
+-      rcu_read_lock();
+-      info->si_uid = from_kuid_munged(task_cred_xxx(t, user_ns),
+-                                      make_kuid(current_user_ns(), info->si_uid));
+-      rcu_read_unlock();
+-}
+-#else
+-static inline void userns_fixup_signal_uid(struct kernel_siginfo *info, struct task_struct *t)
+-{
+-      return;
+-}
+-#endif
+-
+ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
+                       enum pid_type type, int from_ancestor_ns)
+ {
+@@ -1135,7 +1114,11 @@ static int __send_signal(int sig, struct
+                       q->info.si_code = SI_USER;
+                       q->info.si_pid = task_tgid_nr_ns(current,
+                                                       task_active_pid_ns(t));
+-                      q->info.si_uid = from_kuid_munged(current_user_ns(), current_uid());
++                      rcu_read_lock();
++                      q->info.si_uid =
++                              from_kuid_munged(task_cred_xxx(t, user_ns),
++                                               current_uid());
++                      rcu_read_unlock();
+                       break;
+               case (unsigned long) SEND_SIG_PRIV:
+                       clear_siginfo(&q->info);
+@@ -1147,13 +1130,8 @@ static int __send_signal(int sig, struct
+                       break;
+               default:
+                       copy_siginfo(&q->info, info);
+-                      if (from_ancestor_ns)
+-                              q->info.si_pid = 0;
+                       break;
+               }
+-
+-              userns_fixup_signal_uid(&q->info, t);
+-
+       } else if (!is_si_special(info)) {
+               if (sig >= SIGRTMIN && info->si_code != SI_USER) {
+                       /*
+@@ -1197,6 +1175,28 @@ ret:
+       return ret;
+ }
++static inline bool has_si_pid_and_uid(struct kernel_siginfo *info)
++{
++      bool ret = false;
++      switch (siginfo_layout(info->si_signo, info->si_code)) {
++      case SIL_KILL:
++      case SIL_CHLD:
++      case SIL_RT:
++              ret = true;
++              break;
++      case SIL_TIMER:
++      case SIL_POLL:
++      case SIL_FAULT:
++      case SIL_FAULT_MCEERR:
++      case SIL_FAULT_BNDERR:
++      case SIL_FAULT_PKUERR:
++      case SIL_SYS:
++              ret = false;
++              break;
++      }
++      return ret;
++}
++
+ static int send_signal(int sig, struct kernel_siginfo *info, struct task_struct *t,
+                       enum pid_type type)
+ {
+@@ -1206,7 +1206,20 @@ static int send_signal(int sig, struct k
+       from_ancestor_ns = si_fromuser(info) &&
+                          !task_pid_nr_ns(current, task_active_pid_ns(t));
+ #endif
++      if (!is_si_special(info) && has_si_pid_and_uid(info)) {
++              struct user_namespace *t_user_ns;
++
++              rcu_read_lock();
++              t_user_ns = task_cred_xxx(t, user_ns);
++              if (current_user_ns() != t_user_ns) {
++                      kuid_t uid = make_kuid(current_user_ns(), info->si_uid);
++                      info->si_uid = from_kuid_munged(t_user_ns, uid);
++              }
++              rcu_read_unlock();
++              if (!task_pid_nr_ns(current, task_active_pid_ns(t)))
++                      info->si_pid = 0;
++      }
+       return __send_signal(sig, info, t, type, from_ancestor_ns);
+ }
diff --git a/queue-5.2/signal-usb-replace-kill_pid_info_as_cred-with-kill_pid_usb_asyncio.patch b/queue-5.2/signal-usb-replace-kill_pid_info_as_cred-with-kill_pid_usb_asyncio.patch
new file mode 100644 (file)
index 0000000..1caeda6
--- /dev/null
@@ -0,0 +1,458 @@
+From 70f1b0d34bdf03065fe869e93cc17cad1ea20c4a Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Thu, 7 Feb 2019 19:44:12 -0600
+Subject: signal/usb: Replace kill_pid_info_as_cred with kill_pid_usb_asyncio
+
+From: Eric W. Biederman <ebiederm@xmission.com>
+
+commit 70f1b0d34bdf03065fe869e93cc17cad1ea20c4a upstream.
+
+The usb support for asyncio encoded one of it's values in the wrong
+field.  It should have used si_value but instead used si_addr which is
+not present in the _rt union member of struct siginfo.
+
+The practical result of this is that on a 64bit big endian kernel
+when delivering a signal to a 32bit process the si_addr field
+is set to NULL, instead of the expected pointer value.
+
+This issue can not be fixed in copy_siginfo_to_user32 as the usb
+usage of the the _sigfault (aka si_addr) member of the siginfo
+union when SI_ASYNCIO is set is incompatible with the POSIX and
+glibc usage of the _rt member of the siginfo union.
+
+Therefore replace kill_pid_info_as_cred with kill_pid_usb_asyncio a
+dedicated function for this one specific case.  There are no other
+users of kill_pid_info_as_cred so this specialization should have no
+impact on the amount of code in the kernel.  Have kill_pid_usb_asyncio
+take instead of a siginfo_t which is difficult and error prone, 3
+arguments, a signal number, an errno value, and an address enconded as
+a sigval_t.  The encoding of the address as a sigval_t allows the
+code that reads the userspace request for a signal to handle this
+compat issue along with all of the other compat issues.
+
+Add BUILD_BUG_ONs in kernel/signal.c to ensure that we can now place
+the pointer value at the in si_pid (instead of si_addr).  That is the
+code now verifies that si_pid and si_addr always occur at the same
+location.  Further the code veries that for native structures a value
+placed in si_pid and spilling into si_uid will appear in userspace in
+si_addr (on a byte by byte copy of siginfo or a field by field copy of
+siginfo).  The code also verifies that for a 64bit kernel and a 32bit
+userspace the 32bit pointer will fit in si_pid.
+
+I have used the usbsig.c program below written by Alan Stern and
+slightly tweaked by me to run on a big endian machine to verify the
+issue exists (on sparc64) and to confirm the patch below fixes the issue.
+
+ /* usbsig.c -- test USB async signal delivery */
+
+ #define _GNU_SOURCE
+ #include <stdio.h>
+ #include <fcntl.h>
+ #include <signal.h>
+ #include <string.h>
+ #include <sys/ioctl.h>
+ #include <unistd.h>
+ #include <endian.h>
+ #include <linux/usb/ch9.h>
+ #include <linux/usbdevice_fs.h>
+
+ static struct usbdevfs_urb urb;
+ static struct usbdevfs_disconnectsignal ds;
+ static volatile sig_atomic_t done = 0;
+
+ void urb_handler(int sig, siginfo_t *info , void *ucontext)
+ {
+       printf("Got signal %d, signo %d errno %d code %d addr: %p urb: %p\n",
+              sig, info->si_signo, info->si_errno, info->si_code,
+              info->si_addr, &urb);
+
+       printf("%s\n", (info->si_addr == &urb) ? "Good" : "Bad");
+ }
+
+ void ds_handler(int sig, siginfo_t *info , void *ucontext)
+ {
+       printf("Got signal %d, signo %d errno %d code %d addr: %p ds: %p\n",
+              sig, info->si_signo, info->si_errno, info->si_code,
+              info->si_addr, &ds);
+
+       printf("%s\n", (info->si_addr == &ds) ? "Good" : "Bad");
+       done = 1;
+ }
+
+ int main(int argc, char **argv)
+ {
+       char *devfilename;
+       int fd;
+       int rc;
+       struct sigaction act;
+       struct usb_ctrlrequest *req;
+       void *ptr;
+       char buf[80];
+
+       if (argc != 2) {
+               fprintf(stderr, "Usage: usbsig device-file-name\n");
+               return 1;
+       }
+
+       devfilename = argv[1];
+       fd = open(devfilename, O_RDWR);
+       if (fd == -1) {
+               perror("Error opening device file");
+               return 1;
+       }
+
+       act.sa_sigaction = urb_handler;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = SA_SIGINFO;
+
+       rc = sigaction(SIGUSR1, &act, NULL);
+       if (rc == -1) {
+               perror("Error in sigaction");
+               return 1;
+       }
+
+       act.sa_sigaction = ds_handler;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = SA_SIGINFO;
+
+       rc = sigaction(SIGUSR2, &act, NULL);
+       if (rc == -1) {
+               perror("Error in sigaction");
+               return 1;
+       }
+
+       memset(&urb, 0, sizeof(urb));
+       urb.type = USBDEVFS_URB_TYPE_CONTROL;
+       urb.endpoint = USB_DIR_IN | 0;
+       urb.buffer = buf;
+       urb.buffer_length = sizeof(buf);
+       urb.signr = SIGUSR1;
+
+       req = (struct usb_ctrlrequest *) buf;
+       req->bRequestType = USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE;
+       req->bRequest = USB_REQ_GET_DESCRIPTOR;
+       req->wValue = htole16(USB_DT_DEVICE << 8);
+       req->wIndex = htole16(0);
+       req->wLength = htole16(sizeof(buf) - sizeof(*req));
+
+       rc = ioctl(fd, USBDEVFS_SUBMITURB, &urb);
+       if (rc == -1) {
+               perror("Error in SUBMITURB ioctl");
+               return 1;
+       }
+
+       rc = ioctl(fd, USBDEVFS_REAPURB, &ptr);
+       if (rc == -1) {
+               perror("Error in REAPURB ioctl");
+               return 1;
+       }
+
+       memset(&ds, 0, sizeof(ds));
+       ds.signr = SIGUSR2;
+       ds.context = &ds;
+       rc = ioctl(fd, USBDEVFS_DISCSIGNAL, &ds);
+       if (rc == -1) {
+               perror("Error in DISCSIGNAL ioctl");
+               return 1;
+       }
+
+       printf("Waiting for usb disconnect\n");
+       while (!done) {
+               sleep(1);
+       }
+
+       close(fd);
+       return 0;
+ }
+
+Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: linux-usb@vger.kernel.org
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Oliver Neukum <oneukum@suse.com>
+Fixes: v2.3.39
+Cc: stable@vger.kernel.org
+Acked-by: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/usb/core/devio.c     |   48 ++++++++++++++---------------
+ include/linux/sched/signal.h |    2 -
+ kernel/signal.c              |   69 ++++++++++++++++++++++++++++++++++++++-----
+ 3 files changed, 86 insertions(+), 33 deletions(-)
+
+--- a/drivers/usb/core/devio.c
++++ b/drivers/usb/core/devio.c
+@@ -63,7 +63,7 @@ struct usb_dev_state {
+       unsigned int discsignr;
+       struct pid *disc_pid;
+       const struct cred *cred;
+-      void __user *disccontext;
++      sigval_t disccontext;
+       unsigned long ifclaimed;
+       u32 disabled_bulk_eps;
+       bool privileges_dropped;
+@@ -90,6 +90,7 @@ struct async {
+       unsigned int ifnum;
+       void __user *userbuffer;
+       void __user *userurb;
++      sigval_t userurb_sigval;
+       struct urb *urb;
+       struct usb_memory *usbm;
+       unsigned int mem_usage;
+@@ -582,22 +583,19 @@ static void async_completed(struct urb *
+ {
+       struct async *as = urb->context;
+       struct usb_dev_state *ps = as->ps;
+-      struct kernel_siginfo sinfo;
+       struct pid *pid = NULL;
+       const struct cred *cred = NULL;
+       unsigned long flags;
+-      int signr;
++      sigval_t addr;
++      int signr, errno;
+       spin_lock_irqsave(&ps->lock, flags);
+       list_move_tail(&as->asynclist, &ps->async_completed);
+       as->status = urb->status;
+       signr = as->signr;
+       if (signr) {
+-              clear_siginfo(&sinfo);
+-              sinfo.si_signo = as->signr;
+-              sinfo.si_errno = as->status;
+-              sinfo.si_code = SI_ASYNCIO;
+-              sinfo.si_addr = as->userurb;
++              errno = as->status;
++              addr = as->userurb_sigval;
+               pid = get_pid(as->pid);
+               cred = get_cred(as->cred);
+       }
+@@ -615,7 +613,7 @@ static void async_completed(struct urb *
+       spin_unlock_irqrestore(&ps->lock, flags);
+       if (signr) {
+-              kill_pid_info_as_cred(sinfo.si_signo, &sinfo, pid, cred);
++              kill_pid_usb_asyncio(signr, errno, addr, pid, cred);
+               put_pid(pid);
+               put_cred(cred);
+       }
+@@ -1427,7 +1425,7 @@ find_memory_area(struct usb_dev_state *p
+ static int proc_do_submiturb(struct usb_dev_state *ps, struct usbdevfs_urb *uurb,
+                       struct usbdevfs_iso_packet_desc __user *iso_frame_desc,
+-                      void __user *arg)
++                      void __user *arg, sigval_t userurb_sigval)
+ {
+       struct usbdevfs_iso_packet_desc *isopkt = NULL;
+       struct usb_host_endpoint *ep;
+@@ -1727,6 +1725,7 @@ static int proc_do_submiturb(struct usb_
+       isopkt = NULL;
+       as->ps = ps;
+       as->userurb = arg;
++      as->userurb_sigval = userurb_sigval;
+       if (as->usbm) {
+               unsigned long uurb_start = (unsigned long)uurb->buffer;
+@@ -1801,13 +1800,17 @@ static int proc_do_submiturb(struct usb_
+ static int proc_submiturb(struct usb_dev_state *ps, void __user *arg)
+ {
+       struct usbdevfs_urb uurb;
++      sigval_t userurb_sigval;
+       if (copy_from_user(&uurb, arg, sizeof(uurb)))
+               return -EFAULT;
++      memset(&userurb_sigval, 0, sizeof(userurb_sigval));
++      userurb_sigval.sival_ptr = arg;
++
+       return proc_do_submiturb(ps, &uurb,
+                       (((struct usbdevfs_urb __user *)arg)->iso_frame_desc),
+-                      arg);
++                      arg, userurb_sigval);
+ }
+ static int proc_unlinkurb(struct usb_dev_state *ps, void __user *arg)
+@@ -1977,7 +1980,7 @@ static int proc_disconnectsignal_compat(
+       if (copy_from_user(&ds, arg, sizeof(ds)))
+               return -EFAULT;
+       ps->discsignr = ds.signr;
+-      ps->disccontext = compat_ptr(ds.context);
++      ps->disccontext.sival_int = ds.context;
+       return 0;
+ }
+@@ -2005,13 +2008,17 @@ static int get_urb32(struct usbdevfs_urb
+ static int proc_submiturb_compat(struct usb_dev_state *ps, void __user *arg)
+ {
+       struct usbdevfs_urb uurb;
++      sigval_t userurb_sigval;
+       if (get_urb32(&uurb, (struct usbdevfs_urb32 __user *)arg))
+               return -EFAULT;
++      memset(&userurb_sigval, 0, sizeof(userurb_sigval));
++      userurb_sigval.sival_int = ptr_to_compat(arg);
++
+       return proc_do_submiturb(ps, &uurb,
+                       ((struct usbdevfs_urb32 __user *)arg)->iso_frame_desc,
+-                      arg);
++                      arg, userurb_sigval);
+ }
+ static int processcompl_compat(struct async *as, void __user * __user *arg)
+@@ -2092,7 +2099,7 @@ static int proc_disconnectsignal(struct
+       if (copy_from_user(&ds, arg, sizeof(ds)))
+               return -EFAULT;
+       ps->discsignr = ds.signr;
+-      ps->disccontext = ds.context;
++      ps->disccontext.sival_ptr = ds.context;
+       return 0;
+ }
+@@ -2614,22 +2621,15 @@ const struct file_operations usbdev_file
+ static void usbdev_remove(struct usb_device *udev)
+ {
+       struct usb_dev_state *ps;
+-      struct kernel_siginfo sinfo;
+       while (!list_empty(&udev->filelist)) {
+               ps = list_entry(udev->filelist.next, struct usb_dev_state, list);
+               destroy_all_async(ps);
+               wake_up_all(&ps->wait);
+               list_del_init(&ps->list);
+-              if (ps->discsignr) {
+-                      clear_siginfo(&sinfo);
+-                      sinfo.si_signo = ps->discsignr;
+-                      sinfo.si_errno = EPIPE;
+-                      sinfo.si_code = SI_ASYNCIO;
+-                      sinfo.si_addr = ps->disccontext;
+-                      kill_pid_info_as_cred(ps->discsignr, &sinfo,
+-                                      ps->disc_pid, ps->cred);
+-              }
++              if (ps->discsignr)
++                      kill_pid_usb_asyncio(ps->discsignr, EPIPE, ps->disccontext,
++                                           ps->disc_pid, ps->cred);
+       }
+ }
+--- a/include/linux/sched/signal.h
++++ b/include/linux/sched/signal.h
+@@ -329,7 +329,7 @@ extern void force_sigsegv(int sig, struc
+ extern int force_sig_info(int, struct kernel_siginfo *, struct task_struct *);
+ extern int __kill_pgrp_info(int sig, struct kernel_siginfo *info, struct pid *pgrp);
+ extern int kill_pid_info(int sig, struct kernel_siginfo *info, struct pid *pid);
+-extern int kill_pid_info_as_cred(int, struct kernel_siginfo *, struct pid *,
++extern int kill_pid_usb_asyncio(int sig, int errno, sigval_t addr, struct pid *,
+                               const struct cred *);
+ extern int kill_pgrp(struct pid *pid, int sig, int priv);
+ extern int kill_pid(struct pid *pid, int sig, int priv);
+--- a/kernel/signal.c
++++ b/kernel/signal.c
+@@ -1440,13 +1440,44 @@ static inline bool kill_as_cred_perm(con
+              uid_eq(cred->uid, pcred->uid);
+ }
+-/* like kill_pid_info(), but doesn't use uid/euid of "current" */
+-int kill_pid_info_as_cred(int sig, struct kernel_siginfo *info, struct pid *pid,
+-                       const struct cred *cred)
++/*
++ * The usb asyncio usage of siginfo is wrong.  The glibc support
++ * for asyncio which uses SI_ASYNCIO assumes the layout is SIL_RT.
++ * AKA after the generic fields:
++ *    kernel_pid_t    si_pid;
++ *    kernel_uid32_t  si_uid;
++ *    sigval_t        si_value;
++ *
++ * Unfortunately when usb generates SI_ASYNCIO it assumes the layout
++ * after the generic fields is:
++ *    void __user     *si_addr;
++ *
++ * This is a practical problem when there is a 64bit big endian kernel
++ * and a 32bit userspace.  As the 32bit address will encoded in the low
++ * 32bits of the pointer.  Those low 32bits will be stored at higher
++ * address than appear in a 32 bit pointer.  So userspace will not
++ * see the address it was expecting for it's completions.
++ *
++ * There is nothing in the encoding that can allow
++ * copy_siginfo_to_user32 to detect this confusion of formats, so
++ * handle this by requiring the caller of kill_pid_usb_asyncio to
++ * notice when this situration takes place and to store the 32bit
++ * pointer in sival_int, instead of sival_addr of the sigval_t addr
++ * parameter.
++ */
++int kill_pid_usb_asyncio(int sig, int errno, sigval_t addr,
++                       struct pid *pid, const struct cred *cred)
+ {
+-      int ret = -EINVAL;
++      struct kernel_siginfo info;
+       struct task_struct *p;
+       unsigned long flags;
++      int ret = -EINVAL;
++
++      clear_siginfo(&info);
++      info.si_signo = sig;
++      info.si_errno = errno;
++      info.si_code = SI_ASYNCIO;
++      *((sigval_t *)&info.si_pid) = addr;
+       if (!valid_signal(sig))
+               return ret;
+@@ -1457,17 +1488,17 @@ int kill_pid_info_as_cred(int sig, struc
+               ret = -ESRCH;
+               goto out_unlock;
+       }
+-      if (si_fromuser(info) && !kill_as_cred_perm(cred, p)) {
++      if (!kill_as_cred_perm(cred, p)) {
+               ret = -EPERM;
+               goto out_unlock;
+       }
+-      ret = security_task_kill(p, info, sig, cred);
++      ret = security_task_kill(p, &info, sig, cred);
+       if (ret)
+               goto out_unlock;
+       if (sig) {
+               if (lock_task_sighand(p, &flags)) {
+-                      ret = __send_signal(sig, info, p, PIDTYPE_TGID, 0);
++                      ret = __send_signal(sig, &info, p, PIDTYPE_TGID, 0);
+                       unlock_task_sighand(p, &flags);
+               } else
+                       ret = -ESRCH;
+@@ -1476,7 +1507,7 @@ out_unlock:
+       rcu_read_unlock();
+       return ret;
+ }
+-EXPORT_SYMBOL_GPL(kill_pid_info_as_cred);
++EXPORT_SYMBOL_GPL(kill_pid_usb_asyncio);
+ /*
+  * kill_something_info() interprets pid in interesting ways just like kill(2).
+@@ -4477,6 +4508,28 @@ static inline void siginfo_buildtime_che
+       CHECK_OFFSET(si_syscall);
+       CHECK_OFFSET(si_arch);
+ #undef CHECK_OFFSET
++
++      /* usb asyncio */
++      BUILD_BUG_ON(offsetof(struct siginfo, si_pid) !=
++                   offsetof(struct siginfo, si_addr));
++      if (sizeof(int) == sizeof(void __user *)) {
++              BUILD_BUG_ON(sizeof_field(struct siginfo, si_pid) !=
++                           sizeof(void __user *));
++      } else {
++              BUILD_BUG_ON((sizeof_field(struct siginfo, si_pid) +
++                            sizeof_field(struct siginfo, si_uid)) !=
++                           sizeof(void __user *));
++              BUILD_BUG_ON(offsetofend(struct siginfo, si_pid) !=
++                           offsetof(struct siginfo, si_uid));
++      }
++#ifdef CONFIG_COMPAT
++      BUILD_BUG_ON(offsetof(struct compat_siginfo, si_pid) !=
++                   offsetof(struct compat_siginfo, si_addr));
++      BUILD_BUG_ON(sizeof_field(struct compat_siginfo, si_pid) !=
++                   sizeof(compat_uptr_t));
++      BUILD_BUG_ON(sizeof_field(struct compat_siginfo, si_pid) !=
++                   sizeof_field(struct siginfo, si_pid));
++#endif
+ }
+ void __init signals_init(void)