--- /dev/null
+From 913a89f009d98c85a902d718cd54bb32ab11d167 Mon Sep 17 00:00:00 2001
+From: Corey Minyard <cminyard@mvista.com>
+Date: Thu, 20 Dec 2018 16:50:23 -0600
+Subject: ipmi: Don't initialize anything in the core until something uses it
+
+From: Corey Minyard <cminyard@mvista.com>
+
+commit 913a89f009d98c85a902d718cd54bb32ab11d167 upstream.
+
+The IPMI driver was recently modified to use SRCU, but it turns out
+this uses a chunk of percpu memory, even if IPMI is never used.
+
+So modify thing to on initialize on the first use. There was already
+code to sort of handle this for handling init races, so piggy back
+on top of that, and simplify it in the process.
+
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Reported-by: Tejun Heo <tj@kernel.org>
+Cc: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Reviewed-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
+Cc: stable@vger.kernel.org # 4.18
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_msghandler.c | 143 ++++++++++++++++++++----------------
+ 1 file changed, 80 insertions(+), 63 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -62,7 +62,8 @@ static void ipmi_debug_msg(const char *t
+ { }
+ #endif
+
+-static int initialized;
++static bool initialized;
++static bool drvregistered;
+
+ enum ipmi_panic_event_op {
+ IPMI_SEND_PANIC_EVENT_NONE,
+@@ -612,7 +613,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
+
+ static LIST_HEAD(ipmi_interfaces);
+ static DEFINE_MUTEX(ipmi_interfaces_mutex);
+-DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
++struct srcu_struct ipmi_interfaces_srcu;
+
+ /*
+ * List of watchers that want to know when smi's are added and deleted.
+@@ -720,7 +721,15 @@ struct watcher_entry {
+ int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
+ {
+ struct ipmi_smi *intf;
+- int index;
++ int index, rv;
++
++ /*
++ * Make sure the driver is actually initialized, this handles
++ * problems with initialization order.
++ */
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
+
+ mutex_lock(&smi_watchers_mutex);
+
+@@ -1076,7 +1085,7 @@ int ipmi_create_user(unsigned int
+ {
+ unsigned long flags;
+ struct ipmi_user *new_user;
+- int rv = 0, index;
++ int rv, index;
+ struct ipmi_smi *intf;
+
+ /*
+@@ -1094,18 +1103,9 @@ int ipmi_create_user(unsigned int
+ * Make sure the driver is actually initialized, this handles
+ * problems with initialization order.
+ */
+- if (!initialized) {
+- rv = ipmi_init_msghandler();
+- if (rv)
+- return rv;
+-
+- /*
+- * The init code doesn't return an error if it was turned
+- * off, but it won't initialize. Check that.
+- */
+- if (!initialized)
+- return -ENODEV;
+- }
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
+
+ new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
+ if (!new_user)
+@@ -3291,17 +3291,9 @@ int ipmi_register_smi(const struct ipmi_
+ * Make sure the driver is actually initialized, this handles
+ * problems with initialization order.
+ */
+- if (!initialized) {
+- rv = ipmi_init_msghandler();
+- if (rv)
+- return rv;
+- /*
+- * The init code doesn't return an error if it was turned
+- * off, but it won't initialize. Check that.
+- */
+- if (!initialized)
+- return -ENODEV;
+- }
++ rv = ipmi_init_msghandler();
++ if (rv)
++ return rv;
+
+ intf = kzalloc(sizeof(*intf), GFP_KERNEL);
+ if (!intf)
+@@ -5017,6 +5009,22 @@ static int panic_event(struct notifier_b
+ return NOTIFY_DONE;
+ }
+
++/* Must be called with ipmi_interfaces_mutex held. */
++static int ipmi_register_driver(void)
++{
++ int rv;
++
++ if (drvregistered)
++ return 0;
++
++ rv = driver_register(&ipmidriver.driver);
++ if (rv)
++ pr_err("Could not register IPMI driver\n");
++ else
++ drvregistered = true;
++ return rv;
++}
++
+ static struct notifier_block panic_block = {
+ .notifier_call = panic_event,
+ .next = NULL,
+@@ -5027,66 +5035,75 @@ static int ipmi_init_msghandler(void)
+ {
+ int rv;
+
++ mutex_lock(&ipmi_interfaces_mutex);
++ rv = ipmi_register_driver();
++ if (rv)
++ goto out;
+ if (initialized)
+- return 0;
++ goto out;
+
+- rv = driver_register(&ipmidriver.driver);
+- if (rv) {
+- pr_err("Could not register IPMI driver\n");
+- return rv;
+- }
+-
+- pr_info("version " IPMI_DRIVER_VERSION "\n");
++ init_srcu_struct(&ipmi_interfaces_srcu);
+
+ timer_setup(&ipmi_timer, ipmi_timeout, 0);
+ mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
+
+ atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
+
+- initialized = 1;
++ initialized = true;
+
+- return 0;
++out:
++ mutex_unlock(&ipmi_interfaces_mutex);
++ return rv;
+ }
+
+ static int __init ipmi_init_msghandler_mod(void)
+ {
+- ipmi_init_msghandler();
+- return 0;
++ int rv;
++
++ pr_info("version " IPMI_DRIVER_VERSION "\n");
++
++ mutex_lock(&ipmi_interfaces_mutex);
++ rv = ipmi_register_driver();
++ mutex_unlock(&ipmi_interfaces_mutex);
++
++ return rv;
+ }
+
+ static void __exit cleanup_ipmi(void)
+ {
+ int count;
+
+- if (!initialized)
+- return;
+-
+- atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
++ if (initialized) {
++ atomic_notifier_chain_unregister(&panic_notifier_list,
++ &panic_block);
+
+- /*
+- * This can't be called if any interfaces exist, so no worry
+- * about shutting down the interfaces.
+- */
++ /*
++ * This can't be called if any interfaces exist, so no worry
++ * about shutting down the interfaces.
++ */
+
+- /*
+- * Tell the timer to stop, then wait for it to stop. This
+- * avoids problems with race conditions removing the timer
+- * here.
+- */
+- atomic_inc(&stop_operation);
+- del_timer_sync(&ipmi_timer);
++ /*
++ * Tell the timer to stop, then wait for it to stop. This
++ * avoids problems with race conditions removing the timer
++ * here.
++ */
++ atomic_inc(&stop_operation);
++ del_timer_sync(&ipmi_timer);
+
+- driver_unregister(&ipmidriver.driver);
++ initialized = false;
+
+- initialized = 0;
++ /* Check for buffer leaks. */
++ count = atomic_read(&smi_msg_inuse_count);
++ if (count != 0)
++ pr_warn("SMI message count %d at exit\n", count);
++ count = atomic_read(&recv_msg_inuse_count);
++ if (count != 0)
++ pr_warn("recv message count %d at exit\n", count);
+
+- /* Check for buffer leaks. */
+- count = atomic_read(&smi_msg_inuse_count);
+- if (count != 0)
+- pr_warn("SMI message count %d at exit\n", count);
+- count = atomic_read(&recv_msg_inuse_count);
+- if (count != 0)
+- pr_warn("recv message count %d at exit\n", count);
++ cleanup_srcu_struct(&ipmi_interfaces_srcu);
++ }
++ if (drvregistered)
++ driver_unregister(&ipmidriver.driver);
+ }
+ module_exit(cleanup_ipmi);
+
--- /dev/null
+From 77f8269606bf95fcb232ee86f6da80886f1dfae8 Mon Sep 17 00:00:00 2001
+From: Yang Yingliang <yangyingliang@huawei.com>
+Date: Wed, 16 Jan 2019 13:33:22 +0800
+Subject: ipmi: fix use-after-free of user->release_barrier.rda
+
+From: Yang Yingliang <yangyingliang@huawei.com>
+
+commit 77f8269606bf95fcb232ee86f6da80886f1dfae8 upstream.
+
+When we do the following test, we got oops in ipmi_msghandler driver
+while((1))
+do
+ service ipmievd restart & service ipmievd restart
+done
+
+---------------------------------------------------------------
+[ 294.230186] Unable to handle kernel paging request at virtual address 0000803fea6ea008
+[ 294.230188] Mem abort info:
+[ 294.230190] ESR = 0x96000004
+[ 294.230191] Exception class = DABT (current EL), IL = 32 bits
+[ 294.230193] SET = 0, FnV = 0
+[ 294.230194] EA = 0, S1PTW = 0
+[ 294.230195] Data abort info:
+[ 294.230196] ISV = 0, ISS = 0x00000004
+[ 294.230197] CM = 0, WnR = 0
+[ 294.230199] user pgtable: 4k pages, 48-bit VAs, pgdp = 00000000a1c1b75a
+[ 294.230201] [0000803fea6ea008] pgd=0000000000000000
+[ 294.230204] Internal error: Oops: 96000004 [#1] SMP
+[ 294.235211] Modules linked in: nls_utf8 isofs rpcrdma ib_iser ib_srpt target_core_mod ib_srp scsi_transport_srp ib_ipoib rdma_ucm ib_umad rdma_cm ib_cm iw_cm dm_mirror dm_region_hash dm_log dm_mod aes_ce_blk crypto_simd cryptd aes_ce_cipher ghash_ce sha2_ce ses sha256_arm64 sha1_ce hibmc_drm hisi_sas_v2_hw enclosure sg hisi_sas_main sbsa_gwdt ip_tables mlx5_ib ib_uverbs marvell ib_core mlx5_core ixgbe ipmi_si mdio hns_dsaf ipmi_devintf ipmi_msghandler hns_enet_drv hns_mdio
+[ 294.277745] CPU: 3 PID: 0 Comm: swapper/3 Kdump: loaded Not tainted 5.0.0-rc2+ #113
+[ 294.285511] Hardware name: Huawei TaiShan 2280 /BC11SPCD, BIOS 1.37 11/21/2017
+[ 294.292835] pstate: 80000005 (Nzcv daif -PAN -UAO)
+[ 294.297695] pc : __srcu_read_lock+0x38/0x58
+[ 294.301940] lr : acquire_ipmi_user+0x2c/0x70 [ipmi_msghandler]
+[ 294.307853] sp : ffff00001001bc80
+[ 294.311208] x29: ffff00001001bc80 x28: ffff0000117e5000
+[ 294.316594] x27: 0000000000000000 x26: dead000000000100
+[ 294.321980] x25: dead000000000200 x24: ffff803f6bd06800
+[ 294.327366] x23: 0000000000000000 x22: 0000000000000000
+[ 294.332752] x21: ffff00001001bd04 x20: ffff80df33d19018
+[ 294.338137] x19: ffff80df33d19018 x18: 0000000000000000
+[ 294.343523] x17: 0000000000000000 x16: 0000000000000000
+[ 294.348908] x15: 0000000000000000 x14: 0000000000000002
+[ 294.354293] x13: 0000000000000000 x12: 0000000000000000
+[ 294.359679] x11: 0000000000000000 x10: 0000000000100000
+[ 294.365065] x9 : 0000000000000000 x8 : 0000000000000004
+[ 294.370451] x7 : 0000000000000000 x6 : ffff80df34558678
+[ 294.375836] x5 : 000000000000000c x4 : 0000000000000000
+[ 294.381221] x3 : 0000000000000001 x2 : 0000803fea6ea000
+[ 294.386607] x1 : 0000803fea6ea008 x0 : 0000000000000001
+[ 294.391994] Process swapper/3 (pid: 0, stack limit = 0x0000000083087293)
+[ 294.398791] Call trace:
+[ 294.401266] __srcu_read_lock+0x38/0x58
+[ 294.405154] acquire_ipmi_user+0x2c/0x70 [ipmi_msghandler]
+[ 294.410716] deliver_response+0x80/0xf8 [ipmi_msghandler]
+[ 294.416189] deliver_local_response+0x28/0x68 [ipmi_msghandler]
+[ 294.422193] handle_one_recv_msg+0x158/0xcf8 [ipmi_msghandler]
+[ 294.432050] handle_new_recv_msgs+0xc0/0x210 [ipmi_msghandler]
+[ 294.441984] smi_recv_tasklet+0x8c/0x158 [ipmi_msghandler]
+[ 294.451618] tasklet_action_common.isra.5+0x88/0x138
+[ 294.460661] tasklet_action+0x2c/0x38
+[ 294.468191] __do_softirq+0x120/0x2f8
+[ 294.475561] irq_exit+0x134/0x140
+[ 294.482445] __handle_domain_irq+0x6c/0xc0
+[ 294.489954] gic_handle_irq+0xb8/0x178
+[ 294.497037] el1_irq+0xb0/0x140
+[ 294.503381] arch_cpu_idle+0x34/0x1a8
+[ 294.510096] do_idle+0x1d4/0x290
+[ 294.516322] cpu_startup_entry+0x28/0x30
+[ 294.523230] secondary_start_kernel+0x184/0x1d0
+[ 294.530657] Code: d538d082 d2800023 8b010c81 8b020021 (c85f7c25)
+[ 294.539746] ---[ end trace 8a7a880dee570b29 ]---
+[ 294.547341] Kernel panic - not syncing: Fatal exception in interrupt
+[ 294.556837] SMP: stopping secondary CPUs
+[ 294.563996] Kernel Offset: disabled
+[ 294.570515] CPU features: 0x002,21006008
+[ 294.577638] Memory Limit: none
+[ 294.587178] Starting crashdump kernel...
+[ 294.594314] Bye!
+
+Because the user->release_barrier.rda is freed in ipmi_destroy_user(), but
+the refcount is not zero, when acquire_ipmi_user() uses user->release_barrier.rda
+in __srcu_read_lock(), it causes oops.
+Fix this by calling cleanup_srcu_struct() when the refcount is zero.
+
+Fixes: e86ee2d44b44 ("ipmi: Rework locking and shutdown for hot remove")
+Cc: stable@vger.kernel.org # 4.18
+Signed-off-by: Yang Yingliang <yangyingliang@huawei.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_msghandler.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -1183,6 +1183,7 @@ EXPORT_SYMBOL(ipmi_get_smi_info);
+ static void free_user(struct kref *ref)
+ {
+ struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
++ cleanup_srcu_struct(&user->release_barrier);
+ kfree(user);
+ }
+
+@@ -1259,7 +1260,6 @@ int ipmi_destroy_user(struct ipmi_user *
+ {
+ _ipmi_destroy_user(user);
+
+- cleanup_srcu_struct(&user->release_barrier);
+ kref_put(&user->refcount, free_user);
+
+ return 0;
--- /dev/null
+From a7102c7461794a5bb31af24b08e9e0f50038897a Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <gustavo@embeddedor.com>
+Date: Wed, 9 Jan 2019 17:39:06 -0600
+Subject: ipmi: msghandler: Fix potential Spectre v1 vulnerabilities
+
+From: Gustavo A. R. Silva <gustavo@embeddedor.com>
+
+commit a7102c7461794a5bb31af24b08e9e0f50038897a upstream.
+
+channel and addr->channel are indirectly controlled by user-space,
+hence leading to a potential exploitation of the Spectre variant 1
+vulnerability.
+
+These issues were detected with the help of Smatch:
+
+drivers/char/ipmi/ipmi_msghandler.c:1381 ipmi_set_my_address() warn: potential spectre issue 'user->intf->addrinfo' [w] (local cap)
+drivers/char/ipmi/ipmi_msghandler.c:1401 ipmi_get_my_address() warn: potential spectre issue 'user->intf->addrinfo' [r] (local cap)
+drivers/char/ipmi/ipmi_msghandler.c:1421 ipmi_set_my_LUN() warn: potential spectre issue 'user->intf->addrinfo' [w] (local cap)
+drivers/char/ipmi/ipmi_msghandler.c:1441 ipmi_get_my_LUN() warn: potential spectre issue 'user->intf->addrinfo' [r] (local cap)
+drivers/char/ipmi/ipmi_msghandler.c:2260 check_addr() warn: potential spectre issue 'intf->addrinfo' [r] (local cap)
+
+Fix this by sanitizing channel and addr->channel before using them to
+index user->intf->addrinfo and intf->addrinfo, correspondingly.
+
+Notice that given that speculation windows are large, the policy is
+to kill the speculation on the first load and not worry if it can be
+completed with a dependent load/store [1].
+
+[1] https://lore.kernel.org/lkml/20180423164740.GY17484@dhcp22.suse.cz/
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_msghandler.c | 26 ++++++++++++++++++--------
+ 1 file changed, 18 insertions(+), 8 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -32,6 +32,7 @@
+ #include <linux/moduleparam.h>
+ #include <linux/workqueue.h>
+ #include <linux/uuid.h>
++#include <linux/nospec.h>
+
+ #define IPMI_DRIVER_VERSION "39.2"
+
+@@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user
+ if (!user)
+ return -ENODEV;
+
+- if (channel >= IPMI_MAX_CHANNELS)
++ if (channel >= IPMI_MAX_CHANNELS) {
+ rv = -EINVAL;
+- else
++ } else {
++ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
+ user->intf->addrinfo[channel].address = address;
++ }
+ release_ipmi_user(user, index);
+
+ return rv;
+@@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user
+ if (!user)
+ return -ENODEV;
+
+- if (channel >= IPMI_MAX_CHANNELS)
++ if (channel >= IPMI_MAX_CHANNELS) {
+ rv = -EINVAL;
+- else
++ } else {
++ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
+ *address = user->intf->addrinfo[channel].address;
++ }
+ release_ipmi_user(user, index);
+
+ return rv;
+@@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *us
+ if (!user)
+ return -ENODEV;
+
+- if (channel >= IPMI_MAX_CHANNELS)
++ if (channel >= IPMI_MAX_CHANNELS) {
+ rv = -EINVAL;
+- else
++ } else {
++ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
+ user->intf->addrinfo[channel].lun = LUN & 0x3;
++ }
+ release_ipmi_user(user, index);
+
+ return rv;
+@@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *us
+ if (!user)
+ return -ENODEV;
+
+- if (channel >= IPMI_MAX_CHANNELS)
++ if (channel >= IPMI_MAX_CHANNELS) {
+ rv = -EINVAL;
+- else
++ } else {
++ channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
+ *address = user->intf->addrinfo[channel].lun;
++ }
+ release_ipmi_user(user, index);
+
+ return rv;
+@@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi *
+ {
+ if (addr->channel >= IPMI_MAX_CHANNELS)
+ return -EINVAL;
++ addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS);
+ *lun = intf->addrinfo[addr->channel].lun;
+ *saddr = intf->addrinfo[addr->channel].address;
+ return 0;
--- /dev/null
+From 479d6b39b9e0d2de648ebf146f23a1e40962068f Mon Sep 17 00:00:00 2001
+From: Fred Klassen <fklassen@appneta.com>
+Date: Sat, 19 Jan 2019 14:28:18 -0800
+Subject: ipmi: Prevent use-after-free in deliver_response
+
+From: Fred Klassen <fklassen@appneta.com>
+
+commit 479d6b39b9e0d2de648ebf146f23a1e40962068f upstream.
+
+Some IPMI modules (e.g. ibmpex_msg_handler()) will have ipmi_usr_hdlr
+handlers that call ipmi_free_recv_msg() directly. This will essentially
+kfree(msg), leading to use-after-free.
+
+This does not happen in the ipmi_devintf module, which will queue the
+message and run ipmi_free_recv_msg() later.
+
+BUG: KASAN: use-after-free in deliver_response+0x12f/0x1b0
+Read of size 8 at addr ffff888a7bf20018 by task ksoftirqd/3/27
+CPU: 3 PID: 27 Comm: ksoftirqd/3 Tainted: G O 4.19.11-amd64-ani99-debug #12.0.1.601133+pv
+Hardware name: AppNeta r1000/X11SPW-TF, BIOS 2.1a-AP 09/17/2018
+Call Trace:
+dump_stack+0x92/0xeb
+print_address_description+0x73/0x290
+kasan_report+0x258/0x380
+deliver_response+0x12f/0x1b0
+? ipmi_free_recv_msg+0x50/0x50
+deliver_local_response+0xe/0x50
+handle_one_recv_msg+0x37a/0x21d0
+handle_new_recv_msgs+0x1ce/0x440
+...
+
+Allocated by task 9885:
+kasan_kmalloc+0xa0/0xd0
+kmem_cache_alloc_trace+0x116/0x290
+ipmi_alloc_recv_msg+0x28/0x70
+i_ipmi_request+0xb4a/0x1640
+ipmi_request_settime+0x1b8/0x1e0
+...
+
+Freed by task 27:
+__kasan_slab_free+0x12e/0x180
+kfree+0xe9/0x280
+deliver_response+0x122/0x1b0
+deliver_local_response+0xe/0x50
+handle_one_recv_msg+0x37a/0x21d0
+handle_new_recv_msgs+0x1ce/0x440
+tasklet_action_common.isra.19+0xc4/0x250
+__do_softirq+0x11f/0x51f
+
+Fixes: e86ee2d44b44 ("ipmi: Rework locking and shutdown for hot remove")
+Cc: stable@vger.kernel.org # 4.18
+Signed-off-by: Fred Klassen <fklassen@appneta.com>
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_msghandler.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/char/ipmi/ipmi_msghandler.c
++++ b/drivers/char/ipmi/ipmi_msghandler.c
+@@ -894,7 +894,7 @@ static int deliver_response(struct ipmi_
+
+ if (user) {
+ user->handler->ipmi_recv_hndl(msg, user->handler_data);
+- release_ipmi_user(msg->user, index);
++ release_ipmi_user(user, index);
+ } else {
+ /* User went away, give up. */
+ ipmi_free_recv_msg(msg);
--- /dev/null
+From 7d6380cd40f7993f75c4bde5b36f6019237e8719 Mon Sep 17 00:00:00 2001
+From: Corey Minyard <cminyard@mvista.com>
+Date: Fri, 16 Nov 2018 09:59:21 -0600
+Subject: ipmi:ssif: Fix handling of multi-part return messages
+
+From: Corey Minyard <cminyard@mvista.com>
+
+commit 7d6380cd40f7993f75c4bde5b36f6019237e8719 upstream.
+
+The block number was not being compared right, it was off by one
+when checking the response.
+
+Some statistics wouldn't be incremented properly in some cases.
+
+Check to see if that middle-part messages always have 31 bytes of
+data.
+
+Signed-off-by: Corey Minyard <cminyard@mvista.com>
+Cc: stable@vger.kernel.org # 4.4
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/char/ipmi/ipmi_ssif.c | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+--- a/drivers/char/ipmi/ipmi_ssif.c
++++ b/drivers/char/ipmi/ipmi_ssif.c
+@@ -632,8 +632,9 @@ static void msg_done_handler(struct ssif
+
+ /* Remove the multi-part read marker. */
+ len -= 2;
++ data += 2;
+ for (i = 0; i < len; i++)
+- ssif_info->data[i] = data[i+2];
++ ssif_info->data[i] = data[i];
+ ssif_info->multi_len = len;
+ ssif_info->multi_pos = 1;
+
+@@ -661,8 +662,19 @@ static void msg_done_handler(struct ssif
+ }
+
+ blocknum = data[0];
++ len--;
++ data++;
++
++ if (blocknum != 0xff && len != 31) {
++ /* All blocks but the last must have 31 data bytes. */
++ result = -EIO;
++ if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
++ pr_info("Received middle message <31\n");
+
+- if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
++ goto continue_op;
++ }
++
++ if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
+ /* Received message too big, abort the operation. */
+ result = -E2BIG;
+ if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+@@ -671,16 +683,14 @@ static void msg_done_handler(struct ssif
+ goto continue_op;
+ }
+
+- /* Remove the blocknum from the data. */
+- len--;
+ for (i = 0; i < len; i++)
+- ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
++ ssif_info->data[i + ssif_info->multi_len] = data[i];
+ ssif_info->multi_len += len;
+ if (blocknum == 0xff) {
+ /* End of read */
+ len = ssif_info->multi_len;
+ data = ssif_info->data;
+- } else if (blocknum + 1 != ssif_info->multi_pos) {
++ } else if (blocknum != ssif_info->multi_pos) {
+ /*
+ * Out of sequence block, just abort. Block
+ * numbers start at zero for the second block,
+@@ -707,6 +717,7 @@ static void msg_done_handler(struct ssif
+ }
+ }
+
++ continue_op:
+ if (result < 0) {
+ ssif_inc_stat(ssif_info, receive_errors);
+ } else {
+@@ -714,8 +725,6 @@ static void msg_done_handler(struct ssif
+ ssif_inc_stat(ssif_info, received_message_parts);
+ }
+
+-
+- continue_op:
+ if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
+ pr_info("DONE 1: state = %d, result=%d\n",
+ ssif_info->ssif_state, result);
mm-memblock.c-skip-kmemleak-for-kasan_init.patch
drm-amd-display-fix-disabled-cursor-on-top-screen-edge.patch
bluetooth-fix-unnecessary-error-message-for-hci-request-completion.patch
+ipmi-fix-use-after-free-of-user-release_barrier.rda.patch
+ipmi-don-t-initialize-anything-in-the-core-until-something-uses-it.patch
+ipmi-msghandler-fix-potential-spectre-v1-vulnerabilities.patch
+ipmi-prevent-use-after-free-in-deliver_response.patch
+ipmi-ssif-fix-handling-of-multi-part-return-messages.patch