diff mbox series

elf-ops.h: fix int overflow in load_elf()

Message ID 20190910090821.28327-1-sgarzare@redhat.com (mailing list archive)
State New, archived
Headers show
Series elf-ops.h: fix int overflow in load_elf() | expand

Commit Message

Stefano Garzarella Sept. 10, 2019, 9:08 a.m. UTC
This patch fixes a possible integer overflow when we calculate
the total size of ELF segments loaded.

Reported-by: Coverity (CID 1405299)
Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
---
Now we are limited to INT_MAX, should load_elf() returns ssize_t
to support bigger ELFs?
---
 include/hw/elf_ops.h | 6 ++++++
 hw/core/loader.c     | 1 +
 2 files changed, 7 insertions(+)

Comments

Peter Maydell Sept. 10, 2019, 9:37 a.m. UTC | #1
On Tue, 10 Sep 2019 at 10:08, Stefano Garzarella <sgarzare@redhat.com> wrote:
>
> This patch fixes a possible integer overflow when we calculate
> the total size of ELF segments loaded.
>
> Reported-by: Coverity (CID 1405299)
> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> ---
> Now we are limited to INT_MAX, should load_elf() returns ssize_t
> to support bigger ELFs?
> ---
>  include/hw/elf_ops.h | 6 ++++++
>  hw/core/loader.c     | 1 +
>  2 files changed, 7 insertions(+)
>
> diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
> index 1496d7e753..46dd3bf413 100644
> --- a/include/hw/elf_ops.h
> +++ b/include/hw/elf_ops.h
> @@ -485,6 +485,12 @@ static int glue(load_elf, SZ)(const char *name, int fd,
>                  }
>              }
>
> +            if (mem_size > INT_MAX - total_size) {
> +                error_report("ELF total segments size is too big to load "
> +                             "max is %d)", INT_MAX);
> +                goto fail;
> +            }

This function doesn't report issues via error_report()
(some callers intentionally have fallback options for
what they try to do with the file), but by returning
a suitable error value in 'ret', so I think we should
continue that approach rather than adding an error_report()
call here.

I agree that accumulating the size in an 'int' is a bit
dubious these days.

thanks
-- PMM
Stefano Garzarella Sept. 10, 2019, 9:47 a.m. UTC | #2
On Tue, Sep 10, 2019 at 10:37:28AM +0100, Peter Maydell wrote:
> On Tue, 10 Sep 2019 at 10:08, Stefano Garzarella <sgarzare@redhat.com> wrote:
> >
> > This patch fixes a possible integer overflow when we calculate
> > the total size of ELF segments loaded.
> >
> > Reported-by: Coverity (CID 1405299)
> > Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> > ---
> > Now we are limited to INT_MAX, should load_elf() returns ssize_t
> > to support bigger ELFs?
> > ---
> >  include/hw/elf_ops.h | 6 ++++++
> >  hw/core/loader.c     | 1 +
> >  2 files changed, 7 insertions(+)
> >
> > diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
> > index 1496d7e753..46dd3bf413 100644
> > --- a/include/hw/elf_ops.h
> > +++ b/include/hw/elf_ops.h
> > @@ -485,6 +485,12 @@ static int glue(load_elf, SZ)(const char *name, int fd,
> >                  }
> >              }
> >
> > +            if (mem_size > INT_MAX - total_size) {
> > +                error_report("ELF total segments size is too big to load "
> > +                             "max is %d)", INT_MAX);
> > +                goto fail;
> > +            }
> 
> This function doesn't report issues via error_report()
> (some callers intentionally have fallback options for
> what they try to do with the file), but by returning
> a suitable error value in 'ret', so I think we should
> continue that approach rather than adding an error_report()
> call here.

I agree, maybe I can add a new macro "ELF_LOAD_TOO_BIG" and
add the error message to load_elf_strerror().

I'll send a v2.

> 
> I agree that accumulating the size in an 'int' is a bit
> dubious these days.

Maybe I can send another patch to change it and wherever it's used.

Thanks,
Stefano
Alex Bennée Sept. 10, 2019, 9:50 a.m. UTC | #3
Stefano Garzarella <sgarzare@redhat.com> writes:

> This patch fixes a possible integer overflow when we calculate
> the total size of ELF segments loaded.
>
> Reported-by: Coverity (CID 1405299)
> Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> ---
> Now we are limited to INT_MAX, should load_elf() returns ssize_t
> to support bigger ELFs?
> ---
>  include/hw/elf_ops.h | 6 ++++++
>  hw/core/loader.c     | 1 +
>  2 files changed, 7 insertions(+)
>
> diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
> index 1496d7e753..46dd3bf413 100644
> --- a/include/hw/elf_ops.h
> +++ b/include/hw/elf_ops.h
> @@ -485,6 +485,12 @@ static int glue(load_elf, SZ)(const char *name, int fd,
>                  }
>              }
>
> +            if (mem_size > INT_MAX - total_size) {
> +                error_report("ELF total segments size is too big to load "
> +                             "max is %d)", INT_MAX);
> +                goto fail;
> +            }
> +

