Re: [PATCH v2] lib/cmdline: prevent unintented access to address

2020-12-09 Thread Andy Shevchenko
On Thu, Aug 13, 2020 at 05:00:09PM +0300, Andy Shevchenko wrote:
> On Thu, Aug 13, 2020 at 12:07:41PM +0900, Seungil Kang wrote:

> And your test case / module would help a lot, if present.

Just a heads up: I have created a cmdline_kunit.c to test functions
in the module (currently only get_option() test cases are there).
It's in Andrew's quilt, pending for v5.11-rc1.
Feel free to extend it along with amended fix (as per my comments).

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH v2] lib/cmdline: prevent unintented access to address

2020-08-13 Thread Andy Shevchenko
On Thu, Aug 13, 2020 at 12:07:41PM +0900, Seungil Kang wrote:
> When args = "\"\0", "i" will be 0 and args[i-1] is used. (*lib/cmdline.c +238)

What I meant is to put hex dump of the args here in the parentheses, something 
like

"When args = "... \"\0" (... 0x22 0x00), 'i' will be..."

> Because of "i" is an unsigned int type, the function will access at 
> args[0x].
> It can make a crash.

...

> > Can you point out to the code that calls this and leads to a crash?
> 
>  *lib/cmdlinc + 201 ~, next_arg function with args = "\"\0"

Not the next_arg() code :-) The code which calls here...

...

> > Can you provide a KUnit test module which can check the case?
> 
>  If necessary, I will make it and share it.

Please, do as a separate patch in the series.

...

