nss-packages-qosmio/qca-nss-clients/patches-11.4/0032-match-fix-procfs-read-write.patch
Sean Khan 6f823a2b34 treewide: Initial support for kernel 6.12 + GCC 15.1
Signed-off-by: Sean Khan <datapronix@protonmail.com>
2025-05-08 23:12:18 -04:00

407 lines
12 KiB
Diff

--- a/match/nss_match_cmd.c
+++ b/match/nss_match_cmd.c
@@ -127,29 +127,30 @@ static enum nss_match_profile_type nss_m
static int nss_match_cmd_procfs_config_handler(compat_const struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos)
{
char *command_str, *token, *param, *value;
- char *input_msg, *input_msg_orig;
+ char *input_msg, *pos;
nss_match_cmd_t command;
struct nss_ctx_instance *nss_ctx = nss_match_get_context();
size_t count = *lenp;
int ret = proc_dostring(ctl, write, buffer, lenp, ppos);
+ char cmd_buf[100] = {0}; /* Use a fixed buffer size matching nss_match_data */
if (!write) {
return ret;
}
- input_msg = (char *)kzalloc(count + 1, GFP_KERNEL);
- if (!input_msg) {
- nss_match_warn("%px: Dynamic allocation falied while writing input message from file", ctl);
- return -ENOMEM;
+ if (count >= sizeof(cmd_buf)) {
+ nss_match_warn("%px: Input too large: %zu\n", ctl, count);
+ return -EINVAL;
}
- input_msg_orig = input_msg;
- if (copy_from_user(input_msg, buffer, count)) {
- kfree(input_msg);
- nss_match_warn("%px: Cannot copy user's entry to kernel memory\n", ctl);
- return -EFAULT;
+ memcpy(cmd_buf, buffer, count);
+ cmd_buf[count] = '\0'; /* Ensure null termination */
+
+ if ((pos = strrchr(cmd_buf, '\n')) != NULL) {
+ *pos = '\0';
}
+ input_msg = cmd_buf;
command_str = strsep(&input_msg, " ");
command = nss_match_cmd_parse(command_str);
@@ -161,20 +162,17 @@ static int nss_match_cmd_procfs_config_h
profile_type = nss_match_cmd_get_profile_type(input_msg);
if (profile_type == NSS_MATCH_PROFILE_TYPE_NONE) {
pr_warn("%px: Please provide a valid profile type\n", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
table_id = nss_match_instance_create();
if (table_id <= 0) {
pr_warn("%px: Cannot create a new match instance\n", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
nss_match_db_profile_type_add(profile_type, table_id);
pr_warn("%px: New match instance created, table_id = %d\n", ctl, table_id);
- kfree(input_msg_orig);
return count;
}
@@ -194,32 +192,27 @@ static int nss_match_cmd_procfs_config_h
ret = sscanf(value, "%u", &table_id);
if (!ret) {
pr_warn("%px: Cannot convert to integer. Wrong input!!", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
}
if (table_id == 0 || table_id > NSS_MATCH_INSTANCE_MAX) {
pr_warn("%px: Invalid table_id %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (nss_match_db_table_validate(table_id)) {
pr_warn("%px: Table is already configured, %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (nss_match_db_parse_cmd(table_id, input_msg, &input_mask_param, NSS_MATCH_ADD_MASK)) {
- kfree(input_msg_orig);
return -EINVAL;
}
nss_match_db_mask_add(&input_mask_param.msg.configure_msg, table_id);
pr_warn("%px: Mask added to instance successfully. %d", ctl, table_id);
- kfree(input_msg_orig);
return count;
}
@@ -240,43 +233,36 @@ static int nss_match_cmd_procfs_config_h
ret = sscanf(value, "%u", &table_id);
if (!ret) {
pr_warn("%px: Cannot convert to integer. Wrong input!!", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
}
if ((table_id == 0) || (table_id > NSS_MATCH_INSTANCE_MAX)) {
pr_warn("%px: Invalid table_id %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (nss_match_db_table_validate(table_id)) {
pr_warn("%px: Table is already configured, %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (!nss_match_db_instance_config_get(&config_msg, &if_num, table_id)) {
pr_warn("%px: Unable to fetch stored configuration %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (if_num < 0) {
nss_match_warn("%px: Incorrect interface number: %d\n", ctl, if_num);
- kfree(input_msg_orig);
return -EINVAL;
}
if (nss_match_cmd_enable_instance(&config_msg, if_num, table_id)) {
pr_warn("%px: Failed to enable table %d\n", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
pr_warn("%px: Table %d enabled successfully\n", ctl, table_id);
- kfree(input_msg_orig);
return count;
}
@@ -298,14 +284,12 @@ static int nss_match_cmd_procfs_config_h
ret = sscanf(value, "%u", &table_id);
if (!ret) {
pr_warn("%px: Cannot convert to integer. Wrong input!!", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
}
if (table_id == 0 || table_id > NSS_MATCH_INSTANCE_MAX) {
pr_warn("%px: Invalid table_id: %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
@@ -313,7 +297,6 @@ static int nss_match_cmd_procfs_config_h
if (nss_match_db_parse_cmd(table_id, input_msg, &input_rule_param, NSS_MATCH_ADD_RULE)) {
pr_warn("%px: Wrong input", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
@@ -325,12 +308,10 @@ static int nss_match_cmd_procfs_config_h
if (rule_id < 0) {
pr_warn("%px: Failed to add rule into table %d.\n", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
pr_warn("%px: Rule added to table %d successfully with rule_id: %d\n", ctl, table_id, rule_id);
- kfree(input_msg_orig);
return count;
}
@@ -352,7 +333,6 @@ static int nss_match_cmd_procfs_config_h
if (!(strncasecmp(param, "rule_id", strlen("rule_id")))) {
if (!sscanf(token, "%hu", &rule_id)) {
pr_warn("%px: Cannot convert to integer. Wrong input\n", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
continue;
@@ -361,36 +341,30 @@ static int nss_match_cmd_procfs_config_h
if (!strncasecmp(param, "table_id", strlen("table_id"))) {
if (!sscanf(token, "%u", &table_id)) {
pr_warn("%px: Cannot convert to integer. Wrong input!!", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
continue;
}
- kfree(input_msg_orig);
return -EINVAL;
}
if (table_id == 0 || table_id > NSS_MATCH_INSTANCE_MAX) {
pr_warn("%px: Invalid table_id: %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (rule_id == 0 || rule_id > NSS_MATCH_INSTANCE_RULE_MAX) {
pr_warn("%px: Invalid rule_id: %d", ctl, rule_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (nss_match_rule_delete(nss_ctx, rule_id, table_id)) {
pr_warn("%px: Failed to delete rule from table %d.\n", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
pr_warn("%px: Rule deleted from table %d successfully\n", ctl, table_id);
- kfree(input_msg_orig);
return count;
}
@@ -410,39 +384,33 @@ static int nss_match_cmd_procfs_config_h
ret = sscanf(token, "%u", &table_id);
if (!ret) {
pr_warn("%px: Cannot convert to integer. Wrong input!!", input_msg);
- kfree(input_msg_orig);
return -EINVAL;
}
}
if (table_id == 0 || table_id > NSS_MATCH_INSTANCE_MAX) {
pr_warn("%px: Invalid table_id: %d", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
if (nss_match_instance_destroy(table_id)) {
pr_warn("%px: Failed to destroy table %d\n", ctl, table_id);
- kfree(input_msg_orig);
return -EINVAL;
}
pr_warn("%px: Table %d destroyed successfully.\n", ctl, table_id);
- kfree(input_msg_orig);
return count;
}
default:
{
pr_warn("%px: Input command is not as per syntax, Please enter a valid command", ctl);
- kfree(input_msg_orig);
return -EINVAL;
}
}
fail:
pr_warn("%px: Wrong input, check help. (cat /proc/sys/dev/nss/match/help)", ctl);
- kfree(input_msg_orig);
return ret;
}
@@ -456,11 +424,12 @@ static int nss_match_cmd_procfs_reset_ne
struct net_device *dev;
uint32_t if_num, type = 0;
int ret;
- char *dev_name;
- char *cmd_buf = nss_match_data;
+ char *pos;
+ char cmd_buf[IFNAMSIZ] = {0};
nss_tx_status_t nss_tx_status;
struct nss_ctx_instance *nss_ctx = nss_match_get_context();
struct nss_ctx_instance *wifili_nss_ctx = nss_wifili_get_context();
+ size_t count = *lenp;
if (!nss_ctx || !wifili_nss_ctx) {
pr_warn("%px: NSS Context not found. wifili_nss_ctx: %px. Reset nexthop failed", nss_ctx, wifili_nss_ctx);
@@ -473,19 +442,30 @@ static int nss_match_cmd_procfs_reset_ne
return ret;
}
+ if (count >= sizeof(cmd_buf)) {
+ nss_match_warn("%px: Input too large: %zu\n", ctl, count);
+ return -EINVAL;
+ }
+
+ memcpy(cmd_buf, buffer, count);
+ cmd_buf[count] = '\0'; /* Ensure null termination */
+
+ if ((pos = strrchr(cmd_buf, '\n')) != NULL) {
+ *pos = '\0';
+ }
+
/*
* Parse and read the devname from command.
*/
- dev_name = strsep(&cmd_buf, "\0");
- dev = dev_get_by_name(&init_net, dev_name);
+ dev = dev_get_by_name(&init_net, cmd_buf);
if (!dev) {
- pr_warn("%px: Cannot find the net device: %s. Reset nexthop failed.\n", nss_ctx, dev_name);
+ pr_warn("%px: Cannot find the net device: %s. Reset nexthop failed.\n", nss_ctx, cmd_buf);
return -ENODEV;
}
if_num = nss_cmn_get_interface_number_by_dev(dev);
if (if_num < 0) {
- pr_warn("%px: Invalid if_num for interface: %s. Reset nexthop failed.\n", nss_ctx, dev_name);
+ pr_warn("%px: Invalid if_num for interface: %s. Reset nexthop failed.\n", nss_ctx, cmd_buf);
dev_put(dev);
return -ENODEV;
}
@@ -529,7 +509,7 @@ static int nss_match_cmd_procfs_set_if_n
int table_id;
struct nss_ctx_instance *nss_ctx = nss_match_get_context();
struct nss_ctx_instance *wifili_nss_ctx = nss_wifili_get_context();
- char *dev_name, *nexthop_msg;
+ char *dev_name, *pos;
char *cmd_buf = NULL;
size_t count = *lenp;
nss_tx_status_t nss_tx_status;
@@ -544,31 +524,28 @@ static int nss_match_cmd_procfs_set_if_n
return -ENOMEM;
}
- cmd_buf = (char *)kzalloc(count + 1, GFP_KERNEL);
- nexthop_msg = cmd_buf;
- if (!cmd_buf) {
- pr_warn("%px: Cannot allocate buffer to read input", nss_ctx);
- return -ENOMEM;
+ if (count >= sizeof(cmd_buf)) {
+ nss_match_warn("%px: Input too large: %zu\n", ctl, count);
+ return -EINVAL;
}
- if (copy_from_user(cmd_buf, buffer, count)) {
- kfree(nexthop_msg);
- pr_warn("%px: Cannot copy user's entry to kernel memory\n", nss_ctx);
- return -EFAULT;
+ memcpy(cmd_buf, buffer, count);
+ cmd_buf[count] = '\0'; /* Ensure null termination */
+
+ if ((pos = strrchr(cmd_buf, '\n')) != NULL) {
+ *pos = '\0';
}
dev_name = strsep(&cmd_buf, " ");
dev = dev_get_by_name(&init_net, dev_name);
if (!dev) {
pr_warn("%px: Cannot find the net device\n", nss_ctx);
- kfree(nexthop_msg);
return -ENODEV;
}
if_num = nss_cmn_get_interface_number_by_dev(dev);
if (if_num < 0) {
pr_warn("%px: Invalid interface number:%d\n", nss_ctx, if_num);
- kfree(nexthop_msg);
dev_put(dev);
return -ENODEV;
}
@@ -576,20 +553,17 @@ static int nss_match_cmd_procfs_set_if_n
if (isdigit(cmd_buf[0])) {
if (!sscanf(cmd_buf, "%u", &nh_if_num)) {
pr_warn("%px, Failed to write the nexthop if_num token to integer\n", nss_ctx);
- kfree(nexthop_msg);
dev_put(dev);
return -EFAULT;
}
} else {
pr_warn("%px: Invalid nexthop interface number.\n", nss_ctx);
- kfree(nexthop_msg);
dev_put(dev);
return -ENODEV;
}
if (nh_if_num < 0) {
pr_warn("%px: Invalid nexthop interface number:%d\n", nss_ctx, if_num);
- kfree(nexthop_msg);
dev_put(dev);
return -ENODEV;
}
@@ -597,7 +571,6 @@ static int nss_match_cmd_procfs_set_if_n
table_id = nss_match_get_table_id_by_ifnum(nh_if_num);
if (table_id <= 0 || table_id > NSS_MATCH_INSTANCE_MAX) {
pr_warn("Invalid match interface. Failed to set %d as nexthop.\n", nh_if_num);
- kfree(nexthop_msg);
dev_put(dev);
return -EFAULT;
}
@@ -614,7 +587,6 @@ static int nss_match_cmd_procfs_set_if_n
nss_tx_status = nss_phys_if_set_nexthop(nss_ctx, if_num, nh_if_num);
} else {
pr_warn("Invalid interface to set nexthop. Failed to set nexthop on if_num %d.\n", if_num);
- kfree(nexthop_msg);
dev_put(dev);
return -EFAULT;
}
@@ -623,7 +595,6 @@ static int nss_match_cmd_procfs_set_if_n
pr_warn("%px: Sending message failed, cannot change nexthop\n", nss_ctx);
}
- kfree(nexthop_msg);
dev_put(dev);
return ret;
}