Seem sensible enough (although gah, I hate these glue bits). Would the
large amount of goto fail logic be something that could be cleaned up
with the automatic cleanup functions we recently mentioned in
CODING_STYLE.rst?

Anyway:

Reviewed-by: Alex Bennée <alex.bennee@linaro.org>


>              /* address_offset is hack for kernel images that are
>                 linked at the wrong physical address.  */
>              if (translate_fn) {
> diff --git a/hw/core/loader.c b/hw/core/loader.c
> index 32f7cc7c33..feda52fa88 100644
> --- a/hw/core/loader.c
> +++ b/hw/core/loader.c
> @@ -44,6 +44,7 @@
>
>  #include "qemu/osdep.h"
>  #include "qemu-common.h"
> +#include "qemu/error-report.h"
>  #include "qapi/error.h"
>  #include "hw/hw.h"
>  #include "disas/disas.h"


--
Alex Bennée
Daniel P. Berrangé Sept. 10, 2019, 9:53 a.m. UTC | #4
On Tue, Sep 10, 2019 at 10:50:30AM +0100, Alex Bennée wrote:
> 
> Stefano Garzarella <sgarzare@redhat.com> writes:
> 
> > This patch fixes a possible integer overflow when we calculate
> > the total size of ELF segments loaded.
> >
> > Reported-by: Coverity (CID 1405299)
> > Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> > ---
> > Now we are limited to INT_MAX, should load_elf() returns ssize_t
> > to support bigger ELFs?
> > ---
> >  include/hw/elf_ops.h | 6 ++++++
> >  hw/core/loader.c     | 1 +
> >  2 files changed, 7 insertions(+)
> >
> > diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
> > index 1496d7e753..46dd3bf413 100644
> > --- a/include/hw/elf_ops.h
> > +++ b/include/hw/elf_ops.h
> > @@ -485,6 +485,12 @@ static int glue(load_elf, SZ)(const char *name, int fd,
> >                  }
> >              }
> >
> > +            if (mem_size > INT_MAX - total_size) {
> > +                error_report("ELF total segments size is too big to load "
> > +                             "max is %d)", INT_MAX);
> > +                goto fail;
> > +            }
> > +
> 
> Seem sensible enough (although gah, I hate these glue bits). Would the
> large amount of goto fail logic be something that could be cleaned up
> with the automatic cleanup functions we recently mentioned in
> CODING_STYLE.rst?

The target has this:

 fail:
    g_mapped_file_unref(mapped_file);
    g_free(phdr);
    return ret;



GMappedFIle supports the  g_autoptr cleanup, and g_free is trivially
done with g_autofree.

So yes, you can entirely kill the goto's in this function using
auto cleanup

> 
> Anyway:
> 
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
> 

Regards,
Daniel
Peter Maydell Sept. 10, 2019, 9:54 a.m. UTC | #5
On Tue, 10 Sep 2019 at 10:50, Alex Bennée <alex.bennee@linaro.org> wrote:
> Seem sensible enough (although gah, I hate these glue bits). Would the
> large amount of goto fail logic be something that could be cleaned up
> with the automatic cleanup functions we recently mentioned in
> CODING_STYLE.rst?

Probably not, because one bit of cleanup we *should* be doing
in the fail-exit codepaths but currently don't is to delete
any rom blobs we created for earlier segments in the ELF file
before we gave up, so we need to have an error-exit path anyway...

thanks
-- PMM
Stefano Garzarella Sept. 10, 2019, 11:02 a.m. UTC | #6
On Tue, Sep 10, 2019 at 10:54:25AM +0100, Peter Maydell wrote:
> On Tue, 10 Sep 2019 at 10:50, Alex Bennée <alex.bennee@linaro.org> wrote:
> > Seem sensible enough (although gah, I hate these glue bits). Would the
> > large amount of goto fail logic be something that could be cleaned up
> > with the automatic cleanup functions we recently mentioned in
> > CODING_STYLE.rst?
> 
> Probably not, because one bit of cleanup we *should* be doing
> in the fail-exit codepaths but currently don't is to delete
> any rom blobs we created for earlier segments in the ELF file
> before we gave up, so we need to have an error-exit path anyway...

Mmm right, I should add a new API (e.g. rom_remove()) to do this better
cleanup.