> --- a/lib/cmdline.c
> +++ b/lib/cmdline.c
> @@ -200,7 +200,7 @@ bool parse_option_str(const char *str, const char *option)
>   */
>  char *next_arg(char *args, char **param, char **val)
>  {
> - unsigned int i, equals = 0;
> + int i, equals = 0;
>   int in_quote = 0, quoted = 0;
>   char *next;

At the first glance this is not correct fix for it: 0 - 1 is always 'all 1:s'
independently on signedness, but I need to think about.

And your test case / module would help a lot, if present.

-- 
With Best Regards,
Andy Shevchenko




Re: [PATCH v2] lib/cmdline: prevent unintented access to address

2020-08-12 Thread Randy Dunlap
On 8/12/20 8:07 PM, Seungil Kang wrote:
> When args = "\"\0", "i" will be 0 and args[i-1] is used. (*lib/cmdline.c +238)
> Because of "i" is an unsigned int type, the function will access at 
> args[0x].
> It can make a crash.
> 
> Signed-off-by: Seungil Kang 
> ---
> 
> Thanks for your review, my comments below
> 
>> Can you be less ambiguous with the args value? (Perhaps provide a hexdump of 
>> it
> for better understanding)
> 
>  This kind of args as hexdump below can cause crash.
>  
>  : 736f 6d65 7468 696e 6731 3d73 6f6d 655f  something1=some_
>  0010: 7661 6c75 6573 2022      values "
>  
>  The args end with "\"\0".
> 
>> Please, use proper punctuation, I'm lost where is the sentence and what are 
>> the
> logical parts of them.
> 
>  I'm sorry to confuse you. I fix the commit msg
> 
>> Can you point out to the code that calls this and leads to a crash?
> 
>  *lib/cmdlinc + 201 ~, next_arg function with args = "\"\0"
>  
>  char *next_arg(char *args, char **param, char **val) <-- args = "\"\0".
>  {
> unsigned int i, equals = 0;
> int in_quote = 0, quoted = 0;
> char *next;
> 
> if (*args == '"') {   <-- *args == '"' is a true condition,
> args++;   <-- args++, so *args = '\0'.
> in_quote = 1;
> quoted = 1;   <-- quoted also set 1.
> }
> 
> for (i = 0; args[i]; i++) { <-- when reached this point, i = 0, and 
> arg[0] == '\0',
> so for loop is skipped.
> if (isspace(args[i]) && !in_quote)
> break;
> if (equals == 0) {
> if (args[i] == '=')
> equals = i;
> }
> if (args[i] == '"')
> in_quote = !in_quote;
> }
> 
> *param = args;
> if (!equals)
> *val = NULL;
> else {
> args[equals] = '\0';
> *val = args + equals + 1;
> 
> /* Don't include quotes in value. */
> if (**val == '"') {
> (*val)++;
> if (args[i-1] == '"')
> args[i-1] = '\0';
> }
> }
> if (quoted && args[i-1] == '"') <-- When reached this point, quoted 
> is still set 1, 
> "i" is still 0, and "i" is 
> unsigned int type,
> so address will be {address of 
> args} + 0x.
> It can make a crash.
> args[i-1] = '\0';
> 
> if (args[i]) {
> args[i] = '\0';
> next = args + i + 1;
> } else
> next = args + i;
> 
> /* Chew up trailing spaces. */
> return skip_spaces(next);
>  }
> 
> 
>> Can you provide a KUnit test module which can check the case?
> 
>  If necessary, I will make it and share it.

Hi,
Have you tested this patch?
If so, how?


> 
>  lib/cmdline.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/lib/cmdline.c b/lib/cmdline.c
> index fbb9981a04a4..2fd29d7723b2 100644
> --- a/lib/cmdline.c
> +++ b/lib/cmdline.c
> @@ -200,7 +200,7 @@ bool parse_option_str(const char *str, const char *option)
>   */
>  char *next_arg(char *args, char **param, char **val)
>  {
> - unsigned int i, equals = 0;
> + int i, equals = 0;
>   int in_quote = 0, quoted = 0;
>   char *next;
>  
> 

thanks.
-- 
~Randy



[PATCH v2] lib/cmdline: prevent unintented access to address

2020-08-12 Thread Seungil Kang
When args = "\"\0", "i" will be 0 and args[i-1] is used. (*lib/cmdline.c +238)
Because of "i" is an unsigned int type, the function will access at 
args[0x].
It can make a crash.

Signed-off-by: Seungil Kang 
---

Thanks for your review, my comments below

> Can you be less ambiguous with the args value? (Perhaps provide a hexdump of 
> it
for better understanding)

 This kind of args as hexdump below can cause crash.
 
 : 736f 6d65 7468 696e 6731 3d73 6f6d 655f  something1=some_
 0010: 7661 6c75 6573 2022      values "
 
 The args end with "\"\0".

> Please, use proper punctuation, I'm lost where is the sentence and what are 
> the
logical parts of them.

 I'm sorry to confuse you. I fix the commit msg

> Can you point out to the code that calls this and leads to a crash?

 *lib/cmdlinc + 201 ~, next_arg function with args = "\"\0"
 
 char *next_arg(char *args, char **param, char **val) <-- args = "\"\0".
 {
unsigned int i, equals = 0;
int in_quote = 0, quoted = 0;
char *next;

if (*args == '"') {   <-- *args == '"' is a true condition,
args++;   <-- args++, so *args = '\0'.
in_quote = 1;
quoted = 1;   <-- quoted also set 1.
}

for (i = 0; args[i]; i++) { <-- when reached this point, i = 0, and 
arg[0] == '\0',
so for loop is skipped.
if (isspace(args[i]) && !in_quote)
break;
if (equals == 0) {
if (args[i] == '=')
equals = i;
}
if (args[i] == '"')
in_quote = !in_quote;
}

*param = args;
if (!equals)
*val = NULL;
else {
args[equals] = '\0';
*val = args + equals + 1;

/* Don't include quotes in value. */
if (**val == '"') {
(*val)++;
if (args[i-1] == '"')
args[i-1] = '\0';
}
}
if (quoted && args[i-1] == '"') <-- When reached this point, quoted is 
still set 1, 
"i" is still 0, and "i" is unsigned 
int type,
so address will be {address of 
args} + 0x.
It can make a crash.
args[i-1] = '\0';

if (args[i]) {
args[i] = '\0';
next = args + i + 1;
} else
next = args + i;

/* Chew up trailing spaces. */
return skip_spaces(next);
 }


> Can you provide a KUnit test module which can check the case?

 If necessary, I will make it and share it.

 lib/cmdline.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/lib/cmdline.c b/lib/cmdline.c
index fbb9981a04a4..2fd29d7723b2 100644
--- a/lib/cmdline.c
+++ b/lib/cmdline.c
@@ -200,7 +200,7 @@ bool parse_option_str(const char *str, const char *option)
  */
 char *next_arg(char *args, char **param, char **val)
 {
-   unsigned int i, equals = 0;
+   int i, equals = 0;
int in_quote = 0, quoted = 0;
char *next;
 
-- 
2.17.1