[PATCH v2 1/4] ipmi: msghandler: Add a limit for the number of users
From: Chen Guanqiao
Date: Tue Mar 29 2022 - 12:12:57 EST
The administrator sets the limit for the number of users by modifying
/sys/module/ipmi_msghandler/parameters/default_max_users.
Signed-off-by: Chen Guanqiao <chen.chenchacha@xxxxxxxxxxx>
---
drivers/char/ipmi/ipmi_msghandler.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index c59265146e9c..7886c8337368 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -145,6 +145,12 @@ module_param(default_max_retries, uint, 0644);
MODULE_PARM_DESC(default_max_retries,
"The time (milliseconds) between retry sends in maintenance mode");
+/* The default maximum number of users per intf */
+static unsigned int default_max_users = 50;
+module_param(default_max_users, uint, 0644);
+MODULE_PARM_DESC(default_max_users,
+ "The maximum number of users per interface");
+
/* Call every ~1000 ms. */
#define IPMI_TIMEOUT_TIME 1000
@@ -579,6 +585,9 @@ struct ipmi_smi {
atomic_t stats[IPMI_NUM_STATS];
+ /* The number of user in this interface */
+ atomic_t user_count;
+
/*
* run_to_completion duplicate of smb_info, smi_info
* and ipmi_serial_info structures. Used to decrease numbers of
@@ -1182,9 +1191,11 @@ static void free_user_work(struct work_struct *work)
{
struct ipmi_user *user = container_of(work, struct ipmi_user,
remove_work);
+ struct ipmi_smi *intf = user->intf;
cleanup_srcu_struct(&user->release_barrier);
vfree(user);
+ atomic_dec(&intf->user_count);
}
int ipmi_create_user(unsigned int if_num,
@@ -1230,6 +1241,12 @@ int ipmi_create_user(unsigned int if_num,
goto out_kfree;
found:
+ if (atomic_inc_return(&intf->user_count) > default_max_users) {
+ atomic_dec(&intf->user_count);
+ rv = -EBUSY;
+ goto out_kfree;
+ }
+
INIT_WORK(&new_user->remove_work, free_user_work);
rv = init_srcu_struct(&new_user->release_barrier);
@@ -3548,6 +3565,7 @@ int ipmi_add_smi(struct module *owner,
spin_lock_init(&intf->events_lock);
spin_lock_init(&intf->watch_lock);
atomic_set(&intf->event_waiters, 0);
+ atomic_set(&intf->user_count, 0);
intf->ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
INIT_LIST_HEAD(&intf->waiting_events);
intf->waiting_events_count = 0;
--
2.25.1