> 
> thanks
> -- PMM
>
Stefano Garzarella Sept. 10, 2019, 11:07 a.m. UTC | #7
On Tue, Sep 10, 2019 at 10:50:30AM +0100, Alex Bennée wrote:
> 
> Stefano Garzarella <sgarzare@redhat.com> writes:
> 
> > This patch fixes a possible integer overflow when we calculate
> > the total size of ELF segments loaded.
> >
> > Reported-by: Coverity (CID 1405299)
> > Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
> > ---
> > Now we are limited to INT_MAX, should load_elf() returns ssize_t
> > to support bigger ELFs?
> > ---
> >  include/hw/elf_ops.h | 6 ++++++
> >  hw/core/loader.c     | 1 +
> >  2 files changed, 7 insertions(+)
> >
> > diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
> > index 1496d7e753..46dd3bf413 100644
> > --- a/include/hw/elf_ops.h
> > +++ b/include/hw/elf_ops.h
> > @@ -485,6 +485,12 @@ static int glue(load_elf, SZ)(const char *name, int fd,
> >                  }
> >              }
> >
> > +            if (mem_size > INT_MAX - total_size) {
> > +                error_report("ELF total segments size is too big to load "
> > +                             "max is %d)", INT_MAX);
> > +                goto fail;
> > +            }
> > +
> 
> Seem sensible enough (although gah, I hate these glue bits). Would the
> large amount of goto fail logic be something that could be cleaned up
> with the automatic cleanup functions we recently mentioned in
> CODING_STYLE.rst?
> 

As Peter pointed out, maybe we should keep the 'goto fail' and do a
better cleanup, but thanks to pointing that out to me.

> Anyway:
> 
> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>

Thanks for the review!

I'm sending a v2 following the Peter's suggestions,
removing the error_report and returing a new ELF_LOAD_TOO_BIG error
value.

Can I keep your R-b, or would you like to have a look at v2?

Thanks,
Stefano
Alex Bennée Sept. 10, 2019, 12:12 p.m. UTC | #8
Stefano Garzarella <sgarzare@redhat.com> writes:

> On Tue, Sep 10, 2019 at 10:50:30AM +0100, Alex Bennée wrote:
>>
>> Stefano Garzarella <sgarzare@redhat.com> writes:
>>
>> > This patch fixes a possible integer overflow when we calculate
>> > the total size of ELF segments loaded.
>> >
>> > Reported-by: Coverity (CID 1405299)
>> > Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
>> > ---
>> > Now we are limited to INT_MAX, should load_elf() returns ssize_t
>> > to support bigger ELFs?
>> > ---
>> >  include/hw/elf_ops.h | 6 ++++++
>> >  hw/core/loader.c     | 1 +
>> >  2 files changed, 7 insertions(+)
>> >
>> > diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
>> > index 1496d7e753..46dd3bf413 100644
>> > --- a/include/hw/elf_ops.h
>> > +++ b/include/hw/elf_ops.h
>> > @@ -485,6 +485,12 @@ static int glue(load_elf, SZ)(const char *name, int fd,
>> >                  }
>> >              }
>> >
>> > +            if (mem_size > INT_MAX - total_size) {
>> > +                error_report("ELF total segments size is too big to load "
>> > +                             "max is %d)", INT_MAX);
>> > +                goto fail;
>> > +            }
>> > +
>>
>> Seem sensible enough (although gah, I hate these glue bits). Would the
>> large amount of goto fail logic be something that could be cleaned up
>> with the automatic cleanup functions we recently mentioned in
>> CODING_STYLE.rst?
>>
>
> As Peter pointed out, maybe we should keep the 'goto fail' and do a
> better cleanup, but thanks to pointing that out to me.
>
>> Anyway:
>>
>> Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
>
> Thanks for the review!
>
> I'm sending a v2 following the Peter's suggestions,
> removing the error_report and returing a new ELF_LOAD_TOO_BIG error
> value.
>
> Can I keep your R-b, or would you like to have a look at v2?

I'm happy with that - I'm not super familiar with the Elf code although
I'm about to become so....

>
> Thanks,
> Stefano


--
Alex Bennée
diff mbox series

Patch

diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index 1496d7e753..46dd3bf413 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -485,6 +485,12 @@  static int glue(load_elf, SZ)(const char *name, int fd,
                 }
             }
 
+            if (mem_size > INT_MAX - total_size) {
+                error_report("ELF total segments size is too big to load "
+                             "max is %d)", INT_MAX);
+                goto fail;
+            }
+
             /* address_offset is hack for kernel images that are
                linked at the wrong physical address.  */
             if (translate_fn) {
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 32f7cc7c33..feda52fa88 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -44,6 +44,7 @@ 
 
 #include "qemu/osdep.h"
 #include "qemu-common.h"
+#include "qemu/error-report.h"
 #include "qapi/error.h"
 #include "hw/hw.h"
 #include "disas/disas.h"