libcdio-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Libcdio-devel] proposed fix for bug #22865


From: Rocky Bernstein
Subject: Re: [Libcdio-devel] proposed fix for bug #22865
Date: Mon, 23 Jan 2012 23:09:15 -0500

On Mon, Jan 23, 2012 at 12:43 PM, Pete Batard <address@hidden> wrote:

> OK, here is my actual proposed fix for #22865.
>

Overall looks okay. The only thing I'd like to suggest is to be mindful
about Doxygen comments which start /** and /**<

See http://www.gnu.org/software/libcdio/doxygen/ecma__167_8h.html

And as I look at it now, boy it looks ugly and needs attention.


> Haven't applied it to my branch as I want to see if it looks sound to you,
> or if you prefer something different.
>

Again that's find. Just apply without mixing other commits in so that I can
work towards testing just this piece of it.  (Or saying this in the
converse: mixing multiple concerns into a commit will make it harder to
disentangle and test each concern.)


> Also note that I'm adding an assert for the size of udf_file_entry_t in
> udf_open.
>

That's fine. It's okay  to use asserts and for things like this.


>
> Once this patch is applied, and if you test against the Windows 8 preview,
> you will still end up with "Error reading UDF file /sources/install.wim" on
> Linux 32 bit (haven't test x64), but this time it should be due to a 32 bit
> offset issue. I'll discuss that in an upcoming mail.
>
> Regards,
>
> /Pete
> From 0d5e54af5ce136929ef714f5988ba689e8d42656 Mon Sep 17 00:00:00 2001
> From: Pete Batard <address@hidden>
> Date: Mon, 23 Jan 2012 12:34:11 +0000
> Subject: [PATCH] Fix buffer overflow when reusing an UDF file entry
>
> * use an union to ensure a file entry is always the maximum
>  allocatable size as per specs
> * this is bug #22865
> ---
>  include/cdio/ecma_167.h |   10 ++++++++--
>  lib/udf/udf_file.c      |    5 ++---
>  lib/udf/udf_fs.c        |   36 +++++++++++++++---------------------
>  3 files changed, 25 insertions(+), 26 deletions(-)
>
> diff --git a/include/cdio/ecma_167.h b/include/cdio/ecma_167.h
> index 78da7ae..9c7c1bb 100644
> --- a/include/cdio/ecma_167.h
> +++ b/include/cdio/ecma_167.h
> @@ -727,8 +727,14 @@ struct udf_file_entry_s
>   udf_Uint64_t   unique_ID;
>   udf_Uint32_t   i_extended_attr;
>   udf_Uint32_t   i_alloc_descs;
> -  udf_Uint8_t    ext_attr[0];
> -  udf_Uint8_t    alloc_descs[0];
> +  /* The following union allows file entry reuse without worrying
> +     about overflows, by ensuring the struct is always the
> +     maximum possible size allowed by the specs: one UDF block. */
> +  union {
> +    udf_Uint8_t          ext_attr[0];
> +    udf_Uint8_t          alloc_descs[0];
> +    udf_Uint8_t          pad_to_one_block[2048-176];
> +  } u;
>  } GNUC_PACKED;
>
>  typedef struct udf_file_entry_s udf_file_entry_t;
> diff --git a/lib/udf/udf_file.c b/lib/udf/udf_file.c
> index ee766a8..ca4d920 100644
> --- a/lib/udf/udf_file.c
> +++ b/lib/udf/udf_file.c
> @@ -34,7 +34,7 @@
>  #define CEILING(x, y) ((x+(y-1))/y)
>
>  #define        GETICB(offset)  \
> -       &p_udf_fe->alloc_descs[offset]
> +       &p_udf_fe->u.alloc_descs[offset]
>
>  const char *
>  udf_get_filename(const udf_dirent_t *p_udf_dirent)
> @@ -44,8 +44,7 @@ udf_get_filename(const udf_dirent_t *p_udf_dirent)
>   return p_udf_dirent->psz_name;
>  }
>
> -/* Get UDF File Entry. However we do NOT get the variable-length extended
> - attributes. */
> +/* Copy an UDF File Entry into a Directory Entry structure. */
>  bool
>  udf_get_file_entry(const udf_dirent_t *p_udf_dirent,
>                   /*out*/ udf_file_entry_t *p_udf_fe)
> diff --git a/lib/udf/udf_fs.c b/lib/udf/udf_fs.c
> index dcd6e53..eb1da77 100644
> --- a/lib/udf/udf_fs.c
> +++ b/lib/udf/udf_fs.c
> @@ -68,6 +68,7 @@ const char VSD_STD_ID_TEA01[] = {'T', 'E', 'A', '0',
> '1'};
>  #include <cdio/bytesex.h>
>  #include "udf_private.h"
>  #include "udf_fs.h"
> +#include "cdio_assert.h"
>
>  /*
>  * The UDF specs are pretty clear on how each data structure is made
> @@ -154,7 +155,7 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
>     {
>       /* The allocation descriptor field is filled with short_ad's. */
>       udf_short_ad_t *p_ad = (udf_short_ad_t *)
> -       (p_udf_fe->ext_attr + p_udf_fe->i_extended_attr);
> +       (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
>
>       *start = uint32_from_le(p_ad->pos);
>       *end = *start +
> @@ -166,7 +167,7 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
>     {
>       /* The allocation descriptor field is filled with long_ad's */
>       udf_long_ad_t *p_ad = (udf_long_ad_t *)
> -       (p_udf_fe->ext_attr + p_udf_fe->i_extended_attr);
> +       (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
>
>       *start = uint32_from_le(p_ad->loc.lba); /* ignore partition number */
>       *end = *start +
> @@ -177,7 +178,7 @@ udf_get_lba(const udf_file_entry_t *p_udf_fe,
>   case ICBTAG_FLAG_AD_EXTENDED:
>     {
>       udf_ext_ad_t *p_ad = (udf_ext_ad_t *)
> -       (p_udf_fe->ext_attr + p_udf_fe->i_extended_attr);
> +       (p_udf_fe->u.ext_attr + p_udf_fe->i_extended_attr);
>
>       *start = uint32_from_le(p_ad->ext_loc.lba); /* ignore partition
> number */
>       *end = *start +
> @@ -287,11 +288,8 @@ static udf_dirent_t *
>  udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t *p_udf,
>               const char *psz_name, bool b_dir, bool b_parent)
>  {
> -  const unsigned int i_alloc_size = p_udf_fe->i_alloc_descs
> -    + p_udf_fe->i_extended_attr;
> -
>   udf_dirent_t *p_udf_dirent = (udf_dirent_t *)
> -    calloc(1, sizeof(udf_dirent_t) + i_alloc_size);
> +    calloc(1, sizeof(udf_dirent_t));
>   if (!p_udf_dirent) return NULL;
>
>   p_udf_dirent->psz_name     = strdup(psz_name);
> @@ -302,7 +300,7 @@ udf_new_dirent(udf_file_entry_t *p_udf_fe, udf_t
> *p_udf,
>   p_udf_dirent->dir_left     = uint64_from_le(p_udf_fe->info_len);
>
>   memcpy(&(p_udf_dirent->fe), p_udf_fe,
> -        sizeof(udf_file_entry_t) + i_alloc_size);
> +        sizeof(udf_file_entry_t));
>   udf_get_lba( p_udf_fe, &(p_udf_dirent->i_loc),
>               &(p_udf_dirent->i_loc_end) );
>   return p_udf_dirent;
> @@ -349,6 +347,9 @@ udf_open (const char *psz_path)
>
>   if (!p_udf) return NULL;
>
> +  /* Sanity check */
> +  cdio_assert(sizeof(udf_file_entry_t) == UDF_BLOCKSIZE);
> +
>   p_udf->cdio = cdio_open(psz_path, DRIVER_UNKNOWN);
>   if (!p_udf->cdio) {
>     /* Not a CD-ROM drive or CD Image. Maybe it's a UDF file not
> @@ -585,19 +586,18 @@ udf_opendir(const udf_dirent_t *p_udf_dirent)
>  {
>   if (p_udf_dirent->b_dir && !p_udf_dirent->b_parent && p_udf_dirent->fid)
> {
>     udf_t *p_udf = p_udf_dirent->p_udf;
> -    uint8_t data[UDF_BLOCKSIZE];
> -    udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) &data;
> +    udf_file_entry_t udf_fe;
>
>     driver_return_code_t i_ret =
> -      udf_read_sectors(p_udf, p_udf_fe, p_udf->i_part_start
> +      udf_read_sectors(p_udf, &udf_fe, p_udf->i_part_start
>                       + p_udf_dirent->fid->icb.loc.lba, 1);
>
>     if (DRIVER_OP_SUCCESS == i_ret
> -       && !udf_checktag(&p_udf_fe->tag, TAGID_FILE_ENTRY)) {
> +       && !udf_checktag(&udf_fe.tag, TAGID_FILE_ENTRY)) {
>
> -      if (ICBTAG_FILE_TYPE_DIRECTORY == p_udf_fe->icb_tag.file_type) {
> +      if (ICBTAG_FILE_TYPE_DIRECTORY == udf_fe.icb_tag.file_type) {
>        udf_dirent_t *p_udf_dirent_new =
> -         udf_new_dirent(p_udf_fe, p_udf, p_udf_dirent->psz_name, true,
> true);
> +         udf_new_dirent(&udf_fe, p_udf, p_udf_dirent->psz_name, true,
> true);
>        return p_udf_dirent_new;
>       }
>     }
> @@ -661,16 +661,10 @@ udf_readdir(udf_dirent_t *p_udf_dirent)
>
>       {
>        const unsigned int i_len = p_udf_dirent->fid->i_file_id;
> -       uint8_t data[UDF_BLOCKSIZE] = {0};
> -       udf_file_entry_t *p_udf_fe = (udf_file_entry_t *) &data;
>
> -       if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf, p_udf_fe,
> p_udf->i_part_start
> +       if (DRIVER_OP_SUCCESS != udf_read_sectors(p_udf,
> &p_udf_dirent->fe, p_udf->i_part_start
>                         + p_udf_dirent->fid->icb.loc.lba, 1))
>                return NULL;
> -
> -       memcpy(&(p_udf_dirent->fe), p_udf_fe,
> -              sizeof(udf_file_entry_t) + p_udf_fe->i_alloc_descs
> -              + p_udf_fe->i_extended_attr );
>
>        if (strlen(p_udf_dirent->psz_name) < i_len)
>          p_udf_dirent->psz_name = (char *)
> --
> 1.7.8.msysgit.0
>
>
>


reply via email to

[Prev in Thread] Current Thread [Next in Thread]