summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorey Minyard <corey@minyard.net>2025-04-10 13:54:56 -0500
committerCorey Minyard <corey@minyard.net>2025-05-07 17:25:48 -0500
commit87105e07806767b81910d165441607c1461ba2b8 (patch)
treec800f7e54e89858f256cb1f479d1bf292be8bc78
parentada2abaddad9c2c6557353b866c39e3aec9c8443 (diff)
downloadlinux-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.c28
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);