diff options
| author | Corey Minyard <corey@minyard.net> | 2025-04-10 13:54:56 -0500 |
|---|---|---|
| committer | Corey Minyard <corey@minyard.net> | 2025-05-07 17:25:48 -0500 |
| commit | 87105e07806767b81910d165441607c1461ba2b8 (patch) | |
| tree | c800f7e54e89858f256cb1f479d1bf292be8bc78 | |
| parent | ada2abaddad9c2c6557353b866c39e3aec9c8443 (diff) | |
| download | linux-87105e07806767b81910d165441607c1461ba2b8.tar.gz linux-87105e07806767b81910d165441607c1461ba2b8.zip | |
ipmi:msghandler: Don't deliver messages to deleted users
Check to see if they have been destroyed before trying to deliver a
message.
Signed-off-by: Corey Minyard <cminyard@mvista.com>
| -rw-r--r-- | drivers/char/ipmi/ipmi_msghandler.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 29aa52999a96..3cb72f6b12ea 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c @@ -1327,6 +1327,7 @@ static void _ipmi_destroy_user(struct ipmi_user *user) unsigned long flags; struct cmd_rcvr *rcvr; struct cmd_rcvr *rcvrs = NULL; + struct ipmi_recv_msg *msg, *msg2; if (!refcount_dec_if_one(&user->destroyed)) return; @@ -1377,6 +1378,15 @@ static void _ipmi_destroy_user(struct ipmi_user *user) kfree(rcvr); } + mutex_lock(&intf->user_msgs_mutex); + list_for_each_entry_safe(msg, msg2, &intf->user_msgs, link) { + if (msg->user != user) + continue; + list_del(&msg->link); + ipmi_free_recv_msg(msg); + } + mutex_unlock(&intf->user_msgs_mutex); + release_ipmi_user(user); } @@ -4844,8 +4854,22 @@ static void smi_work(struct work_struct *t) struct ipmi_user *user = msg->user; list_del(&msg->link); - atomic_dec(&user->nr_msgs); - user->handler->ipmi_recv_hndl(msg, user->handler_data); + + /* + * I would like for this check (and user->destroyed) + * to go away, but it's possible that an interface is + * processing a message that belongs to the user while + * the user is being deleted. When that response + * comes back, it could be queued after the user is + * destroyed. This is simpler than handling it in the + * interface. + */ + if (refcount_read(&user->destroyed) == 0) { + ipmi_free_recv_msg(msg); + } else { + atomic_dec(&user->nr_msgs); + user->handler->ipmi_recv_hndl(msg, user->handler_data); + } } mutex_unlock(&intf->user_msgs_mutex); |
