[v2] net/cpfl: fix cpfl parser issue

Message ID 20240731072303.1119177-1-praveen.shetty@intel.com (mailing list archive)
State Changes Requested
Delegated to: Bruce Richardson
Headers
Series [v2] net/cpfl: fix cpfl parser issue |

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/loongarch-compilation success Compilation OK
ci/loongarch-unit-testing success Unit Testing PASS
ci/Intel-compilation success Compilation OK
ci/intel-Testing success Testing PASS
ci/github-robot: build success github build: passed
ci/intel-Functional success Functional PASS
ci/iol-mellanox-Performance success Performance Testing PASS
ci/iol-intel-Performance success Performance Testing PASS
ci/iol-marvell-Functional success Functional Testing PASS
ci/iol-abi-testing success Testing PASS
ci/iol-broadcom-Performance success Performance Testing PASS
ci/iol-intel-Functional success Functional Testing PASS
ci/iol-broadcom-Functional success Functional Testing PASS
ci/iol-unit-arm64-testing success Testing PASS
ci/iol-unit-amd64-testing success Testing PASS
ci/iol-compile-amd64-testing success Testing PASS
ci/iol-compile-arm64-testing success Testing PASS
ci/iol-sample-apps-testing success Testing PASS

Commit Message

Praveen Shetty July 31, 2024, 7:23 a.m. UTC
CPFL parser was incorrectly parsing the mask value of the
next_proto_id field from recipe.json file as a string
instead of unsigned integer.

Fixes: 41f20298ee8c ("net/cpfl: parse flow offloading hint from JSON")
Cc: stable@dpdk.org

Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>

---
v2:
* Fixed CI issues.
---
 drivers/net/cpfl/cpfl_flow_parser.c | 34 +++++++++++++++++++----------
 1 file changed, 22 insertions(+), 12 deletions(-)
  

Comments

Bruce Richardson Aug. 22, 2024, 4:50 p.m. UTC | #1
On Wed, Jul 31, 2024 at 07:23:03AM +0000, Praveen Shetty wrote:
> CPFL parser was incorrectly parsing the mask value of the
> next_proto_id field from recipe.json file as a string
> instead of unsigned integer.
> 
> Fixes: 41f20298ee8c ("net/cpfl: parse flow offloading hint from JSON")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> 
> ---
> v2:
> * Fixed CI issues.
> ---
>  drivers/net/cpfl/cpfl_flow_parser.c | 34 +++++++++++++++++++----------
>  1 file changed, 22 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c
> index 40569ddc6f..7800ad97ea 100644
> --- a/drivers/net/cpfl/cpfl_flow_parser.c
> +++ b/drivers/net/cpfl/cpfl_flow_parser.c
> @@ -198,6 +198,8 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
>  	for (i = 0; i < len; i++) {
>  		json_t *object;
>  		const char *name, *mask;
> +		uint32_t mask_32b = 0;
> +		int ret;
>  
>  		object = json_array_get(ob_fields, i);
>  		name = cpfl_json_t_to_string(object, "name");
> @@ -213,20 +215,28 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
>  
>  		if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
>  		    js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
> -			mask = cpfl_json_t_to_string(object, "mask");
> -			if (!mask) {
> -				PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> -				goto err;
> -			}
> -			if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> -				PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> -				goto err;
> +			/* Added a check for parsing mask value of the next_proto_id field. */
> +			if (strcmp(name, "next_proto_id") == 0) {
> +				ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
> +				if (ret < 0) {
> +					PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
> +					goto err;
> +				}
> +				js_field->fields[i].mask_32b = mask_32b;
> +			} else {
> +				mask = cpfl_json_t_to_string(object, "mask");
> +				if (!mask) {
> +					PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> +					goto err;
> +				}
> +				if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> +					PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> +					goto err;
> +				}
> +				rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 1);

+1 for replacing strncpy with something safer, since original code is wrong
and can leave a non-null-terminated string, but unfortunately the copy here
isn't quite right. For strlcpy and rte_strscpy, you specify the exact
buffer size, not the size-1.

Also, you don't need to check the length and then do the copy, you might as
well just do the copy using strscpy or strlcpy and check the return value
from it. Saves iterating the string twice (once for length, second time for
copy). For example:

  if (rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE) < 0) {
  	PMD_DRV_LOG(ERR, "The 'mask' is too long.");
  	goto err;
  }

Regards,
/Bruce
  
