diff options
| -rw-r--r-- | lib/sys_info.c | 28 |
1 files changed, 16 insertions, 12 deletions
diff --git a/lib/sys_info.c b/lib/sys_info.c index 29a63238b31d..eb5c1226bfc8 100644 --- a/lib/sys_info.c +++ b/lib/sys_info.c @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only +#include <linux/array_size.h> #include <linux/bitops.h> +#include <linux/cleanup.h> #include <linux/console.h> #include <linux/log2.h> #include <linux/kernel.h> @@ -11,10 +13,6 @@ #include <linux/sys_info.h> -/* - * When 'si_names' gets updated, please make sure the 'sys_info_avail' - * below is updated accordingly. - */ static const char * const si_names[] = { [ilog2(SYS_INFO_TASKS)] = "tasks", [ilog2(SYS_INFO_MEM)] = "mem", @@ -45,25 +43,32 @@ unsigned long sys_info_parse_param(char *str) #ifdef CONFIG_SYSCTL -static const char sys_info_avail[] __maybe_unused = "tasks,mem,timers,locks,ftrace,all_bt,blocked_tasks"; - int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write, void *buffer, size_t *lenp, loff_t *ppos) { - char names[sizeof(sys_info_avail)]; struct ctl_table table; unsigned long *si_bits_global; unsigned long si_bits; + unsigned int i; + size_t maxlen; si_bits_global = ro_table->data; + maxlen = 0; + for (i = 0; i < ARRAY_SIZE(si_names); i++) + maxlen += strlen(si_names[i]) + 1; + + char *names __free(kfree) = kzalloc(maxlen, GFP_KERNEL); + if (!names) + return -ENOMEM; + if (write) { int ret; table = *ro_table; table.data = names; - table.maxlen = sizeof(names); + table.maxlen = maxlen; ret = proc_dostring(&table, write, buffer, lenp, ppos); if (ret) return ret; @@ -74,16 +79,15 @@ int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write, return 0; } else { /* for 'read' operation */ + unsigned int len = 0; char *delim = ""; - int i, len = 0; /* The access to the global value is not synchronized. */ si_bits = READ_ONCE(*si_bits_global); - names[0] = '\0'; for_each_set_bit(i, &si_bits, ARRAY_SIZE(si_names)) { if (*si_names[i]) { - len += scnprintf(names + len, sizeof(names) - len, + len += scnprintf(names + len, maxlen - len, "%s%s", delim, si_names[i]); delim = ","; } @@ -91,7 +95,7 @@ int sysctl_sys_info_handler(const struct ctl_table *ro_table, int write, table = *ro_table; table.data = names; - table.maxlen = sizeof(names); + table.maxlen = maxlen; return proc_dostring(&table, write, buffer, lenp, ppos); } } |
