From 387698c63bc81761256040c2e1b0d57c056e618e Mon Sep 17 00:00:00 2001 From: Sean Khan Date: Thu, 17 Apr 2025 01:05:36 -0400 Subject: [PATCH] nss-drv: nss_rps/dscp fix read/write procfs files Another fix for reading procfs files. This fixes a long time bug where reading/writing to ipv4_dscp_map, ipv6_dscp_map, pri_map would result in a 'Bad Memory' error Should now look like this when reading the following: ``` dev.nss.ipv4cfg.ipv4_dscp_map = priority: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 dev.nss.ipv4cfg.ipv4_dscp_map = action: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 dev.nss.ipv6cfg.ipv6_dscp_map = priority: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 dev.nss.ipv6cfg.ipv6_dscp_map = action: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 dev.nss.rps.pri_map = Cores: -1 -1 -1 -1 ``` Signed-off-by: Sean Khan --- .../0025-nss_rps-fix-procfs-read-write.patch | 195 ++++++++++++++++++ .../0025-nss_rps-fix-procfs-read-write.patch | 195 ++++++++++++++++++ 2 files changed, 390 insertions(+) create mode 100644 qca-nss-drv/patches-11.4/0025-nss_rps-fix-procfs-read-write.patch create mode 100644 qca-nss-drv/patches/0025-nss_rps-fix-procfs-read-write.patch diff --git a/qca-nss-drv/patches-11.4/0025-nss_rps-fix-procfs-read-write.patch b/qca-nss-drv/patches-11.4/0025-nss_rps-fix-procfs-read-write.patch new file mode 100644 index 0000000..8a315b2 --- /dev/null +++ b/qca-nss-drv/patches-11.4/0025-nss_rps-fix-procfs-read-write.patch @@ -0,0 +1,195 @@ +--- a/nss_rps.c ++++ b/nss_rps.c +@@ -67,7 +67,7 @@ static inline void nss_rps_pri_map_usage + * nss_rps_pri_map_print() + * Sysctl handler for printing rps/pri mapping. + */ +-static int nss_rps_pri_map_print(struct ctl_table *ctl, void __user *buffer, ++static int nss_rps_pri_map_print(void *buffer, + size_t *lenp, loff_t *ppos, int *pri_map) + { + char *r_buf; +@@ -106,7 +106,7 @@ static int nss_rps_pri_map_print(struct + len = scnprintf(r_buf + cp_bytes, 4, "\n"); + cp_bytes += len; + +- cp_bytes = simple_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); ++ cp_bytes = memory_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); + *lenp = cp_bytes; + kfree(r_buf); + return 0; +@@ -116,13 +116,10 @@ static int nss_rps_pri_map_print(struct + * nss_rps_pri_map_parse() + * Sysctl handler for rps/pri mappings. + */ +-static int nss_rps_pri_map_parse(struct ctl_table *ctl, void __user *buffer, +- size_t *lenp, loff_t *ppos, struct nss_rps_pri_map_parse_data *out) ++static int nss_rps_pri_map_parse(void *buffer, ++ size_t *lenp, struct nss_rps_pri_map_parse_data *out) + { +- size_t cp_bytes = 0; + char w_buf[5]; +- loff_t w_offset = 0; +- char *str; + unsigned int pri; + int core, res; + +@@ -137,14 +134,15 @@ static int nss_rps_pri_map_parse(struct + /* + * It's a write operation + */ +- cp_bytes = simple_write_to_buffer(w_buf, *lenp, &w_offset, buffer, 5); +- if (cp_bytes != *lenp) { +- nss_warning("failed to write to buffer\n"); +- return -EFAULT; ++ if (*lenp >= sizeof(w_buf)) { ++ nss_warning("Input too large: %zu\n", *lenp); ++ return -EINVAL; + } + +- str = w_buf; +- res = sscanf(str, "%u %d", &pri, &core); ++ memcpy(w_buf, buffer, *lenp); ++ w_buf[*lenp] = '\0'; /* Ensure null termination */ ++ ++ res = sscanf(w_buf, "%u %d", &pri, &core); + if (res != NSS_RPS_PRI_MAP_PARAM_FIELD_COUNT) { + nss_warning("failed to read the buffer\n"); + return -EFAULT; +@@ -404,7 +402,7 @@ static nss_tx_status_t nss_rps_pri_map_c + * Enable NSS RPS. + */ + static int nss_rps_cfg_handler(struct ctl_table *ctl, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) ++ void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx; +@@ -455,7 +453,7 @@ static int nss_rps_cfg_handler(struct ct + * Configure NSS rps_hash_bitmap + */ + static int nss_rps_hash_bitmap_cfg_handler(struct ctl_table *ctl, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) ++ void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx __attribute__((unused)) = &nss_top->nss[0]; +@@ -518,7 +516,7 @@ static int nss_rps_hash_bitmap_cfg_handl + * Configure NSS rps_pri_map + */ + static int nss_rps_pri_map_cfg_handler(struct ctl_table *ctl, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) ++ void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +@@ -526,10 +524,10 @@ static int nss_rps_pri_map_cfg_handler(s + int ret, ret_pri_map; + struct nss_rps_pri_map_parse_data out, current_state; + if (!write) { +- return nss_rps_pri_map_print(ctl, buffer, lenp, ppos, nss_rps_pri_map); ++ return nss_rps_pri_map_print(buffer, lenp, ppos, nss_rps_pri_map); + } + +- ret = nss_rps_pri_map_parse(ctl, buffer, lenp, ppos, &out); ++ ret = nss_rps_pri_map_parse(buffer, lenp, &out); + + if (ret != NSS_SUCCESS) { + nss_rps_pri_map_usage(); +--- a/nss_ipv6.c ++++ b/nss_ipv6.c +@@ -595,7 +595,7 @@ void nss_ipv6_free_conn_tables(void) + * nss_ipv6_accel_mode_cfg_handler() + * Configure acceleration mode for IPv6 + */ +-static int nss_ipv6_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv6_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +@@ -639,7 +639,7 @@ static int nss_ipv6_accel_mode_cfg_handl + * nss_ipv6_dscp_map_cfg_handler() + * Sysctl handler for dscp/pri mappings. + */ +-static int nss_ipv6_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv6_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +--- a/nss_ipv4.c ++++ b/nss_ipv4.c +@@ -599,7 +599,7 @@ void nss_ipv4_free_conn_tables(void) + * nss_ipv4_accel_mode_cfg_handler() + * Configure acceleration mode for IPv4 + */ +-static int nss_ipv4_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv4_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +@@ -643,7 +643,7 @@ static int nss_ipv4_accel_mode_cfg_handl + * nss_ipv4_dscp_map_cfg_handler() + * Sysctl handler for dscp/pri mappings. + */ +-static int nss_ipv4_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv4_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +--- a/nss_dscp_map.h ++++ b/nss_dscp_map.h +@@ -46,7 +46,7 @@ struct nss_dscp_map_parse { + * nss_dscp_map_print() + * Sysctl handler for printing dscp/pri mapping. + */ +-static int nss_dscp_map_print(struct ctl_table *ctl, void __user *buffer, size_t *lenp, ++static int nss_dscp_map_print(struct ctl_table *ctl, void *buffer, size_t *lenp, + loff_t *ppos, struct nss_dscp_map_entry *mapping) + { + char *r_buf; +@@ -105,7 +105,7 @@ static int nss_dscp_map_print(struct ctl + len = scnprintf(r_buf + cp_bytes, 4, "\n"); + cp_bytes += len; + +- cp_bytes = simple_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); ++ cp_bytes = memory_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); + *lenp = cp_bytes; + kfree(r_buf); + return 0; +@@ -115,13 +115,11 @@ static int nss_dscp_map_print(struct ctl + * nss_dscp_map_parse() + * Sysctl handler for dscp/pri mappings. + */ +-static int nss_dscp_map_parse(struct ctl_table *ctl, void __user *buffer, size_t *lenp, ++static int nss_dscp_map_parse(struct ctl_table *ctl, void *buffer, size_t *lenp, + loff_t *ppos, struct nss_dscp_map_parse *out) + { + int count; +- size_t cp_bytes = 0; + char w_buf[7]; +- loff_t w_offset = 0; + char *str; + char *tokens[NSS_DSCP_MAP_PARAM_FIELD_COUNT]; + unsigned int dscp, priority, action; +@@ -135,15 +133,14 @@ static int nss_dscp_map_parse(struct ctl + return -EINVAL; + } + +- /* +- * It's a write operation +- */ +- cp_bytes = simple_write_to_buffer(w_buf, *lenp, &w_offset, buffer, 7); +- if (cp_bytes != *lenp) { +- nss_warning("failed to write to buffer\n"); +- return -EFAULT; ++ if (*lenp >= sizeof(w_buf)) { ++ nss_warning("Input too large: %zu\n", *lenp); ++ return -EINVAL; + } + ++ memcpy(w_buf, buffer, *lenp); ++ w_buf[*lenp] = '\0'; /* Ensure null termination */ ++ + count = 0; + str = w_buf; + tokens[count] = strsep(&str, " "); diff --git a/qca-nss-drv/patches/0025-nss_rps-fix-procfs-read-write.patch b/qca-nss-drv/patches/0025-nss_rps-fix-procfs-read-write.patch new file mode 100644 index 0000000..cfdcdcd --- /dev/null +++ b/qca-nss-drv/patches/0025-nss_rps-fix-procfs-read-write.patch @@ -0,0 +1,195 @@ +--- a/nss_rps.c ++++ b/nss_rps.c +@@ -70,7 +70,7 @@ static inline void nss_rps_pri_map_usage + * nss_rps_pri_map_print() + * Sysctl handler for printing rps/pri mapping. + */ +-static int nss_rps_pri_map_print(struct ctl_table *ctl, void __user *buffer, ++static int nss_rps_pri_map_print(void *buffer, + size_t *lenp, loff_t *ppos, int *pri_map) + { + char *r_buf; +@@ -109,7 +109,7 @@ static int nss_rps_pri_map_print(struct + len = scnprintf(r_buf + cp_bytes, 4, "\n"); + cp_bytes += len; + +- cp_bytes = simple_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); ++ cp_bytes = memory_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); + *lenp = cp_bytes; + kfree(r_buf); + return 0; +@@ -119,13 +119,10 @@ static int nss_rps_pri_map_print(struct + * nss_rps_pri_map_parse() + * Sysctl handler for rps/pri mappings. + */ +-static int nss_rps_pri_map_parse(struct ctl_table *ctl, void __user *buffer, +- size_t *lenp, loff_t *ppos, struct nss_rps_pri_map_parse_data *out) ++static int nss_rps_pri_map_parse(void *buffer, ++ size_t *lenp, struct nss_rps_pri_map_parse_data *out) + { +- size_t cp_bytes = 0; + char w_buf[5]; +- loff_t w_offset = 0; +- char *str; + unsigned int pri; + int core, res; + +@@ -140,14 +137,15 @@ static int nss_rps_pri_map_parse(struct + /* + * It's a write operation + */ +- cp_bytes = simple_write_to_buffer(w_buf, *lenp, &w_offset, buffer, 5); +- if (cp_bytes != *lenp) { +- nss_warning("failed to write to buffer\n"); +- return -EFAULT; ++ if (*lenp >= sizeof(w_buf)) { ++ nss_warning("Input too large: %zu\n", *lenp); ++ return -EINVAL; + } + +- str = w_buf; +- res = sscanf(str, "%u %d", &pri, &core); ++ memcpy(w_buf, buffer, *lenp); ++ w_buf[*lenp] = '\0'; /* Ensure null termination */ ++ ++ res = sscanf(w_buf, "%u %d", &pri, &core); + if (res != NSS_RPS_PRI_MAP_PARAM_FIELD_COUNT) { + nss_warning("failed to read the buffer\n"); + return -EFAULT; +@@ -407,7 +405,7 @@ static nss_tx_status_t nss_rps_pri_map_c + * Enable NSS RPS. + */ + static int nss_rps_cfg_handler(struct ctl_table *ctl, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) ++ void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx; +@@ -458,7 +456,7 @@ static int nss_rps_cfg_handler(struct ct + * Configure NSS rps_hash_bitmap + */ + static int nss_rps_hash_bitmap_cfg_handler(struct ctl_table *ctl, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) ++ void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx __attribute__((unused)) = &nss_top->nss[0]; +@@ -521,7 +519,7 @@ static int nss_rps_hash_bitmap_cfg_handl + * Configure NSS rps_pri_map + */ + static int nss_rps_pri_map_cfg_handler(struct ctl_table *ctl, int write, +- void __user *buffer, size_t *lenp, loff_t *ppos) ++ void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +@@ -529,10 +527,10 @@ static int nss_rps_pri_map_cfg_handler(s + int ret, ret_pri_map; + struct nss_rps_pri_map_parse_data out, current_state; + if (!write) { +- return nss_rps_pri_map_print(ctl, buffer, lenp, ppos, nss_rps_pri_map); ++ return nss_rps_pri_map_print(buffer, lenp, ppos, nss_rps_pri_map); + } + +- ret = nss_rps_pri_map_parse(ctl, buffer, lenp, ppos, &out); ++ ret = nss_rps_pri_map_parse(buffer, lenp, &out); + + if (ret != NSS_SUCCESS) { + nss_rps_pri_map_usage(); +--- a/nss_ipv6.c ++++ b/nss_ipv6.c +@@ -595,7 +595,7 @@ void nss_ipv6_free_conn_tables(void) + * nss_ipv6_accel_mode_cfg_handler() + * Configure acceleration mode for IPv6 + */ +-static int nss_ipv6_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv6_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +@@ -639,7 +639,7 @@ static int nss_ipv6_accel_mode_cfg_handl + * nss_ipv6_dscp_map_cfg_handler() + * Sysctl handler for dscp/pri mappings. + */ +-static int nss_ipv6_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv6_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +--- a/nss_ipv4.c ++++ b/nss_ipv4.c +@@ -599,7 +599,7 @@ void nss_ipv4_free_conn_tables(void) + * nss_ipv4_accel_mode_cfg_handler() + * Configure acceleration mode for IPv4 + */ +-static int nss_ipv4_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv4_accel_mode_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +@@ -643,7 +643,7 @@ static int nss_ipv4_accel_mode_cfg_handl + * nss_ipv4_dscp_map_cfg_handler() + * Sysctl handler for dscp/pri mappings. + */ +-static int nss_ipv4_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void __user *buffer, size_t *lenp, loff_t *ppos) ++static int nss_ipv4_dscp_map_cfg_handler(struct ctl_table *ctl, int write, void *buffer, size_t *lenp, loff_t *ppos) + { + struct nss_top_instance *nss_top = &nss_top_main; + struct nss_ctx_instance *nss_ctx = &nss_top->nss[0]; +--- a/nss_dscp_map.h ++++ b/nss_dscp_map.h +@@ -46,7 +46,7 @@ struct nss_dscp_map_parse { + * nss_dscp_map_print() + * Sysctl handler for printing dscp/pri mapping. + */ +-static int nss_dscp_map_print(struct ctl_table *ctl, void __user *buffer, size_t *lenp, ++static int nss_dscp_map_print(struct ctl_table *ctl, void *buffer, size_t *lenp, + loff_t *ppos, struct nss_dscp_map_entry *mapping) + { + char *r_buf; +@@ -105,7 +105,7 @@ static int nss_dscp_map_print(struct ctl + len = scnprintf(r_buf + cp_bytes, 4, "\n"); + cp_bytes += len; + +- cp_bytes = simple_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); ++ cp_bytes = memory_read_from_buffer(buffer, *lenp, ppos, r_buf, cp_bytes); + *lenp = cp_bytes; + kfree(r_buf); + return 0; +@@ -115,13 +115,11 @@ static int nss_dscp_map_print(struct ctl + * nss_dscp_map_parse() + * Sysctl handler for dscp/pri mappings. + */ +-static int nss_dscp_map_parse(struct ctl_table *ctl, void __user *buffer, size_t *lenp, ++static int nss_dscp_map_parse(struct ctl_table *ctl, void *buffer, size_t *lenp, + loff_t *ppos, struct nss_dscp_map_parse *out) + { + int count; +- size_t cp_bytes = 0; + char w_buf[7]; +- loff_t w_offset = 0; + char *str; + char *tokens[NSS_DSCP_MAP_PARAM_FIELD_COUNT]; + unsigned int dscp, priority, action; +@@ -135,15 +133,14 @@ static int nss_dscp_map_parse(struct ctl + return -EINVAL; + } + +- /* +- * It's a write operation +- */ +- cp_bytes = simple_write_to_buffer(w_buf, *lenp, &w_offset, buffer, 7); +- if (cp_bytes != *lenp) { +- nss_warning("failed to write to buffer\n"); +- return -EFAULT; ++ if (*lenp >= sizeof(w_buf)) { ++ nss_warning("Input too large: %zu\n", *lenp); ++ return -EINVAL; + } + ++ memcpy(w_buf, buffer, *lenp); ++ w_buf[*lenp] = '\0'; /* Ensure null termination */ ++ + count = 0; + str = w_buf; + tokens[count] = strsep(&str, " ");