]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Mar 2020 18:38:47 +0000 (19:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 2 Mar 2020 18:38:47 +0000 (19:38 +0100)
added patches:
audit-fix-error-handling-in-audit_data_to_entry.patch
ext4-potential-crash-on-allocation-error-in-ext4_alloc_flex_bg_array.patch
hid-core-fix-off-by-one-memset-in-hid_report_raw_event.patch
hid-core-increase-hid-report-buffer-size-to-8kib.patch
kvm-vmx-check-descriptor-table-exits-on-instruction-emulation.patch

queue-4.4/audit-fix-error-handling-in-audit_data_to_entry.patch [new file with mode: 0644]
queue-4.4/ext4-potential-crash-on-allocation-error-in-ext4_alloc_flex_bg_array.patch [new file with mode: 0644]
queue-4.4/hid-core-fix-off-by-one-memset-in-hid_report_raw_event.patch [new file with mode: 0644]
queue-4.4/hid-core-increase-hid-report-buffer-size-to-8kib.patch [new file with mode: 0644]
queue-4.4/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/audit-fix-error-handling-in-audit_data_to_entry.patch b/queue-4.4/audit-fix-error-handling-in-audit_data_to_entry.patch
new file mode 100644 (file)
index 0000000..3c9ea28
--- /dev/null
@@ -0,0 +1,203 @@
+From 2ad3e17ebf94b7b7f3f64c050ff168f9915345eb Mon Sep 17 00:00:00 2001
+From: Paul Moore <paul@paul-moore.com>
+Date: Sat, 22 Feb 2020 20:36:47 -0500
+Subject: audit: fix error handling in audit_data_to_entry()
+
+From: Paul Moore <paul@paul-moore.com>
+
+commit 2ad3e17ebf94b7b7f3f64c050ff168f9915345eb upstream.
+
+Commit 219ca39427bf ("audit: use union for audit_field values since
+they are mutually exclusive") combined a number of separate fields in
+the audit_field struct into a single union.  Generally this worked
+just fine because they are generally mutually exclusive.
+Unfortunately in audit_data_to_entry() the overlap can be a problem
+when a specific error case is triggered that causes the error path
+code to attempt to cleanup an audit_field struct and the cleanup
+involves attempting to free a stored LSM string (the lsm_str field).
+Currently the code always has a non-NULL value in the
+audit_field.lsm_str field as the top of the for-loop transfers a
+value into audit_field.val (both .lsm_str and .val are part of the
+same union); if audit_data_to_entry() fails and the audit_field
+struct is specified to contain a LSM string, but the
+audit_field.lsm_str has not yet been properly set, the error handling
+code will attempt to free the bogus audit_field.lsm_str value that
+was set with audit_field.val at the top of the for-loop.
+
+This patch corrects this by ensuring that the audit_field.val is only
+set when needed (it is cleared when the audit_field struct is
+allocated with kcalloc()).  It also corrects a few other issues to
+ensure that in case of error the proper error code is returned.
+
+Cc: stable@vger.kernel.org
+Fixes: 219ca39427bf ("audit: use union for audit_field values since they are mutually exclusive")
+Reported-by: syzbot+1f4d90ead370d72e450b@syzkaller.appspotmail.com
+Signed-off-by: Paul Moore <paul@paul-moore.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ kernel/auditfilter.c |   71 ++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 39 insertions(+), 32 deletions(-)
+
+--- a/kernel/auditfilter.c
++++ b/kernel/auditfilter.c
+@@ -434,6 +434,7 @@ static struct audit_entry *audit_data_to
+       bufp = data->buf;
+       for (i = 0; i < data->field_count; i++) {
+               struct audit_field *f = &entry->rule.fields[i];
++              u32 f_val;
+               err = -EINVAL;
+@@ -442,12 +443,12 @@ static struct audit_entry *audit_data_to
+                       goto exit_free;
+               f->type = data->fields[i];
+-              f->val = data->values[i];
++              f_val = data->values[i];
+               /* Support legacy tests for a valid loginuid */
+-              if ((f->type == AUDIT_LOGINUID) && (f->val == AUDIT_UID_UNSET)) {
++              if ((f->type == AUDIT_LOGINUID) && (f_val == AUDIT_UID_UNSET)) {
+                       f->type = AUDIT_LOGINUID_SET;
+-                      f->val = 0;
++                      f_val = 0;
+                       entry->rule.pflags |= AUDIT_LOGINUID_LEGACY;
+               }
+@@ -463,7 +464,7 @@ static struct audit_entry *audit_data_to
+               case AUDIT_SUID:
+               case AUDIT_FSUID:
+               case AUDIT_OBJ_UID:
+-                      f->uid = make_kuid(current_user_ns(), f->val);
++                      f->uid = make_kuid(current_user_ns(), f_val);
+                       if (!uid_valid(f->uid))
+                               goto exit_free;
+                       break;
+@@ -472,11 +473,12 @@ static struct audit_entry *audit_data_to
+               case AUDIT_SGID:
+               case AUDIT_FSGID:
+               case AUDIT_OBJ_GID:
+-                      f->gid = make_kgid(current_user_ns(), f->val);
++                      f->gid = make_kgid(current_user_ns(), f_val);
+                       if (!gid_valid(f->gid))
+                               goto exit_free;
+                       break;
+               case AUDIT_ARCH:
++                      f->val = f_val;
+                       entry->rule.arch_f = f;
+                       break;
+               case AUDIT_SUBJ_USER:
+@@ -489,11 +491,13 @@ static struct audit_entry *audit_data_to
+               case AUDIT_OBJ_TYPE:
+               case AUDIT_OBJ_LEV_LOW:
+               case AUDIT_OBJ_LEV_HIGH:
+-                      str = audit_unpack_string(&bufp, &remain, f->val);
+-                      if (IS_ERR(str))
++                      str = audit_unpack_string(&bufp, &remain, f_val);
++                      if (IS_ERR(str)) {
++                              err = PTR_ERR(str);
+                               goto exit_free;
+-                      entry->rule.buflen += f->val;
+-
++                      }
++                      entry->rule.buflen += f_val;
++                      f->lsm_str = str;
+                       err = security_audit_rule_init(f->type, f->op, str,
+                                                      (void **)&f->lsm_rule);
+                       /* Keep currently invalid fields around in case they
+@@ -502,68 +506,71 @@ static struct audit_entry *audit_data_to
+                               pr_warn("audit rule for LSM \'%s\' is invalid\n",
+                                       str);
+                               err = 0;
+-                      }
+-                      if (err) {
+-                              kfree(str);
++                      } else if (err)
+                               goto exit_free;
+-                      } else
+-                              f->lsm_str = str;
+                       break;
+               case AUDIT_WATCH:
+-                      str = audit_unpack_string(&bufp, &remain, f->val);
+-                      if (IS_ERR(str))
++                      str = audit_unpack_string(&bufp, &remain, f_val);
++                      if (IS_ERR(str)) {
++                              err = PTR_ERR(str);
+                               goto exit_free;
+-                      entry->rule.buflen += f->val;
+-
+-                      err = audit_to_watch(&entry->rule, str, f->val, f->op);
++                      }
++                      err = audit_to_watch(&entry->rule, str, f_val, f->op);
+                       if (err) {
+                               kfree(str);
+                               goto exit_free;
+                       }
++                      entry->rule.buflen += f_val;
+                       break;
+               case AUDIT_DIR:
+-                      str = audit_unpack_string(&bufp, &remain, f->val);
+-                      if (IS_ERR(str))
++                      str = audit_unpack_string(&bufp, &remain, f_val);
++                      if (IS_ERR(str)) {
++                              err = PTR_ERR(str);
+                               goto exit_free;
+-                      entry->rule.buflen += f->val;
+-
++                      }
+                       err = audit_make_tree(&entry->rule, str, f->op);
+                       kfree(str);
+                       if (err)
+                               goto exit_free;
++                      entry->rule.buflen += f_val;
+                       break;
+               case AUDIT_INODE:
++                      f->val = f_val;
+                       err = audit_to_inode(&entry->rule, f);
+                       if (err)
+                               goto exit_free;
+                       break;
+               case AUDIT_FILTERKEY:
+-                      if (entry->rule.filterkey || f->val > AUDIT_MAX_KEY_LEN)
++                      if (entry->rule.filterkey || f_val > AUDIT_MAX_KEY_LEN)
+                               goto exit_free;
+-                      str = audit_unpack_string(&bufp, &remain, f->val);
+-                      if (IS_ERR(str))
++                      str = audit_unpack_string(&bufp, &remain, f_val);
++                      if (IS_ERR(str)) {
++                              err = PTR_ERR(str);
+                               goto exit_free;
+-                      entry->rule.buflen += f->val;
++                      }
++                      entry->rule.buflen += f_val;
+                       entry->rule.filterkey = str;
+                       break;
+               case AUDIT_EXE:
+-                      if (entry->rule.exe || f->val > PATH_MAX)
++                      if (entry->rule.exe || f_val > PATH_MAX)
+                               goto exit_free;
+-                      str = audit_unpack_string(&bufp, &remain, f->val);
++                      str = audit_unpack_string(&bufp, &remain, f_val);
+                       if (IS_ERR(str)) {
+                               err = PTR_ERR(str);
+                               goto exit_free;
+                       }
+-                      entry->rule.buflen += f->val;
+-
+-                      audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
++                      audit_mark = audit_alloc_mark(&entry->rule, str, f_val);
+                       if (IS_ERR(audit_mark)) {
+                               kfree(str);
+                               err = PTR_ERR(audit_mark);
+                               goto exit_free;
+                       }
++                      entry->rule.buflen += f_val;
+                       entry->rule.exe = audit_mark;
+                       break;
++              default:
++                      f->val = f_val;
++                      break;
+               }
+       }
diff --git a/queue-4.4/ext4-potential-crash-on-allocation-error-in-ext4_alloc_flex_bg_array.patch b/queue-4.4/ext4-potential-crash-on-allocation-error-in-ext4_alloc_flex_bg_array.patch
new file mode 100644 (file)
index 0000000..0a7f17a
--- /dev/null
@@ -0,0 +1,50 @@
+From 37b0b6b8b99c0e1c1f11abbe7cf49b6d03795b3f Mon Sep 17 00:00:00 2001
+From: Dan Carpenter <dan.carpenter@oracle.com>
+Date: Fri, 28 Feb 2020 12:22:56 +0300
+Subject: ext4: potential crash on allocation error in ext4_alloc_flex_bg_array()
+
+From: Dan Carpenter <dan.carpenter@oracle.com>
+
+commit 37b0b6b8b99c0e1c1f11abbe7cf49b6d03795b3f upstream.
+
+If sbi->s_flex_groups_allocated is zero and the first allocation fails
+then this code will crash.  The problem is that "i--" will set "i" to
+-1 but when we compare "i >= sbi->s_flex_groups_allocated" then the -1
+is type promoted to unsigned and becomes UINT_MAX.  Since UINT_MAX
+is more than zero, the condition is true so we call kvfree(new_groups[-1]).
+The loop will carry on freeing invalid memory until it crashes.
+
+Fixes: 7c990728b99e ("ext4: fix potential race between s_flex_groups online resizing and access")
+Reviewed-by: Suraj Jitindar Singh <surajjs@amazon.com>
+Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
+Cc: stable@kernel.org
+Link: https://lore.kernel.org/r/20200228092142.7irbc44yaz3by7nb@kili.mountain
+Signed-off-by: Theodore Ts'o <tytso@mit.edu>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ fs/ext4/super.c |    6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/ext4/super.c
++++ b/fs/ext4/super.c
+@@ -1989,7 +1989,7 @@ int ext4_alloc_flex_bg_array(struct supe
+ {
+       struct ext4_sb_info *sbi = EXT4_SB(sb);
+       struct flex_groups **old_groups, **new_groups;
+-      int size, i;
++      int size, i, j;
+       if (!sbi->s_log_groups_per_flex)
+               return 0;
+@@ -2010,8 +2010,8 @@ int ext4_alloc_flex_bg_array(struct supe
+                                             sizeof(struct flex_groups)),
+                                             GFP_KERNEL);
+               if (!new_groups[i]) {
+-                      for (i--; i >= sbi->s_flex_groups_allocated; i--)
+-                              kvfree(new_groups[i]);
++                      for (j = sbi->s_flex_groups_allocated; j < i; j++)
++                              kvfree(new_groups[j]);
+                       kvfree(new_groups);
+                       ext4_msg(sb, KERN_ERR,
+                                "not enough memory for %d flex groups", size);
diff --git a/queue-4.4/hid-core-fix-off-by-one-memset-in-hid_report_raw_event.patch b/queue-4.4/hid-core-fix-off-by-one-memset-in-hid_report_raw_event.patch
new file mode 100644 (file)
index 0000000..86a8724
--- /dev/null
@@ -0,0 +1,46 @@
+From 5ebdffd25098898aff1249ae2f7dbfddd76d8f8f Mon Sep 17 00:00:00 2001
+From: Johan Korsnes <jkorsnes@cisco.com>
+Date: Fri, 17 Jan 2020 13:08:35 +0100
+Subject: HID: core: fix off-by-one memset in hid_report_raw_event()
+
+From: Johan Korsnes <jkorsnes@cisco.com>
+
+commit 5ebdffd25098898aff1249ae2f7dbfddd76d8f8f upstream.
+
+In case a report is greater than HID_MAX_BUFFER_SIZE, it is truncated,
+but the report-number byte is not correctly handled. This results in a
+off-by-one in the following memset, causing a kernel Oops and ensuing
+system crash.
+
+Note: With commit 8ec321e96e05 ("HID: Fix slab-out-of-bounds read in
+hid_field_extract") I no longer hit the kernel Oops as we instead fail
+"controlled" at probe if there is a report too long in the HID
+report-descriptor. hid_report_raw_event() is an exported symbol, so
+presumabely we cannot always rely on this being the case.
+
+Fixes: 966922f26c7f ("HID: fix a crash in hid_report_raw_event()
+                     function.")
+Signed-off-by: Johan Korsnes <jkorsnes@cisco.com>
+Cc: Armando Visconti <armando.visconti@st.com>
+Cc: Jiri Kosina <jkosina@suse.cz>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/hid/hid-core.c |    4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/hid/hid-core.c
++++ b/drivers/hid/hid-core.c
+@@ -1508,7 +1508,9 @@ int hid_report_raw_event(struct hid_devi
+       rsize = ((report->size - 1) >> 3) + 1;
+-      if (rsize > HID_MAX_BUFFER_SIZE)
++      if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
++              rsize = HID_MAX_BUFFER_SIZE - 1;
++      else if (rsize > HID_MAX_BUFFER_SIZE)
+               rsize = HID_MAX_BUFFER_SIZE;
+       if (csize < rsize) {
diff --git a/queue-4.4/hid-core-increase-hid-report-buffer-size-to-8kib.patch b/queue-4.4/hid-core-increase-hid-report-buffer-size-to-8kib.patch
new file mode 100644 (file)
index 0000000..3da80fe
--- /dev/null
@@ -0,0 +1,37 @@
+From 84a4062632462c4320704fcdf8e99e89e94c0aba Mon Sep 17 00:00:00 2001
+From: Johan Korsnes <jkorsnes@cisco.com>
+Date: Fri, 17 Jan 2020 13:08:36 +0100
+Subject: HID: core: increase HID report buffer size to 8KiB
+
+From: Johan Korsnes <jkorsnes@cisco.com>
+
+commit 84a4062632462c4320704fcdf8e99e89e94c0aba upstream.
+
+We have a HID touch device that reports its opens and shorts test
+results in HID buffers of size 8184 bytes. The maximum size of the HID
+buffer is currently set to 4096 bytes, causing probe of this device to
+fail. With this patch we increase the maximum size of the HID buffer to
+8192 bytes, making device probe and acquisition of said buffers succeed.
+
+Signed-off-by: Johan Korsnes <jkorsnes@cisco.com>
+Cc: Alan Stern <stern@rowland.harvard.edu>
+Cc: Armando Visconti <armando.visconti@st.com>
+Cc: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ include/linux/hid.h |    2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/include/linux/hid.h
++++ b/include/linux/hid.h
+@@ -451,7 +451,7 @@ struct hid_report_enum {
+ };
+ #define HID_MIN_BUFFER_SIZE   64              /* make sure there is at least a packet size of space */
+-#define HID_MAX_BUFFER_SIZE   4096            /* 4kb */
++#define HID_MAX_BUFFER_SIZE   8192            /* 8kb */
+ #define HID_CONTROL_FIFO_SIZE 256             /* to init devices with >100 reports */
+ #define HID_OUTPUT_FIFO_SIZE  64
diff --git a/queue-4.4/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation.patch b/queue-4.4/kvm-vmx-check-descriptor-table-exits-on-instruction-emulation.patch
new file mode 100644 (file)
index 0000000..917644d
--- /dev/null
@@ -0,0 +1,61 @@
+From 86f7e90ce840aa1db407d3ea6e9b3a52b2ce923c Mon Sep 17 00:00:00 2001
+From: Oliver Upton <oupton@google.com>
+Date: Sat, 29 Feb 2020 11:30:14 -0800
+Subject: KVM: VMX: check descriptor table exits on instruction emulation
+
+From: Oliver Upton <oupton@google.com>
+
+commit 86f7e90ce840aa1db407d3ea6e9b3a52b2ce923c upstream.
+
+KVM emulates UMIP on hardware that doesn't support it by setting the
+'descriptor table exiting' VM-execution control and performing
+instruction emulation. When running nested, this emulation is broken as
+KVM refuses to emulate L2 instructions by default.
+
+Correct this regression by allowing the emulation of descriptor table
+instructions if L1 hasn't requested 'descriptor table exiting'.
+
+Fixes: 07721feee46b ("KVM: nVMX: Don't emulate instructions in guest mode")
+Reported-by: Jan Kiszka <jan.kiszka@web.de>
+Cc: stable@vger.kernel.org
+Cc: Paolo Bonzini <pbonzini@redhat.com>
+Cc: Jim Mattson <jmattson@google.com>
+Signed-off-by: Oliver Upton <oupton@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ arch/x86/kvm/vmx.c |   15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/arch/x86/kvm/vmx.c
++++ b/arch/x86/kvm/vmx.c
+@@ -10784,6 +10784,7 @@ static int vmx_check_intercept_io(struct
+       else
+               intercept = nested_vmx_check_io_bitmaps(vcpu, port, size);
++      /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
+       return intercept ? X86EMUL_UNHANDLEABLE : X86EMUL_CONTINUE;
+ }
+@@ -10813,6 +10814,20 @@ static int vmx_check_intercept(struct kv
+       case x86_intercept_outs:
+               return vmx_check_intercept_io(vcpu, info);
++      case x86_intercept_lgdt:
++      case x86_intercept_lidt:
++      case x86_intercept_lldt:
++      case x86_intercept_ltr:
++      case x86_intercept_sgdt:
++      case x86_intercept_sidt:
++      case x86_intercept_sldt:
++      case x86_intercept_str:
++              if (!nested_cpu_has2(vmcs12, SECONDARY_EXEC_DESC))
++                      return X86EMUL_CONTINUE;
++
++              /* FIXME: produce nested vmexit and return X86EMUL_INTERCEPTED.  */
++              break;
++
+       /* TODO: check more intercepts... */
+       default:
+               break;
index de55a1da206b77fa0647087e5ad1f7972237e4df..c8fc3fe99d0ac0f83921db1c3795138191617a0b 100644 (file)
@@ -17,3 +17,8 @@ ipv6-fix-route-replacement-with-dev-only-route.patch
 sctp-move-the-format-error-check-out-of-__sctp_sf_do_9_1_abort.patch
 nfc-pn544-fix-occasional-hw-initialization-failure.patch
 net-sched-correct-flower-port-blocking.patch
+ext4-potential-crash-on-allocation-error-in-ext4_alloc_flex_bg_array.patch
+audit-fix-error-handling-in-audit_data_to_entry.patch
+kvm-vmx-check-descriptor-table-exits-on-instruction-emulation.patch
+hid-core-fix-off-by-one-memset-in-hid_report_raw_event.patch
+hid-core-increase-hid-report-buffer-size-to-8kib.patch