diff mbox

APEI / ERST: Fix missing error handling in erst_reader()

Message ID 20171214123116.929-1-tiwai@suse.de (mailing list archive)
State Accepted, archived
Delegated to: Rafael Wysocki
Headers show

Commit Message

Takashi Iwai Dec. 14, 2017, 12:31 p.m. UTC
The commit f6f828513290 ("pstore: pass allocated memory region back to
caller") changed the check of the return value from erst_read() in
erst_reader() in the following way:

        if (len == -ENOENT)
                goto skip;
-       else if (len < 0) {
-               rc = -1;
+       else if (len < sizeof(*rcd)) {
+               rc = -EIO;
                goto out;

This introduced another bug: since the comparison with sizeof() is
cast to unsigned, a negative len value doesn't hit any longer.
As a result, when an error is returned from erst_read(), the code
falls through, and it may eventually lead to some weird thing like
memory corruption.

This patch adds the negative error value check more explicitly for
addressing the issue.

Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller")
Cc: <stable@vger.kernel.org>
Tested-by: Jerry Tang <jtang@suse.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
 drivers/acpi/apei/erst.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Rafael J. Wysocki Dec. 15, 2017, 1:01 a.m. UTC | #1
On Thu, Dec 14, 2017 at 1:31 PM, Takashi Iwai <tiwai@suse.de> wrote:
> The commit f6f828513290 ("pstore: pass allocated memory region back to
> caller") changed the check of the return value from erst_read() in
> erst_reader() in the following way:
>
>         if (len == -ENOENT)
>                 goto skip;
> -       else if (len < 0) {
> -               rc = -1;
> +       else if (len < sizeof(*rcd)) {
> +               rc = -EIO;
>                 goto out;
>
> This introduced another bug: since the comparison with sizeof() is
> cast to unsigned, a negative len value doesn't hit any longer.
> As a result, when an error is returned from erst_read(), the code
> falls through, and it may eventually lead to some weird thing like
> memory corruption.
>
> This patch adds the negative error value check more explicitly for
> addressing the issue.
>
> Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller")

That's ancient. :-)

> Cc: <stable@vger.kernel.org>
> Tested-by: Jerry Tang <jtang@suse.com>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> ---
>  drivers/acpi/apei/erst.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
> index 6742f6c68034..9bff853e85f3 100644
> --- a/drivers/acpi/apei/erst.c
> +++ b/drivers/acpi/apei/erst.c
> @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record *record)
>         /* The record may be cleared by others, try read next record */
>         if (len == -ENOENT)
>                 goto skip;
> -       else if (len < sizeof(*rcd)) {
> +       else if (len < 0 || len < sizeof(*rcd)) {
>                 rc = -EIO;
>                 goto out;
>         }
> --

OK, I'm going to queue this up unless I see objections from Boris or Tony.

Thanks,
Rafael
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Kees Cook Dec. 15, 2017, 1:05 a.m. UTC | #2
On Thu, Dec 14, 2017 at 5:01 PM, Rafael J. Wysocki <rafael@kernel.org> wrote:
> On Thu, Dec 14, 2017 at 1:31 PM, Takashi Iwai <tiwai@suse.de> wrote:
>> The commit f6f828513290 ("pstore: pass allocated memory region back to
>> caller") changed the check of the return value from erst_read() in
>> erst_reader() in the following way:
>>
>>         if (len == -ENOENT)
>>                 goto skip;
>> -       else if (len < 0) {
>> -               rc = -1;
>> +       else if (len < sizeof(*rcd)) {
>> +               rc = -EIO;
>>                 goto out;
>>
>> This introduced another bug: since the comparison with sizeof() is
>> cast to unsigned, a negative len value doesn't hit any longer.
>> As a result, when an error is returned from erst_read(), the code
>> falls through, and it may eventually lead to some weird thing like
>> memory corruption.
>>
>> This patch adds the negative error value check more explicitly for
>> addressing the issue.

Ew, nice catch, thanks!

>>
>> Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller")
>
> That's ancient. :-)
>
>> Cc: <stable@vger.kernel.org>
>> Tested-by: Jerry Tang <jtang@suse.com>
>> Signed-off-by: Takashi Iwai <tiwai@suse.de>
>> ---
>>  drivers/acpi/apei/erst.c | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
>> index 6742f6c68034..9bff853e85f3 100644
>> --- a/drivers/acpi/apei/erst.c
>> +++ b/drivers/acpi/apei/erst.c
>> @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record *record)
>>         /* The record may be cleared by others, try read next record */
>>         if (len == -ENOENT)
>>                 goto skip;
>> -       else if (len < sizeof(*rcd)) {
>> +       else if (len < 0 || len < sizeof(*rcd)) {
>>                 rc = -EIO;
>>                 goto out;
>>         }
>> --
>
> OK, I'm going to queue this up unless I see objections from Boris or Tony.

Please do, yes.

Acked-by: Kees Cook <keescook@chromium.org>

-Kees
Takashi Iwai Dec. 15, 2017, 7:22 a.m. UTC | #3
On Fri, 15 Dec 2017 02:01:20 +0100,
Rafael J. Wysocki wrote:
> 
> On Thu, Dec 14, 2017 at 1:31 PM, Takashi Iwai <tiwai@suse.de> wrote:
> > The commit f6f828513290 ("pstore: pass allocated memory region back to
> > caller") changed the check of the return value from erst_read() in
> > erst_reader() in the following way:
> >
> >         if (len == -ENOENT)
> >                 goto skip;
> > -       else if (len < 0) {
> > -               rc = -1;
> > +       else if (len < sizeof(*rcd)) {
> > +               rc = -EIO;
> >                 goto out;
> >
> > This introduced another bug: since the comparison with sizeof() is
> > cast to unsigned, a negative len value doesn't hit any longer.
> > As a result, when an error is returned from erst_read(), the code
> > falls through, and it may eventually lead to some weird thing like
> > memory corruption.
> >
> > This patch adds the negative error value check more explicitly for
> > addressing the issue.
> >
> > Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller")
> 
> That's ancient. :-)
> 
> > Cc: <stable@vger.kernel.org>
> > Tested-by: Jerry Tang <jtang@suse.com>
> > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > ---
> >  drivers/acpi/apei/erst.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
> > index 6742f6c68034..9bff853e85f3 100644
> > --- a/drivers/acpi/apei/erst.c
> > +++ b/drivers/acpi/apei/erst.c
> > @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record *record)
> >         /* The record may be cleared by others, try read next record */
> >         if (len == -ENOENT)
> >                 goto skip;
> > -       else if (len < sizeof(*rcd)) {
> > +       else if (len < 0 || len < sizeof(*rcd)) {
> >                 rc = -EIO;
> >                 goto out;
> >         }
> > --
> 
> OK, I'm going to queue this up unless I see objections from Boris or Tony.

I missed Boris in Cc list, sorry.  Now added.


Takashi
--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Borislav Petkov Dec. 15, 2017, 10:52 a.m. UTC | #4
On Fri, Dec 15, 2017 at 08:22:32AM +0100, Takashi Iwai wrote:
> On Fri, 15 Dec 2017 02:01:20 +0100,
> Rafael J. Wysocki wrote:
> > 
> > On Thu, Dec 14, 2017 at 1:31 PM, Takashi Iwai <tiwai@suse.de> wrote:
> > > The commit f6f828513290 ("pstore: pass allocated memory region back to
> > > caller") changed the check of the return value from erst_read() in
> > > erst_reader() in the following way:
> > >
> > >         if (len == -ENOENT)
> > >                 goto skip;
> > > -       else if (len < 0) {
> > > -               rc = -1;
> > > +       else if (len < sizeof(*rcd)) {
> > > +               rc = -EIO;
> > >                 goto out;
> > >
> > > This introduced another bug: since the comparison with sizeof() is
> > > cast to unsigned, a negative len value doesn't hit any longer.
> > > As a result, when an error is returned from erst_read(), the code
> > > falls through, and it may eventually lead to some weird thing like
> > > memory corruption.
> > >
> > > This patch adds the negative error value check more explicitly for
> > > addressing the issue.
> > >
> > > Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller")
> > 
> > That's ancient. :-)
> > 
> > > Cc: <stable@vger.kernel.org>
> > > Tested-by: Jerry Tang <jtang@suse.com>
> > > Signed-off-by: Takashi Iwai <tiwai@suse.de>
> > > ---
> > >  drivers/acpi/apei/erst.c | 2 +-
> > >  1 file changed, 1 insertion(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
> > > index 6742f6c68034..9bff853e85f3 100644
> > > --- a/drivers/acpi/apei/erst.c
> > > +++ b/drivers/acpi/apei/erst.c
> > > @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record *record)
> > >         /* The record may be cleared by others, try read next record */
> > >         if (len == -ENOENT)
> > >                 goto skip;
> > > -       else if (len < sizeof(*rcd)) {
> > > +       else if (len < 0 || len < sizeof(*rcd)) {
> > >                 rc = -EIO;
> > >                 goto out;
> > >         }
> > > --
> > 
> > OK, I'm going to queue this up unless I see objections from Boris or Tony.
> 
> I missed Boris in Cc list, sorry.  Now added.

LGTM.

Reviewed-by: Borislav Petkov <bp@suse.de>
Rafael J. Wysocki Dec. 17, 2017, 5:37 p.m. UTC | #5
On Thursday, December 14, 2017 1:31:16 PM CET Takashi Iwai wrote:
> The commit f6f828513290 ("pstore: pass allocated memory region back to
> caller") changed the check of the return value from erst_read() in
> erst_reader() in the following way:
> 
>         if (len == -ENOENT)
>                 goto skip;
> -       else if (len < 0) {
> -               rc = -1;
> +       else if (len < sizeof(*rcd)) {
> +               rc = -EIO;
>                 goto out;
> 
> This introduced another bug: since the comparison with sizeof() is
> cast to unsigned, a negative len value doesn't hit any longer.
> As a result, when an error is returned from erst_read(), the code
> falls through, and it may eventually lead to some weird thing like
> memory corruption.
> 
> This patch adds the negative error value check more explicitly for
> addressing the issue.
> 
> Fixes: f6f828513290 ("pstore: pass allocated memory region back to caller")
> Cc: <stable@vger.kernel.org>
> Tested-by: Jerry Tang <jtang@suse.com>
> Signed-off-by: Takashi Iwai <tiwai@suse.de>
> ---
>  drivers/acpi/apei/erst.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
> index 6742f6c68034..9bff853e85f3 100644
> --- a/drivers/acpi/apei/erst.c
> +++ b/drivers/acpi/apei/erst.c
> @@ -1007,7 +1007,7 @@ static ssize_t erst_reader(struct pstore_record *record)
>  	/* The record may be cleared by others, try read next record */
>  	if (len == -ENOENT)
>  		goto skip;
> -	else if (len < sizeof(*rcd)) {
> +	else if (len < 0 || len < sizeof(*rcd)) {
>  		rc = -EIO;
>  		goto out;
>  	}
> 

Applied, thanks!


--
To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/acpi/apei/erst.c b/drivers/acpi/apei/erst.c
index 6742f6c68034..9bff853e85f3 100644
--- a/drivers/acpi/apei/erst.c
+++ b/drivers/acpi/apei/erst.c
@@ -1007,7 +1007,7 @@  static ssize_t erst_reader(struct pstore_record *record)
 	/* The record may be cleared by others, try read next record */
 	if (len == -ENOENT)
 		goto skip;
-	else if (len < sizeof(*rcd)) {
+	else if (len < 0 || len < sizeof(*rcd)) {
 		rc = -EIO;
 		goto out;
 	}