Praveen Shetty Aug. 23, 2024, 7:28 a.m. UTC | #2
> CPFL parser was incorrectly parsing the mask value of the 
> next_proto_id field from recipe.json file as a string instead of 
> unsigned integer.
> 
> Fixes: 41f20298ee8c ("net/cpfl: parse flow offloading hint from JSON")
> Cc: stable@dpdk.org
> 
> Signed-off-by: Praveen Shetty <praveen.shetty@intel.com>
> 
> ---
> v2:
> * Fixed CI issues.
> ---
>  drivers/net/cpfl/cpfl_flow_parser.c | 34 
> +++++++++++++++++++----------
>  1 file changed, 22 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/net/cpfl/cpfl_flow_parser.c 
> b/drivers/net/cpfl/cpfl_flow_parser.c
> index 40569ddc6f..7800ad97ea 100644
> --- a/drivers/net/cpfl/cpfl_flow_parser.c
> +++ b/drivers/net/cpfl/cpfl_flow_parser.c
> @@ -198,6 +198,8 @@ cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
>  	for (i = 0; i < len; i++) {
>  		json_t *object;
>  		const char *name, *mask;
> +		uint32_t mask_32b = 0;
> +		int ret;
>  
>  		object = json_array_get(ob_fields, i);
>  		name = cpfl_json_t_to_string(object, "name"); @@ -213,20 +215,28 @@ 
> cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
>  
>  		if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
>  		    js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
> -			mask = cpfl_json_t_to_string(object, "mask");
> -			if (!mask) {
> -				PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> -				goto err;
> -			}
> -			if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> -				PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> -				goto err;
> +			/* Added a check for parsing mask value of the next_proto_id field. */
> +			if (strcmp(name, "next_proto_id") == 0) {
> +				ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
> +				if (ret < 0) {
> +					PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
> +					goto err;
> +				}
> +				js_field->fields[i].mask_32b = mask_32b;
> +			} else {
> +				mask = cpfl_json_t_to_string(object, "mask");
> +				if (!mask) {
> +					PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
> +					goto err;
> +				}
> +				if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
> +					PMD_DRV_LOG(ERR, "The 'mask' is too long.");
> +					goto err;
> +				}
> +				rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 
> +1);

+1 for replacing strncpy with something safer, since original code is 
+wrong
and can leave a non-null-terminated string, but unfortunately the copy here isn't quite right. For strlcpy and rte_strscpy, you specify the exact buffer size, not the size-1.

Also, you don't need to check the length and then do the copy, you might as well just do the copy using strscpy or strlcpy and check the return value from it. Saves iterating the string twice (once for length, second time for copy). For example:

  if (rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE) < 0) {
  	PMD_DRV_LOG(ERR, "The 'mask' is too long.");
  	goto err;
  }

Thanks, will fix this in v3.

Regards,
/Bruce
  

Patch

diff --git a/drivers/net/cpfl/cpfl_flow_parser.c b/drivers/net/cpfl/cpfl_flow_parser.c
index 40569ddc6f..7800ad97ea 100644
--- a/drivers/net/cpfl/cpfl_flow_parser.c
+++ b/drivers/net/cpfl/cpfl_flow_parser.c
@@ -198,6 +198,8 @@  cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
 	for (i = 0; i < len; i++) {
 		json_t *object;
 		const char *name, *mask;
+		uint32_t mask_32b = 0;
+		int ret;
 
 		object = json_array_get(ob_fields, i);
 		name = cpfl_json_t_to_string(object, "name");
@@ -213,20 +215,28 @@  cpfl_flow_js_pattern_key_proto_field(json_t *ob_fields,
 
 		if (js_field->type == RTE_FLOW_ITEM_TYPE_ETH ||
 		    js_field->type == RTE_FLOW_ITEM_TYPE_IPV4) {
-			mask = cpfl_json_t_to_string(object, "mask");
-			if (!mask) {
-				PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
-				goto err;
-			}
-			if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
-				PMD_DRV_LOG(ERR, "The 'mask' is too long.");
-				goto err;
+			/* Added a check for parsing mask value of the next_proto_id field. */
+			if (strcmp(name, "next_proto_id") == 0) {
+				ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
+				if (ret < 0) {
+					PMD_DRV_LOG(ERR, "Cannot parse uint32 'mask'.");
+					goto err;
+				}
+				js_field->fields[i].mask_32b = mask_32b;
+			} else {
+				mask = cpfl_json_t_to_string(object, "mask");
+				if (!mask) {
+					PMD_DRV_LOG(ERR, "Can not parse string 'mask'.");
+					goto err;
+				}
+				if (strlen(mask) > CPFL_JS_STR_SIZE - 1) {
+					PMD_DRV_LOG(ERR, "The 'mask' is too long.");
+					goto err;
+				}
+				rte_strscpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 1);
 			}
-			strncpy(js_field->fields[i].mask, mask, CPFL_JS_STR_SIZE - 1);
-		} else {
-			uint32_t mask_32b;
-			int ret;
 
+		} else {
 			ret = cpfl_json_t_to_uint32(object, "mask", &mask_32b);
 			if (ret < 0) {
 				PMD_DRV_LOG(ERR, "Can not parse uint32 'mask'.");