From: Greg Kroah-Hartman Date: Thu, 19 Sep 2019 14:02:36 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.194~38 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=428307c2a035aef82fa821f482154c550c432d3d;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: firmware-google-check-if-size-is-valid-when-decoding-vpd-data.patch kvm-coalesced_mmio-add-bounds-checking.patch serial-sprd-correct-the-wrong-sequence-of-arguments.patch tty-serial-atmel-reschedule-tx-after-rx-was-started.patch --- diff --git a/queue-4.14/firmware-google-check-if-size-is-valid-when-decoding-vpd-data.patch b/queue-4.14/firmware-google-check-if-size-is-valid-when-decoding-vpd-data.patch new file mode 100644 index 00000000000..9bc33194858 --- /dev/null +++ b/queue-4.14/firmware-google-check-if-size-is-valid-when-decoding-vpd-data.patch @@ -0,0 +1,158 @@ +From 4b708b7b1a2c09fbdfff6b942ebe3a160213aacd Mon Sep 17 00:00:00 2001 +From: Hung-Te Lin +Date: Fri, 30 Aug 2019 10:23:58 +0800 +Subject: firmware: google: check if size is valid when decoding VPD data + +From: Hung-Te Lin + +commit 4b708b7b1a2c09fbdfff6b942ebe3a160213aacd upstream. + +The VPD implementation from Chromium Vital Product Data project used to +parse data from untrusted input without checking if the meta data is +invalid or corrupted. For example, the size from decoded content may +be negative value, or larger than whole input buffer. Such invalid data +may cause buffer overflow. + +To fix that, the size parameters passed to vpd_decode functions should +be changed to unsigned integer (u32) type, and the parsing of entry +header should be refactored so every size field is correctly verified +before starting to decode. + +Fixes: ad2ac9d5c5e0 ("firmware: Google VPD: import lib_vpd source files") +Signed-off-by: Hung-Te Lin +Cc: stable +Reviewed-by: Guenter Roeck +Reviewed-by: Stephen Boyd +Link: https://lore.kernel.org/r/20190830022402.214442-1-hungte@chromium.org +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/firmware/google/vpd.c | 4 +- + drivers/firmware/google/vpd_decode.c | 55 ++++++++++++++++++++--------------- + drivers/firmware/google/vpd_decode.h | 6 +-- + 3 files changed, 37 insertions(+), 28 deletions(-) + +--- a/drivers/firmware/google/vpd.c ++++ b/drivers/firmware/google/vpd.c +@@ -100,8 +100,8 @@ static int vpd_section_check_key_name(co + return VPD_OK; + } + +-static int vpd_section_attrib_add(const u8 *key, s32 key_len, +- const u8 *value, s32 value_len, ++static int vpd_section_attrib_add(const u8 *key, u32 key_len, ++ const u8 *value, u32 value_len, + void *arg) + { + int ret; +--- a/drivers/firmware/google/vpd_decode.c ++++ b/drivers/firmware/google/vpd_decode.c +@@ -19,8 +19,8 @@ + + #include "vpd_decode.h" + +-static int vpd_decode_len(const s32 max_len, const u8 *in, +- s32 *length, s32 *decoded_len) ++static int vpd_decode_len(const u32 max_len, const u8 *in, ++ u32 *length, u32 *decoded_len) + { + u8 more; + int i = 0; +@@ -40,18 +40,39 @@ static int vpd_decode_len(const s32 max_ + } while (more); + + *decoded_len = i; ++ return VPD_OK; ++} ++ ++static int vpd_decode_entry(const u32 max_len, const u8 *input_buf, ++ u32 *_consumed, const u8 **entry, u32 *entry_len) ++{ ++ u32 decoded_len; ++ u32 consumed = *_consumed; + ++ if (vpd_decode_len(max_len - consumed, &input_buf[consumed], ++ entry_len, &decoded_len) != VPD_OK) ++ return VPD_FAIL; ++ if (max_len - consumed < decoded_len) ++ return VPD_FAIL; ++ ++ consumed += decoded_len; ++ *entry = input_buf + consumed; ++ ++ /* entry_len is untrusted data and must be checked again. */ ++ if (max_len - consumed < *entry_len) ++ return VPD_FAIL; ++ ++ consumed += decoded_len; ++ *_consumed = consumed; + return VPD_OK; + } + +-int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed, ++int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed, + vpd_decode_callback callback, void *callback_arg) + { + int type; +- int res; +- s32 key_len; +- s32 value_len; +- s32 decoded_len; ++ u32 key_len; ++ u32 value_len; + const u8 *key; + const u8 *value; + +@@ -66,26 +87,14 @@ int vpd_decode_string(const s32 max_len, + case VPD_TYPE_STRING: + (*consumed)++; + +- /* key */ +- res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed], +- &key_len, &decoded_len); +- if (res != VPD_OK || *consumed + decoded_len >= max_len) ++ if (vpd_decode_entry(max_len, input_buf, consumed, &key, ++ &key_len) != VPD_OK) + return VPD_FAIL; + +- *consumed += decoded_len; +- key = &input_buf[*consumed]; +- *consumed += key_len; +- +- /* value */ +- res = vpd_decode_len(max_len - *consumed, &input_buf[*consumed], +- &value_len, &decoded_len); +- if (res != VPD_OK || *consumed + decoded_len > max_len) ++ if (vpd_decode_entry(max_len, input_buf, consumed, &value, ++ &value_len) != VPD_OK) + return VPD_FAIL; + +- *consumed += decoded_len; +- value = &input_buf[*consumed]; +- *consumed += value_len; +- + if (type == VPD_TYPE_STRING) + return callback(key, key_len, value, value_len, + callback_arg); +--- a/drivers/firmware/google/vpd_decode.h ++++ b/drivers/firmware/google/vpd_decode.h +@@ -33,8 +33,8 @@ enum { + }; + + /* Callback for vpd_decode_string to invoke. */ +-typedef int vpd_decode_callback(const u8 *key, s32 key_len, +- const u8 *value, s32 value_len, ++typedef int vpd_decode_callback(const u8 *key, u32 key_len, ++ const u8 *value, u32 value_len, + void *arg); + + /* +@@ -52,7 +52,7 @@ typedef int vpd_decode_callback(const u8 + * If one entry is successfully decoded, sends it to callback and returns the + * result. + */ +-int vpd_decode_string(const s32 max_len, const u8 *input_buf, s32 *consumed, ++int vpd_decode_string(const u32 max_len, const u8 *input_buf, u32 *consumed, + vpd_decode_callback callback, void *callback_arg); + + #endif /* __VPD_DECODE_H */ diff --git a/queue-4.14/kvm-coalesced_mmio-add-bounds-checking.patch b/queue-4.14/kvm-coalesced_mmio-add-bounds-checking.patch new file mode 100644 index 00000000000..e269010dc4d --- /dev/null +++ b/queue-4.14/kvm-coalesced_mmio-add-bounds-checking.patch @@ -0,0 +1,82 @@ +From b60fe990c6b07ef6d4df67bc0530c7c90a62623a Mon Sep 17 00:00:00 2001 +From: Matt Delco +Date: Mon, 16 Sep 2019 14:16:54 -0700 +Subject: KVM: coalesced_mmio: add bounds checking + +From: Matt Delco + +commit b60fe990c6b07ef6d4df67bc0530c7c90a62623a upstream. + +The first/last indexes are typically shared with a user app. +The app can change the 'last' index that the kernel uses +to store the next result. This change sanity checks the index +before using it for writing to a potentially arbitrary address. + +This fixes CVE-2019-14821. + +Cc: stable@vger.kernel.org +Fixes: 5f94c1741bdc ("KVM: Add coalesced MMIO support (common part)") +Signed-off-by: Matt Delco +Signed-off-by: Jim Mattson +Reported-by: syzbot+983c866c3dd6efa3662a@syzkaller.appspotmail.com +[Use READ_ONCE. - Paolo] +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + virt/kvm/coalesced_mmio.c | 17 ++++++++++------- + 1 file changed, 10 insertions(+), 7 deletions(-) + +--- a/virt/kvm/coalesced_mmio.c ++++ b/virt/kvm/coalesced_mmio.c +@@ -40,7 +40,7 @@ static int coalesced_mmio_in_range(struc + return 1; + } + +-static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev) ++static int coalesced_mmio_has_room(struct kvm_coalesced_mmio_dev *dev, u32 last) + { + struct kvm_coalesced_mmio_ring *ring; + unsigned avail; +@@ -52,7 +52,7 @@ static int coalesced_mmio_has_room(struc + * there is always one unused entry in the buffer + */ + ring = dev->kvm->coalesced_mmio_ring; +- avail = (ring->first - ring->last - 1) % KVM_COALESCED_MMIO_MAX; ++ avail = (ring->first - last - 1) % KVM_COALESCED_MMIO_MAX; + if (avail == 0) { + /* full */ + return 0; +@@ -67,24 +67,27 @@ static int coalesced_mmio_write(struct k + { + struct kvm_coalesced_mmio_dev *dev = to_mmio(this); + struct kvm_coalesced_mmio_ring *ring = dev->kvm->coalesced_mmio_ring; ++ __u32 insert; + + if (!coalesced_mmio_in_range(dev, addr, len)) + return -EOPNOTSUPP; + + spin_lock(&dev->kvm->ring_lock); + +- if (!coalesced_mmio_has_room(dev)) { ++ insert = READ_ONCE(ring->last); ++ if (!coalesced_mmio_has_room(dev, insert) || ++ insert >= KVM_COALESCED_MMIO_MAX) { + spin_unlock(&dev->kvm->ring_lock); + return -EOPNOTSUPP; + } + + /* copy data in first free entry of the ring */ + +- ring->coalesced_mmio[ring->last].phys_addr = addr; +- ring->coalesced_mmio[ring->last].len = len; +- memcpy(ring->coalesced_mmio[ring->last].data, val, len); ++ ring->coalesced_mmio[insert].phys_addr = addr; ++ ring->coalesced_mmio[insert].len = len; ++ memcpy(ring->coalesced_mmio[insert].data, val, len); + smp_wmb(); +- ring->last = (ring->last + 1) % KVM_COALESCED_MMIO_MAX; ++ ring->last = (insert + 1) % KVM_COALESCED_MMIO_MAX; + spin_unlock(&dev->kvm->ring_lock); + return 0; + } diff --git a/queue-4.14/serial-sprd-correct-the-wrong-sequence-of-arguments.patch b/queue-4.14/serial-sprd-correct-the-wrong-sequence-of-arguments.patch new file mode 100644 index 00000000000..cae17958af5 --- /dev/null +++ b/queue-4.14/serial-sprd-correct-the-wrong-sequence-of-arguments.patch @@ -0,0 +1,35 @@ +From 9c801e313195addaf11c16e155f50789d6ebfd19 Mon Sep 17 00:00:00 2001 +From: Chunyan Zhang +Date: Thu, 5 Sep 2019 15:41:51 +0800 +Subject: serial: sprd: correct the wrong sequence of arguments + +From: Chunyan Zhang + +commit 9c801e313195addaf11c16e155f50789d6ebfd19 upstream. + +The sequence of arguments which was passed to handle_lsr_errors() didn't +match the parameters defined in that function, &lsr was passed to flag +and &flag was passed to lsr, this patch fixed that. + +Fixes: b7396a38fb28 ("tty/serial: Add Spreadtrum sc9836-uart driver support") +Signed-off-by: Chunyan Zhang +Signed-off-by: Chunyan Zhang +Cc: stable +Link: https://lore.kernel.org/r/20190905074151.5268-1-zhang.lyra@gmail.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/sprd_serial.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/tty/serial/sprd_serial.c ++++ b/drivers/tty/serial/sprd_serial.c +@@ -240,7 +240,7 @@ static inline void sprd_rx(struct uart_p + + if (lsr & (SPRD_LSR_BI | SPRD_LSR_PE | + SPRD_LSR_FE | SPRD_LSR_OE)) +- if (handle_lsr_errors(port, &lsr, &flag)) ++ if (handle_lsr_errors(port, &flag, &lsr)) + continue; + if (uart_handle_sysrq_char(port, ch)) + continue; diff --git a/queue-4.14/series b/queue-4.14/series index 6750af75354..bade85c401f 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -6,3 +6,7 @@ phy-renesas-rcar-gen3-usb2-disable-clearing-vbus-in-over-current.patch media-tm6000-double-free-if-usb-disconnect-while-streaming.patch xen-netfront-do-not-assume-sk_buff_head-list-is-empty-in-error-handling.patch net_sched-let-qdisc_put-accept-null-pointer.patch +kvm-coalesced_mmio-add-bounds-checking.patch +firmware-google-check-if-size-is-valid-when-decoding-vpd-data.patch +serial-sprd-correct-the-wrong-sequence-of-arguments.patch +tty-serial-atmel-reschedule-tx-after-rx-was-started.patch diff --git a/queue-4.14/tty-serial-atmel-reschedule-tx-after-rx-was-started.patch b/queue-4.14/tty-serial-atmel-reschedule-tx-after-rx-was-started.patch new file mode 100644 index 00000000000..36eda2a729c --- /dev/null +++ b/queue-4.14/tty-serial-atmel-reschedule-tx-after-rx-was-started.patch @@ -0,0 +1,34 @@ +From d2ace81bf902a9f11d52e59e5d232d2255a0e353 Mon Sep 17 00:00:00 2001 +From: Razvan Stefanescu +Date: Tue, 13 Aug 2019 10:40:25 +0300 +Subject: tty/serial: atmel: reschedule TX after RX was started + +From: Razvan Stefanescu + +commit d2ace81bf902a9f11d52e59e5d232d2255a0e353 upstream. + +When half-duplex RS485 communication is used, after RX is started, TX +tasklet still needs to be scheduled tasklet. This avoids console freezing +when more data is to be transmitted, if the serial communication is not +closed. + +Fixes: 69646d7a3689 ("tty/serial: atmel: RS485 HD w/DMA: enable RX after TX is stopped") +Signed-off-by: Razvan Stefanescu +Cc: stable +Link: https://lore.kernel.org/r/20190813074025.16218-1-razvan.stefanescu@microchip.com +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/atmel_serial.c | 1 - + 1 file changed, 1 deletion(-) + +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -1276,7 +1276,6 @@ atmel_handle_transmit(struct uart_port * + + atmel_port->hd_start_rx = false; + atmel_start_rx(port); +- return; + } + + atmel_tasklet_schedule(atmel_port, &atmel_port->tasklet_tx);