crypto: qat - use strscpy_pad to simplify buffer initialization
Subsystems (2)
PATCH 1/1 crypto: qat - use strscpy_pad to simplify buffer initialization
Use strscpy_pad() to copy the string and zero-pad the destination buffer in a single step instead of zero-initializing the buffer first and then immediately overwriting it using strscpy().
Replace the magic number 16 with sizeof(buf) and remove the redundant parentheses around kstrtoul() while we're at it.
--- drivers/crypto/intel/qat/qat_common/qat_uclo.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/crypto/intel/qat/qat_common/qat_uclo.c +4 -4
@@ -200,18 +200,18 @@ qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,static int qat_uclo_parse_num (char *str,unsigned int *num) { -char buf[16 ] = {0 }; +char buf[16 ] = {};unsigned long ae =0 ;int i; -strscpy (buf, str,sizeof (buf)); -for (i =0 ; i <16 ; i++) { +strscpy_pad (buf, str); +for (i =0 ; i <sizeof (buf); i++) {if (!isdigit (buf[i])) { buf[i] ='\0' ;break ; } } -if ((kstrtoul (buf,10 , &ae))) +if (kstrtoul (buf,10 , &ae))return -EFAULT ; *num = (unsigned int )ae;
Signature · 1 line
2.51.0
Quoted 6 lines · Thorsten Blum
Use
strscpy_pad()to copy the string and zero-pad the destination buffer in a single step instead of zero-initializing the buffer first and then immediately overwriting it usingstrscpy().Replace the magic number 16 with sizeof(buf) and remove the redundant parentheses around
kstrtoul()while we're at it.
I understand that you focused on strscpy*() conversions, but the below I think needs a bigger refactoring, see my remarks.
...
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 207
Quoted 8 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +2
-3-char buf[16 ] = {0 }; +char buf[16 ] = {};unsigned long ae =0 ;int i; -strscpy (buf, str,sizeof (buf)); -for (i =0 ; i <16 ; i++) { +strscpy_pad (buf, str);
First of all, why do we need a _pad() version here? Is the data somehow being used as a whole?
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 215
Quoted 9 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +2
-1+for (i =0 ; i <sizeof (buf); i++) {if (!isdigit (buf[i])) { buf[i] ='\0' ;break ; } } -if ((kstrtoul (buf,10 , &ae))) +if (kstrtoul (buf,10 , &ae))return -EFAULT ;
Looking at this, it tries to work around the kstrtoul() inability to perform partial parses. Instead, this should do something like
unsigned long long x; const char *end; simple_strtoull(...); if (x > UINT_MAX || end == buf) return $ERR; // wrong input / overflow
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 10 lines · Andy Shevchenko
Quoted 6 lines · Thorsten Blum
Use
strscpy_pad()to copy the string and zero-pad the destination buffer in a single step instead of zero-initializing the buffer first and then immediately overwriting it usingstrscpy().Replace the magic number 16 with sizeof(buf) and remove the redundant parentheses around
kstrtoul()while we're at it.I understand that you focused on strscpy*() conversions, but the below I think needs a bigger refactoring, see my remarks.
...
Quoted 12 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 207
Quoted 8 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +2
-3-char buf[16 ] = {0 }; +char buf[16 ] = {};unsigned long ae =0 ;int i; -strscpy (buf, str,sizeof (buf)); -for (i =0 ; i <16 ; i++) { +strscpy_pad (buf, str);First of all, why do we need a
_pad()version here? Is the data somehow being used as a whole?
Quoted 9 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 215
Quoted 9 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +2
-1+for (i =0 ; i <sizeof (buf); i++) {if (!isdigit (buf[i])) { buf[i] ='\0' ;break ; } } -if ((kstrtoul (buf,10 , &ae))) +if (kstrtoul (buf,10 , &ae))return -EFAULT ;
On top of that the function is called only from one place and returns different error code, instead it would have returned what kstrtoul() gives...
Quoted 9 lines
Looking at this, it tries to work around the
kstrtoul()inability to perform partial parses. Instead, this should do something likeunsigned long long x; const char *end; simple_strtoull(...); if (x > UINT_MAX || end == buf) return $ERR; // wrong input / overflow
Yeah, the overflow check here is not comprehensive, it won't catch the overflow (wrap around) of 64-bit value. But we can add a check for the end not to be farther than ~19 characters from the start, which would correspond the initial copy of 16 characters.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 8 lines · Andy Shevchenko
Quoted 6 lines · Thorsten Blum
Use
strscpy_pad()to copy the string and zero-pad the destination buffer in a single step instead of zero-initializing the buffer first and then immediately overwriting it usingstrscpy().Replace the magic number 16 with sizeof(buf) and remove the redundant parentheses around
kstrtoul()while we're at it.
Quoted 7 lines
I understand that you focused on strscpy*() conversions, but the below I think needs a bigger refactoring, see my remarks.
...
Review
Quoted 2 lines
(quoted diff) +1
-1- char buf[16] = {0}; + char buf[16] = {};
Sorry, this should have been just 'char buf[16];' since {} and {0} are equivalent and both zero-initialize the array.
Quoted 9 lines
Review
Quoted 6 lines
unsigned long ae = 0; int i;(quoted diff) +1
-2- strscpy(buf, str, sizeof(buf)); - for (i = 0; i < 16; i++) { + strscpy_pad(buf, str);First of all, why do we need a
_pad()version here? Is the data somehow being used as a whole?
I honestly didn't question this, but it looks like strscpy() would be sufficient (with this approach at least).
Quoted 13 lines
Quoted 9 lines
(quoted diff) +1
-0+ for (i = 0; i < sizeof(buf); i++) {if (!isdigit(buf[i])) { buf[i] = '\0'; break; } }(quoted diff) +1
-1- if ((kstrtoul(buf, 10, &ae))) + if (kstrtoul(buf, 10, &ae))return -EFAULT;Looking at this, it tries to work around the
kstrtoul()inability to perform partial parses. Instead, this should do something like
Quoted 6 lines
unsigned long long x; const char *end; simple_strtoull(...); if (x > UINT_MAX || end == buf) return $ERR; // wrong input / overflow
How about this?
drivers/crypto/intel/qat/qat_common/qat_uclo.c +5 -13
@@ -200,20 +200,12 @@ qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,static int qat_uclo_parse_num (char *str,unsigned int *num) { -char buf[16 ] = {0 }; -unsigned long ae =0 ; -int i; - -strscpy (buf, str,sizeof (buf)); -for (i =0 ; i <16 ; i++) { -if (!isdigit (buf[i])) { - buf[i] ='\0' ; -break ; - } - } -if ((kstrtoul (buf,10 , &ae))) -return -EFAULT ; +unsigned long long ae; +char *end; + ae =simple_strtoull (str, &end,10 ); +if (ae >UINT_MAX || str == end || (end - str) >20 ) +return -EINVAL ; *num = (unsigned int )ae;return 0 ; }
Quoted 2 lines · Thorsten Blum
Quoted 1 line · Andy Shevchenko
On Wed, Oct 22, 2025 at 02:36:19PM +0200, Thorsten Blum wrote:
...
Quoted 1 line
How about this?
LGTM, and that's what I had in mind, but please double check the behaviour of kstrtox() on an empty strings.
Quoted 16 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +0
-8@@ -200,20 +200,12 @@ qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,static int qat_uclo_parse_num (char *str,unsigned int *num) { -char buf[16 ] = {0 }; -unsigned long ae =0 ; -int i; - -strscpy (buf, str,sizeof (buf)); -for (i =0 ; i <16 ; i++) { -if (!isdigit (buf[i])) { - buf[i] ='\0' ;
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 207
Quoted 10 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +4
-5-break ; - } - } -if ((kstrtoul (buf,10 , &ae))) -return -EFAULT ; +unsigned long long ae; +char *end; + ae =simple_strtoull (str, &end,10 ); +if (ae >UINT_MAX || str == end || (end - str) >20 )
I would go with >= 20, the 64-bit value is approx. 1 * 10^19.
Quoted 4 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +1
-0+return -EINVAL ; *num = (unsigned int )ae;return 0 ; }
Signature · 2 lines
With Best Regards, Andy Shevchenko
Giovanni Cabiddu
maintainerQuoted 10 lines · Andy Shevchenko
Quoted 2 lines · Thorsten Blum
Quoted 1 line · Andy Shevchenko
On Wed, Oct 22, 2025 at 02:36:19PM +0200, Thorsten Blum wrote:
...
Quoted 1 line
How about this?
LGTM, and that's what I had in mind, but please double check the behaviour of
kstrtox()on an empty strings.
LGTM as well.
I checked the behaviour of kstrtoul() when given an empty string. It returns -EINVAL (-22). The result variable (the third parameter) is only modified if the conversion is succesful.
Anyway, the caller will not provide a NULL string to this function [1].
Quoted 24 lines
Quoted 24 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +2
-13@@ -200,20 +200,12 @@ qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle,static int qat_uclo_parse_num (char *str,unsigned int *num) { -char buf[16 ] = {0 }; -unsigned long ae =0 ; -int i; - -strscpy (buf, str,sizeof (buf)); -for (i =0 ; i <16 ; i++) { -if (!isdigit (buf[i])) { - buf[i] ='\0' ; -break ; - } - } -if ((kstrtoul (buf,10 , &ae))) -return -EFAULT ; +unsigned long long ae; +char *end;
Quoted 4 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 207
Quoted 2 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +2
-0+ ae =simple_strtoull (str, &end,10 ); +if (ae >UINT_MAX || str == end || (end - str) >20 )I would go with >= 20, the 64-bit value is approx. 1 * 10^19.
Just an insight into the type of strings being parsed here. If they are well-formed, the format looks like:
<AE_NUMBER>!<...>
Example:
11!l0000!lm_thread_ctrl_struct_base
This function just extract the first number. Currently, that is 2 digits [2], and I believe it is unlikely to exceed 3 in future gens.
[1] https://elixir.bootlin.com/linux/v6.17.4/source/drivers/crypto/intel/qat/qat_common/qat_uclo.c#L237
[2] https://elixir.bootlin.com/linux/v6.17.4/source/drivers/crypto/intel/qat/qat_common/icp_qat_uclo.h#L11
Regards,
Signature · 1 line
Giovanni
Quoted 4 lines · Giovanni Cabiddu
Quoted 3 lines · Andy Shevchenko
Quoted 2 lines · Thorsten Blum
Quoted 1 line · Andy Shevchenko
On Wed, Oct 22, 2025 at 02:36:19PM +0200, Thorsten Blum wrote:
...
Quoted 10 lines
Quoted 4 lines
Quoted 1 line
How about this?
LGTM, and that's what I had in mind, but please double check the behaviour of
kstrtox()on an empty strings.LGTM as well.
I checked the behaviour of
kstrtoul()when given an empty string. It returns-EINVAL(-22). The result variable (the third parameter) is only modified if the conversion is succesful.
Thanks for confirming!
Quoted 13 lines
Anyway, the caller will not provide a NULL string to this function [1].
Quoted 7 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c qat_uclo_cleanup_batch_init_list(struct icp_qat_fw_loader_handle *handle, · line 207
Quoted 5 lines
drivers/crypto/intel/qat/qat_common/qat_uclo.c +4
-0+unsigned long long ae; +char *end; + ae =simple_strtoull (str, &end,10 ); +if (ae >UINT_MAX || str == end || (end - str) >20 )I would go with >= 20, the 64-bit value is approx. 1 * 10^19.
Just an insight into the type of strings being parsed here. If they are well-formed, the format looks like:
Quoted 8 lines
<AE_NUMBER>!<...>Example:
11!l0000!lm_thread_ctrl_struct_baseThis function just extract the first number. Currently, that is 2 digits [2], and I believe it is unlikely to exceed 3 in future gens.
Yep, but it is better to make code more robust (and esp. in case somebody copies'n'pastes to somewhere else).
Quoted 2 lines
[1] https://elixir.bootlin.com/linux/v6.17.4/source/drivers/crypto/intel/qat/qat_common/qat_uclo.c#L237
[2] https://elixir.bootlin.com/linux/v6.17.4/source/drivers/crypto/intel/qat/qat_common/icp_qat_uclo.h#L11
Signature · 2 lines
With Best Regards, Andy Shevchenko
Hi Andy,
Quoted 9 lines · Andy Shevchenko
Quoted 2 lines · Thorsten Blum
Quoted 1 line · Andy Shevchenko
On Wed, Oct 22, 2025 at 02:36:19PM +0200, Thorsten Blum wrote:
...
Quoted 1 line
How about this?
LGTM, and that's what I had in mind, ...
I was about to submit v2, but checkpatch warns me about simple_strtoull:
WARNING: simple_strtoull is obsolete, use kstrtoull instead
Any recommendations?
Thanks,
Thorsten
Quoted 4 lines · Thorsten Blum
Quoted 3 lines · Andy Shevchenko
Quoted 2 lines · Thorsten Blum
Quoted 1 line · Andy Shevchenko
On Wed, Oct 22, 2025 at 02:36:19PM +0200, Thorsten Blum wrote:
...
Quoted 9 lines
Quoted 3 lines
Quoted 1 line
How about this?
LGTM, and that's what I had in mind, ...
I was about to submit v2, but checkpatch warns me about
simple_strtoull:WARNING:
simple_strtoullis obsolete, use kstrtoull insteadAny recommendations?
Yes, fix checkpatch as per commit 885e68e8b7b1 ("kernel.h: update comment about simple_strto<foo>() functions") or ignore this false positive.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Quoted 6 lines · Andy Shevchenko
Quoted 2 lines · Thorsten Blum
[...]
Any recommendations?Yes, fix checkpatch as per commit
885e68e8b7b1("kernel.h: update comment about simple_strto<foo>() functions") or ignore this false positive.
Thanks for the commit hash. I ignored it and submitted v2: