linux-uconsole/drivers/char/ipmi
Junichi Nomura de0f9fa7a5 ipmi: Remove smi_msg from waiting_rcv_msgs list before handle_one_recv_msg()
commit ae4ea9a246 upstream.

Commit 7ea0ed2b5b ("ipmi: Make the message handler easier to use for
SMI interfaces") changed handle_new_recv_msgs() to call handle_one_recv_msg()
for a smi_msg while the smi_msg is still connected to waiting_rcv_msgs list.
That could lead to following list corruption problems:

1) low-level function treats smi_msg as not connected to list

  handle_one_recv_msg() could end up calling smi_send(), which
  assumes the msg is not connected to list.

  For example, the following sequence could corrupt list by
  doing list_add_tail() for the entry still connected to other list.

    handle_new_recv_msgs()
      msg = list_entry(waiting_rcv_msgs)
      handle_one_recv_msg(msg)
        handle_ipmb_get_msg_cmd(msg)
          smi_send(msg)
            spin_lock(xmit_msgs_lock)
            list_add_tail(msg)
            spin_unlock(xmit_msgs_lock)

2) race between multiple handle_new_recv_msgs() instances

  handle_new_recv_msgs() once releases waiting_rcv_msgs_lock before calling
  handle_one_recv_msg() then retakes the lock and list_del() it.

  If others call handle_new_recv_msgs() during the window shown below
  list_del() will be done twice for the same smi_msg.

  handle_new_recv_msgs()
    spin_lock(waiting_rcv_msgs_lock)
    msg = list_entry(waiting_rcv_msgs)
    spin_unlock(waiting_rcv_msgs_lock)
  |
  | handle_one_recv_msg(msg)
  |
    spin_lock(waiting_rcv_msgs_lock)
    list_del(msg)
    spin_unlock(waiting_rcv_msgs_lock)

Fixes: 7ea0ed2b5b ("ipmi: Make the message handler easier to use for SMI interfaces")
Signed-off-by: Jun'ichi Nomura <j-nomura@ce.jp.nec.com>
[Added a comment to describe why this works.]
Signed-off-by: Corey Minyard <cminyard@mvista.com>
Tested-by: Ye Feng <yefeng.yl@alibaba-inc.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2016-07-27 09:47:32 -07:00
..
ipmi_bt_sm.c ipmi: Make some data const that was only read 2015-09-03 15:02:27 -05:00
ipmi_devintf.c ipmi: Free ipmi_recv_msg messages from the linked list on close 2015-02-19 20:58:40 -06:00
ipmi_kcs_sm.c ipmi: Make some data const that was only read 2015-09-03 15:02:27 -05:00
ipmi_msghandler.c ipmi: Remove smi_msg from waiting_rcv_msgs list before handle_one_recv_msg() 2016-07-27 09:47:32 -07:00
ipmi_powernv.c impi:Remove unneeded setting of module owner to THIS_MODULE in the platform structure, powernv_ipmi_driver 2015-09-03 15:02:24 -05:00
ipmi_poweroff.c char: Convert use of typedef ctl_table to struct ctl_table 2013-06-17 16:43:08 -07:00
ipmi_si_intf.c ipmi: move timer init to before irq is setup 2015-12-09 13:13:06 -06:00
ipmi_si_sm.h ipmi: Make some data const that was only read 2015-09-03 15:02:27 -05:00
ipmi_smic_sm.c ipmi: Make some data const that was only read 2015-09-03 15:02:27 -05:00
ipmi_ssif.c char: ipmi: ipmi_ssif: Replace timeval with timespec64 2015-10-24 19:46:42 -07:00
ipmi_watchdog.c ipmi watchdog : add panic_wdt_timeout parameter 2015-11-16 06:28:43 -06:00
Kconfig drivers/char/ipmi: Add powernv IPMI driver 2014-12-11 15:04:12 -06:00
Makefile drivers/char/ipmi: Add powernv IPMI driver 2014-12-11 15:04:12 -06:00