]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Mar 2020 13:16:42 +0000 (14:16 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 16 Mar 2020 13:16:42 +0000 (14:16 +0100)
added patches:
arc-define-__align_str-and-__align-symbols-for-arc.patch
efi-fix-a-race-and-a-buffer-overflow-while-reading-efivars-via-sysfs.patch
gfs2_atomic_open-fix-o_excl-o_creat-handling-on-cold-dcache.patch
iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint.patch
iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page.patch
kvm-x86-clear-stale-x86_emulate_ctxt-intercept-value.patch

queue-4.4/arc-define-__align_str-and-__align-symbols-for-arc.patch [new file with mode: 0644]
queue-4.4/efi-fix-a-race-and-a-buffer-overflow-while-reading-efivars-via-sysfs.patch [new file with mode: 0644]
queue-4.4/gfs2_atomic_open-fix-o_excl-o_creat-handling-on-cold-dcache.patch [new file with mode: 0644]
queue-4.4/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint.patch [new file with mode: 0644]
queue-4.4/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page.patch [new file with mode: 0644]
queue-4.4/kvm-x86-clear-stale-x86_emulate_ctxt-intercept-value.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/arc-define-__align_str-and-__align-symbols-for-arc.patch b/queue-4.4/arc-define-__align_str-and-__align-symbols-for-arc.patch
new file mode 100644 (file)
index 0000000..f079f3d
--- /dev/null
@@ -0,0 +1,35 @@
+From 8d92e992a785f35d23f845206cf8c6cafbc264e0 Mon Sep 17 00:00:00 2001
+From: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+Date: Wed, 11 Mar 2020 19:26:43 +0300
+Subject: ARC: define __ALIGN_STR and __ALIGN symbols for ARC
+
+From: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+
+commit 8d92e992a785f35d23f845206cf8c6cafbc264e0 upstream.
+
+The default defintions use fill pattern 0x90 for padding which for ARC
+generates unintended "ldh_s r12,[r0,0x20]" corresponding to opcode 0x9090
+
+So use ".align 4" which insert a "nop_s" instruction instead.
+
+Cc: stable@vger.kernel.org
+Acked-by: Vineet Gupta <vgupta@synopsys.com>
+Signed-off-by: Eugeniy Paltsev <Eugeniy.Paltsev@synopsys.com>
+Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/arc/include/asm/linkage.h |    2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/arch/arc/include/asm/linkage.h
++++ b/arch/arc/include/asm/linkage.h
+@@ -12,6 +12,8 @@
+ #ifdef __ASSEMBLY__
+ #define ASM_NL                 `      /* use '`' to mark new line in macro */
++#define __ALIGN               .align 4
++#define __ALIGN_STR   __stringify(__ALIGN)
+ /* annotation for data we want in DCCM - if enabled in .config */
+ .macro ARCFP_DATA nm
diff --git a/queue-4.4/efi-fix-a-race-and-a-buffer-overflow-while-reading-efivars-via-sysfs.patch b/queue-4.4/efi-fix-a-race-and-a-buffer-overflow-while-reading-efivars-via-sysfs.patch
new file mode 100644 (file)
index 0000000..5790803
--- /dev/null
@@ -0,0 +1,138 @@
+From 286d3250c9d6437340203fb64938bea344729a0e Mon Sep 17 00:00:00 2001
+From: Vladis Dronov <vdronov@redhat.com>
+Date: Sun, 8 Mar 2020 09:08:54 +0100
+Subject: efi: Fix a race and a buffer overflow while reading efivars via sysfs
+
+From: Vladis Dronov <vdronov@redhat.com>
+
+commit 286d3250c9d6437340203fb64938bea344729a0e upstream.
+
+There is a race and a buffer overflow corrupting a kernel memory while
+reading an EFI variable with a size more than 1024 bytes via the older
+sysfs method. This happens because accessing struct efi_variable in
+efivar_{attr,size,data}_read() and friends is not protected from
+a concurrent access leading to a kernel memory corruption and, at best,
+to a crash. The race scenario is the following:
+
+CPU0:                                CPU1:
+efivar_attr_read()
+  var->DataSize = 1024;
+  efivar_entry_get(... &var->DataSize)
+    down_interruptible(&efivars_lock)
+                                     efivar_attr_read() // same EFI var
+                                       var->DataSize = 1024;
+                                       efivar_entry_get(... &var->DataSize)
+                                         down_interruptible(&efivars_lock)
+    virt_efi_get_variable()
+    // returns EFI_BUFFER_TOO_SMALL but
+    // var->DataSize is set to a real
+    // var size more than 1024 bytes
+    up(&efivars_lock)
+                                         virt_efi_get_variable()
+                                         // called with var->DataSize set
+                                         // to a real var size, returns
+                                         // successfully and overwrites
+                                         // a 1024-bytes kernel buffer
+                                         up(&efivars_lock)
+
+This can be reproduced by concurrent reading of an EFI variable which size
+is more than 1024 bytes:
+
+  ts# for cpu in $(seq 0 $(nproc --ignore=1)); do ( taskset -c $cpu \
+  cat /sys/firmware/efi/vars/KEKDefault*/size & ) ; done
+
+Fix this by using a local variable for a var's data buffer size so it
+does not get overwritten.
+
+Fixes: e14ab23dde12b80d ("efivars: efivar_entry API")
+Reported-by: Bob Sanders <bob.sanders@hpe.com> and the LTP testsuite
+Signed-off-by: Vladis Dronov <vdronov@redhat.com>
+Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
+Signed-off-by: Ingo Molnar <mingo@kernel.org>
+Cc: <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20200305084041.24053-2-vdronov@redhat.com
+Link: https://lore.kernel.org/r/20200308080859.21568-24-ardb@kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/firmware/efi/efivars.c |   29 ++++++++++++++++++++---------
+ 1 file changed, 20 insertions(+), 9 deletions(-)
+
+--- a/drivers/firmware/efi/efivars.c
++++ b/drivers/firmware/efi/efivars.c
+@@ -139,13 +139,16 @@ static ssize_t
+ efivar_attr_read(struct efivar_entry *entry, char *buf)
+ {
+       struct efi_variable *var = &entry->var;
++      unsigned long size = sizeof(var->Data);
+       char *str = buf;
++      int ret;
+       if (!entry || !buf)
+               return -EINVAL;
+-      var->DataSize = 1024;
+-      if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
++      ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
++      var->DataSize = size;
++      if (ret)
+               return -EIO;
+       if (var->Attributes & EFI_VARIABLE_NON_VOLATILE)
+@@ -172,13 +175,16 @@ static ssize_t
+ efivar_size_read(struct efivar_entry *entry, char *buf)
+ {
+       struct efi_variable *var = &entry->var;
++      unsigned long size = sizeof(var->Data);
+       char *str = buf;
++      int ret;
+       if (!entry || !buf)
+               return -EINVAL;
+-      var->DataSize = 1024;
+-      if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
++      ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
++      var->DataSize = size;
++      if (ret)
+               return -EIO;
+       str += sprintf(str, "0x%lx\n", var->DataSize);
+@@ -189,12 +195,15 @@ static ssize_t
+ efivar_data_read(struct efivar_entry *entry, char *buf)
+ {
+       struct efi_variable *var = &entry->var;
++      unsigned long size = sizeof(var->Data);
++      int ret;
+       if (!entry || !buf)
+               return -EINVAL;
+-      var->DataSize = 1024;
+-      if (efivar_entry_get(entry, &var->Attributes, &var->DataSize, var->Data))
++      ret = efivar_entry_get(entry, &var->Attributes, &size, var->Data);
++      var->DataSize = size;
++      if (ret)
+               return -EIO;
+       memcpy(buf, var->Data, var->DataSize);
+@@ -314,14 +323,16 @@ efivar_show_raw(struct efivar_entry *ent
+ {
+       struct efi_variable *var = &entry->var;
+       struct compat_efi_variable *compat;
++      unsigned long datasize = sizeof(var->Data);
+       size_t size;
++      int ret;
+       if (!entry || !buf)
+               return 0;
+-      var->DataSize = 1024;
+-      if (efivar_entry_get(entry, &entry->var.Attributes,
+-                           &entry->var.DataSize, entry->var.Data))
++      ret = efivar_entry_get(entry, &var->Attributes, &datasize, var->Data);
++      var->DataSize = datasize;
++      if (ret)
+               return -EIO;
+       if (is_compat()) {
diff --git a/queue-4.4/gfs2_atomic_open-fix-o_excl-o_creat-handling-on-cold-dcache.patch b/queue-4.4/gfs2_atomic_open-fix-o_excl-o_creat-handling-on-cold-dcache.patch
new file mode 100644 (file)
index 0000000..3e74c81
--- /dev/null
@@ -0,0 +1,34 @@
+From 21039132650281de06a169cbe8a0f7e5c578fd8b Mon Sep 17 00:00:00 2001
+From: Al Viro <viro@zeniv.linux.org.uk>
+Date: Tue, 10 Mar 2020 09:31:41 -0400
+Subject: gfs2_atomic_open(): fix O_EXCL|O_CREAT handling on cold dcache
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+commit 21039132650281de06a169cbe8a0f7e5c578fd8b upstream.
+
+with the way fs/namei.c:do_last() had been done, ->atomic_open()
+instances needed to recognize the case when existing file got
+found with O_EXCL|O_CREAT, either by falling back to finish_no_open()
+or failing themselves.  gfs2 one didn't.
+
+Fixes: 6d4ade986f9c (GFS2: Add atomic_open support)
+Cc: stable@kernel.org # v3.11
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/gfs2/inode.c |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/fs/gfs2/inode.c
++++ b/fs/gfs2/inode.c
+@@ -1245,7 +1245,7 @@ static int gfs2_atomic_open(struct inode
+               if (!(*opened & FILE_OPENED))
+                       return finish_no_open(file, d);
+               dput(d);
+-              return 0;
++              return excl && (flags & O_CREAT) ? -EEXIST : 0;
+       }
+       BUG_ON(d != NULL);
diff --git a/queue-4.4/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint.patch b/queue-4.4/iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint.patch
new file mode 100644 (file)
index 0000000..16c2dce
--- /dev/null
@@ -0,0 +1,100 @@
+From 59833696442c674acbbd297772ba89e7ad8c753d Mon Sep 17 00:00:00 2001
+From: Hans de Goede <hdegoede@redhat.com>
+Date: Mon, 9 Mar 2020 15:01:37 +0100
+Subject: iommu/vt-d: dmar: replace WARN_TAINT with pr_warn + add_taint
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 59833696442c674acbbd297772ba89e7ad8c753d upstream.
+
+Quoting from the comment describing the WARN functions in
+include/asm-generic/bug.h:
+
+ * WARN(), WARN_ON(), WARN_ON_ONCE, and so on can be used to report
+ * significant kernel issues that need prompt attention if they should ever
+ * appear at runtime.
+ *
+ * Do not use these macros when checking for invalid external inputs
+
+The (buggy) firmware tables which the dmar code was calling WARN_TAINT
+for really are invalid external inputs. They are not under the kernel's
+control and the issues in them cannot be fixed by a kernel update.
+So logging a backtrace, which invites bug reports to be filed about this,
+is not helpful.
+
+Some distros, e.g. Fedora, have tools watching for the kernel backtraces
+logged by the WARN macros and offer the user an option to file a bug for
+this when these are encountered. The WARN_TAINT in warn_invalid_dmar()
++ another iommu WARN_TAINT, addressed in another patch, have lead to over
+a 100 bugs being filed this way.
+
+This commit replaces the WARN_TAINT("...") calls, with
+pr_warn(FW_BUG "...") + add_taint(TAINT_FIRMWARE_WORKAROUND, ...) calls
+avoiding the backtrace and thus also avoiding bug-reports being filed
+about this against the kernel.
+
+Fixes: fd0c8894893c ("intel-iommu: Set a more specific taint flag for invalid BIOS DMAR tables")
+Fixes: e625b4a95d50 ("iommu/vt-d: Parse ANDD records")
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20200309140138.3753-2-hdegoede@redhat.com
+BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1564895
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/dmar.c |   11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/drivers/iommu/dmar.c
++++ b/drivers/iommu/dmar.c
+@@ -438,12 +438,13 @@ static int __init dmar_parse_one_andd(st
+       /* Check for NUL termination within the designated length */
+       if (strnlen(andd->device_name, header->length - 8) == header->length - 8) {
+-              WARN_TAINT(1, TAINT_FIRMWARE_WORKAROUND,
++              pr_warn(FW_BUG
+                          "Your BIOS is broken; ANDD object name is not NUL-terminated\n"
+                          "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+                          dmi_get_system_info(DMI_BIOS_VENDOR),
+                          dmi_get_system_info(DMI_BIOS_VERSION),
+                          dmi_get_system_info(DMI_PRODUCT_VERSION));
++              add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+               return -EINVAL;
+       }
+       pr_info("ANDD device: %x name: %s\n", andd->device_number,
+@@ -469,14 +470,14 @@ static int dmar_parse_one_rhsa(struct ac
+                       return 0;
+               }
+       }
+-      WARN_TAINT(
+-              1, TAINT_FIRMWARE_WORKAROUND,
++      pr_warn(FW_BUG
+               "Your BIOS is broken; RHSA refers to non-existent DMAR unit at %llx\n"
+               "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+               drhd->reg_base_addr,
+               dmi_get_system_info(DMI_BIOS_VENDOR),
+               dmi_get_system_info(DMI_BIOS_VERSION),
+               dmi_get_system_info(DMI_PRODUCT_VERSION));
++      add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+       return 0;
+ }
+@@ -822,14 +823,14 @@ int __init dmar_table_init(void)
+ static void warn_invalid_dmar(u64 addr, const char *message)
+ {
+-      WARN_TAINT_ONCE(
+-              1, TAINT_FIRMWARE_WORKAROUND,
++      pr_warn_once(FW_BUG
+               "Your BIOS is broken; DMAR reported at address %llx%s!\n"
+               "BIOS vendor: %s; Ver: %s; Product Version: %s\n",
+               addr, message,
+               dmi_get_system_info(DMI_BIOS_VENDOR),
+               dmi_get_system_info(DMI_BIOS_VERSION),
+               dmi_get_system_info(DMI_PRODUCT_VERSION));
++      add_taint(TAINT_FIRMWARE_WORKAROUND, LOCKDEP_STILL_OK);
+ }
+ static int __ref
diff --git a/queue-4.4/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page.patch b/queue-4.4/iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page.patch
new file mode 100644 (file)
index 0000000..3240c97
--- /dev/null
@@ -0,0 +1,41 @@
+From 77a1bce84bba01f3f143d77127b72e872b573795 Mon Sep 17 00:00:00 2001
+From: Yonghyun Hwang <yonghyun@google.com>
+Date: Wed, 26 Feb 2020 12:30:06 -0800
+Subject: iommu/vt-d: Fix a bug in intel_iommu_iova_to_phys() for huge page
+
+From: Yonghyun Hwang <yonghyun@google.com>
+
+commit 77a1bce84bba01f3f143d77127b72e872b573795 upstream.
+
+intel_iommu_iova_to_phys() has a bug when it translates an IOVA for a huge
+page onto its corresponding physical address. This commit fixes the bug by
+accomodating the level of page entry for the IOVA and adds IOVA's lower
+address to the physical address.
+
+Cc: <stable@vger.kernel.org>
+Acked-by: Lu Baolu <baolu.lu@linux.intel.com>
+Reviewed-by: Moritz Fischer <mdf@kernel.org>
+Signed-off-by: Yonghyun Hwang <yonghyun@google.com>
+Fixes: 3871794642579 ("VT-d: Changes to support KVM")
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/iommu/intel-iommu.c |    6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/iommu/intel-iommu.c
++++ b/drivers/iommu/intel-iommu.c
+@@ -5017,8 +5017,10 @@ static phys_addr_t intel_iommu_iova_to_p
+       u64 phys = 0;
+       pte = pfn_to_dma_pte(dmar_domain, iova >> VTD_PAGE_SHIFT, &level);
+-      if (pte)
+-              phys = dma_pte_addr(pte);
++      if (pte && dma_pte_present(pte))
++              phys = dma_pte_addr(pte) +
++                      (iova & (BIT_MASK(level_to_offset_bits(level) +
++                                              VTD_PAGE_SHIFT) - 1));
+       return phys;
+ }
diff --git a/queue-4.4/kvm-x86-clear-stale-x86_emulate_ctxt-intercept-value.patch b/queue-4.4/kvm-x86-clear-stale-x86_emulate_ctxt-intercept-value.patch
new file mode 100644 (file)
index 0000000..86872c3
--- /dev/null
@@ -0,0 +1,50 @@
+From 342993f96ab24d5864ab1216f46c0b199c2baf8e Mon Sep 17 00:00:00 2001
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+Date: Tue, 3 Mar 2020 15:33:15 +0100
+Subject: KVM: x86: clear stale x86_emulate_ctxt->intercept value
+
+From: Vitaly Kuznetsov <vkuznets@redhat.com>
+
+commit 342993f96ab24d5864ab1216f46c0b199c2baf8e upstream.
+
+After commit 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest
+mode") Hyper-V guests on KVM stopped booting with:
+
+ kvm_nested_vmexit:    rip fffff802987d6169 reason EPT_VIOLATION info1 181
+    info2 0 int_info 0 int_info_err 0
+ kvm_page_fault:       address febd0000 error_code 181
+ kvm_emulate_insn:     0:fffff802987d6169: f3 a5
+ kvm_emulate_insn:     0:fffff802987d6169: f3 a5 FAIL
+ kvm_inj_exception:    #UD (0x0)
+
+"f3 a5" is a "rep movsw" instruction, which should not be intercepted
+at all.  Commit c44b4c6ab80e ("KVM: emulate: clean up initializations in
+init_decode_cache") reduced the number of fields cleared by
+init_decode_cache() claiming that they are being cleared elsewhere,
+'intercept', however, is left uncleared if the instruction does not have
+any of the "slow path" flags (NotImpl, Stack, Op3264, Sse, Mmx, CheckPerm,
+NearBranch, No16 and of course Intercept itself).
+
+Fixes: c44b4c6ab80e ("KVM: emulate: clean up initializations in init_decode_cache")
+Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode")
+Cc: stable@vger.kernel.org
+Suggested-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
+Reviewed-by: Sean Christopherson <sean.j.christopherson@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/emulate.c |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -5010,6 +5010,7 @@ int x86_decode_insn(struct x86_emulate_c
+       ctxt->fetch.ptr = ctxt->fetch.data;
+       ctxt->fetch.end = ctxt->fetch.data + insn_len;
+       ctxt->opcode_len = 1;
++      ctxt->intercept = x86_intercept_none;
+       if (insn_len > 0)
+               memcpy(ctxt->fetch.data, insn, insn_len);
+       else {
index 4c8d85fae1eb4c97e3fa2acddeb9269198467279..3ba1fb2816e2fbd1c78293f69acdcffc479b261c 100644 (file)
@@ -21,3 +21,9 @@ bonding-alb-make-sure-arp-header-is-pulled-before-accessing-it.patch
 net-fq-add-missing-attribute-validation-for-orphan-mask.patch
 iommu-vt-d-quirk_ioat_snb_local_iommu-replace-warn_taint-with-pr_warn-add_taint.patch
 drm-amd-display-remove-duplicated-assignment-to-grph_obj_type.patch
+gfs2_atomic_open-fix-o_excl-o_creat-handling-on-cold-dcache.patch
+kvm-x86-clear-stale-x86_emulate_ctxt-intercept-value.patch
+arc-define-__align_str-and-__align-symbols-for-arc.patch
+efi-fix-a-race-and-a-buffer-overflow-while-reading-efivars-via-sysfs.patch
+iommu-vt-d-dmar-replace-warn_taint-with-pr_warn-add_taint.patch
+iommu-vt-d-fix-a-bug-in-intel_iommu_iova_to_phys-for-huge-page.patch