]> git-server-git.apps.pok.os.sepia.ceph.com Git - ceph-client.git/commitdiff
ipmi:si: Fix check for a misbehaving BMC
authorCorey Minyard <corey@minyard.net>
Fri, 13 Feb 2026 06:15:04 +0000 (00:15 -0600)
committerCorey Minyard <corey@minyard.net>
Mon, 23 Feb 2026 15:00:48 +0000 (09:00 -0600)
There is a race on checking the state in the sender, it needs to be
checked under a lock.  But you also need a check to avoid issues with
a misbehaving BMC for run to completion mode.  So leave the check at
the beginning for run to completion, and add a check under the lock
to avoid the race.

Reported-by: Rafael J. Wysocki <rafael@kernel.org>
Fixes: bc3a9d217755 ("ipmi:si: Gracefully handle if the BMC is non-functional")
Cc: stable@vger.kernel.org # 4.18
Signed-off-by: Corey Minyard <corey@minyard.net>
Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
drivers/char/ipmi/ipmi_si_intf.c

index 3667033fcc51587f0942ae14c9000e5b8482b6f7..6eda61664aaa89776102f1763d7f1c113e50a3a2 100644 (file)
@@ -924,9 +924,14 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
 {
        struct smi_info   *smi_info = send_info;
        unsigned long     flags;
+       int rv = IPMI_CC_NO_ERROR;
 
        debug_timestamp(smi_info, "Enqueue");
 
+       /*
+        * Check here for run to completion mode.  A check under lock is
+        * later.
+        */
        if (smi_info->si_state == SI_HOSED)
                return IPMI_BUS_ERR;
 
@@ -940,18 +945,15 @@ static int sender(void *send_info, struct ipmi_smi_msg *msg)
        }
 
        spin_lock_irqsave(&smi_info->si_lock, flags);
-       /*
-        * The following two lines don't need to be under the lock for
-        * the lock's sake, but they do need SMP memory barriers to
-        * avoid getting things out of order.  We are already claiming
-        * the lock, anyway, so just do it under the lock to avoid the
-        * ordering problem.
-        */
-       BUG_ON(smi_info->waiting_msg);
-       smi_info->waiting_msg = msg;
-       check_start_timer_thread(smi_info);
+       if (smi_info->si_state == SI_HOSED) {
+               rv = IPMI_BUS_ERR;
+       } else {
+               BUG_ON(smi_info->waiting_msg);
+               smi_info->waiting_msg = msg;
+               check_start_timer_thread(smi_info);
+       }
        spin_unlock_irqrestore(&smi_info->si_lock, flags);
-       return IPMI_CC_NO_ERROR;
+       return rv;
 }
 
 static void set_run_to_completion(void *send_info, bool i_run_to_completion)