All of lore.kernel.org
 help / color / mirror / Atom feed
* Possible memory fault in fs/iso9660
@ 2022-11-19 12:38 Thomas Schmitt
  2022-11-19 12:57 ` Possible memory fault in fs/iso9660 (correction) Thomas Schmitt
  0 siblings, 1 reply; 9+ messages in thread
From: Thomas Schmitt @ 2022-11-19 12:38 UTC (permalink / raw)
  To: grub-devel; +Cc: fengtao40

Hi,

(Cc-ing t.feng in the hope that this issue can become part of the code
review.)

While reviewing "[PATCH 7/9]" by t.feng, i wonder whether there is a bug
in grub_iso9660_susp_iterate() in regard to the end of the SUSP data:

  for (entry = (struct grub_iso9660_susp_entry *) sua; (char *) entry < (char *) sua + sua_size - 1 && entry->len > 0;
       entry = (struct grub_iso9660_susp_entry *)
	 ((char *) entry + entry->len))
    {

I think the loop end condition should use 4 rather than 1:

       (char *) entry < (char *) sua + sua_size - 4 && entry->len > 0

The entry struct has at least 4 bytes:

  struct grub_iso9660_susp_entry
  {
    grub_uint8_t sig[2];
    grub_uint8_t len;
    grub_uint8_t version;
    grub_uint8_t data[0];
  } GRUB_PACKED;

Especially the expression
  entry->len > 0
reads beyond the end of the allocated buffer sua if

  entry >= sua + sua_size - 3


It does not look as if there are guard rails installed yet:

The size of the allocated space (parameter sua_size) is determined by the
callers of grub_iso9660_susp_iterate from struct grub_iso9660_dir objects,
which obviously represent ISO 9660 directory entry bytes as read from the
filesystem.

---------------------------------------------------------------------------

So the producer of the ISO filesystem can create in GRUB the impression
of trailing bytes which form no valid SUSP entry. This may even happen in
good faith because a ISO 9660 System Use field may hold data which are not
under control of the SUSP protocol.

There is a "ST" entry specified which explcitely ends the range of SUSP.
But the SUSP specs, both 1.10 and 1.12, mention that a System Use field
or a Continuation area may end without ST entry with up to 3 remaining
bytes which shall be ignored. From SUSP 1.12:

  If the remaining allocated space following the last recorded System Use
  Entry in a System Use field or Continuation Area is less than four bytes
  long, it cannot contain a System Use Entry and shall be ignored.
  Otherwise an "ST" System Use Entry (see section 5.4) shall be the last
  System Use Entry recorded in a System Use field or Continuation Area.

Neither mkisofs/genisominage nor libisofs write any ST entries. At least
for libisofs i can state that there is no trailing non-SUSP data announced
by the size of the directory entry or the Continuation Area.


Have a nice day :)

Thomas



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-19 12:38 Possible memory fault in fs/iso9660 Thomas Schmitt
@ 2022-11-19 12:57 ` Thomas Schmitt
  2022-11-24 13:17   ` Daniel Kiper
  0 siblings, 1 reply; 9+ messages in thread
From: Thomas Schmitt @ 2022-11-19 12:57 UTC (permalink / raw)
  To: grub-devel; +Cc: fengtao40

Hi,

i wrote:
> I think the loop end condition should use 4 rather than 1:
>       (char *) entry < (char *) sua + sua_size - 4 && entry->len > 0

Urm ... better "3 rather than 1":

       (char *) entry < (char *) sua + sua_size - 3 && entry->len > 0

The memory fault by entry->len will appear if
  entry >= sua + sua_size - 2


(Only good i did not submit a patch attempt.
Why is that "- 1" present anyways ? Shall it ensure the presence of
entry->type ?)


Have a nice day :)

Thomas



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-19 12:57 ` Possible memory fault in fs/iso9660 (correction) Thomas Schmitt
@ 2022-11-24 13:17   ` Daniel Kiper
  2022-11-24 15:16     ` Thomas Schmitt
  0 siblings, 1 reply; 9+ messages in thread
From: Daniel Kiper @ 2022-11-24 13:17 UTC (permalink / raw)
  To: Thomas Schmitt; +Cc: grub-devel, fengtao40

On Sat, Nov 19, 2022 at 01:57:59PM +0100, Thomas Schmitt wrote:
> Hi,
>
> i wrote:
> > I think the loop end condition should use 4 rather than 1:
> >       (char *) entry < (char *) sua + sua_size - 4 && entry->len > 0
>
> Urm ... better "3 rather than 1":
>
>        (char *) entry < (char *) sua + sua_size - 3 && entry->len > 0
>
> The memory fault by entry->len will appear if
>   entry >= sua + sua_size - 2
>
>
> (Only good i did not submit a patch attempt.
> Why is that "- 1" present anyways ? Shall it ensure the presence of
> entry->type ?)

I am not an ISO format expert but your thinking LGTM. So, could you send
a patch fixing this issue?

Daniel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-24 13:17   ` Daniel Kiper
@ 2022-11-24 15:16     ` Thomas Schmitt
  2022-11-29  9:32       ` Fengtao (fengtao, Euler)
  0 siblings, 1 reply; 9+ messages in thread
From: Thomas Schmitt @ 2022-11-24 15:16 UTC (permalink / raw)
  To: grub-devel; +Cc: fengtao40

Hi,

(Again i Cc t.feng in the hope that the review is not finished yet. :))

Daniel Kiper wrote:
> I am not an ISO format expert but your thinking LGTM.

So you agree that "3" is really the right number if any remaining bytes
fewer than 4 shall be ignored ?
(I don't trust myself, although i made an example with finger counting.)


> could you send a patch fixing this issue?

This should be possible. But how to test ?

Normal ISOs made with GNU/Linux will cause (entry == sua + sua_size) at
the end of the SUSP data. So provoking the problem and checking whether
it is solved will need a hacked ISO.
I will think about creating such an ISO by help of xorriso and dd.


While exploring the SUSP/RRIP entry types which are interpreted by GRUB,
i got to more credulence towards the ISO producer.
E.g. in grub-core/fs/iso9660.c line 404 ff.

      /* The 2nd data byte stored how many bytes are skipped every time
	 to get to the SUA (System Usage Area).  */
      data->susp_skip = entry->data[2];

This is a memory fault if (sua_size < 7). I see no check between
  sua = grub_malloc (sua_size);
and the read access to entry->data[2].

Another example:
grub_iso9660_susp_iterate() calls its parameter hook() without checking
that the alleged entry size is within the range of sua_size. The hook()
function does not get sua_size to check on its own.

In general:
How mistrusting should GRUB be towards the bytes in the filesystem ?


Have a nice day :)

Thomas



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-24 15:16     ` Thomas Schmitt
@ 2022-11-29  9:32       ` Fengtao (fengtao, Euler)
  2022-11-29 14:26         ` Daniel Kiper
  2022-11-29 18:47         ` Thomas Schmitt
  0 siblings, 2 replies; 9+ messages in thread
From: Fengtao (fengtao, Euler) @ 2022-11-29  9:32 UTC (permalink / raw)
  To: Thomas Schmitt, grub-devel; +Cc: Daniel Kiper, yanan

Hi, Thomas
Sorry for the delay, I am also not familiar with ISO format.
But, i have check the cdrkit src-code[1] and syslinux src-code[2]

I think:
	(char *) entry < (char *) sua + sua_size - 3 && entry->len > 0
is ok, or:
	(char *) entry <= (char *) sua + sua_size - 4 && entry->len > 0


[1]:https://github.com/Distrotech/cdrkit/blob/distrortech-cdrkit/genisoimage/diag/isoinfo.c#L373
[2]:https://github.com/geneC/syslinux/blob/master/core/fs/iso9660/susp_rr.c#L145

On 2022/11/24 23:16, Thomas Schmitt wrote:
> Hi,
> 
> (Again i Cc t.feng in the hope that the review is not finished yet. :))
> 
> Daniel Kiper wrote:
>> I am not an ISO format expert but your thinking LGTM.
> 
> So you agree that "3" is really the right number if any remaining bytes
> fewer than 4 shall be ignored ?
> (I don't trust myself, although i made an example with finger counting.)
> 
> 
>> could you send a patch fixing this issue?
> 
> This should be possible. But how to test ?
> 
> Normal ISOs made with GNU/Linux will cause (entry == sua + sua_size) at
> the end of the SUSP data. So provoking the problem and checking whether
> it is solved will need a hacked ISO.
> I will think about creating such an ISO by help of xorriso and dd.
> 
> 
> While exploring the SUSP/RRIP entry types which are interpreted by GRUB,
> i got to more credulence towards the ISO producer.
> E.g. in grub-core/fs/iso9660.c line 404 ff.
> 
>       /* The 2nd data byte stored how many bytes are skipped every time
> 	 to get to the SUA (System Usage Area).  */
>       data->susp_skip = entry->data[2];
> 
> This is a memory fault if (sua_size < 7). I see no check between
>   sua = grub_malloc (sua_size);
> and the read access to entry->data[2].
> 
> Another example:
> grub_iso9660_susp_iterate() calls its parameter hook() without checking
> that the alleged entry size is within the range of sua_size. The hook()
> function does not get sua_size to check on its own.
> 
> In general:
> How mistrusting should GRUB be towards the bytes in the filesystem ?
> 
> 
> Have a nice day :)
> 
> Thomas
> 
> .
>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-29  9:32       ` Fengtao (fengtao, Euler)
@ 2022-11-29 14:26         ` Daniel Kiper
  2022-11-29 19:12           ` Thomas Schmitt
  2022-11-29 18:47         ` Thomas Schmitt
  1 sibling, 1 reply; 9+ messages in thread
From: Daniel Kiper @ 2022-11-29 14:26 UTC (permalink / raw)
  To: Thomas Schmitt, fengtao40; +Cc: grub-devel, yanan

On Tue, Nov 29, 2022 at 05:32:56PM +0800, Fengtao (fengtao, Euler) via Grub-devel wrote:
> Hi, Thomas
> Sorry for the delay, I am also not familiar with ISO format.
> But, i have check the cdrkit src-code[1] and syslinux src-code[2]
>
> I think:
> 	(char *) entry < (char *) sua + sua_size - 3 && entry->len > 0
> is ok, or:
> 	(char *) entry <= (char *) sua + sua_size - 4 && entry->len > 0
>
> [1]:https://github.com/Distrotech/cdrkit/blob/distrortech-cdrkit/genisoimage/diag/isoinfo.c#L373
> [2]:https://github.com/geneC/syslinux/blob/master/core/fs/iso9660/susp_rr.c#L145

I think you are right...

> On 2022/11/24 23:16, Thomas Schmitt wrote:
> > Hi,
> >
> > (Again i Cc t.feng in the hope that the review is not finished yet. :))
> >
> > Daniel Kiper wrote:
> >> I am not an ISO format expert but your thinking LGTM.
> >
> > So you agree that "3" is really the right number if any remaining bytes
> > fewer than 4 shall be ignored ?
> > (I don't trust myself, although i made an example with finger counting.)
> >
> >
> >> could you send a patch fixing this issue?
> >
> > This should be possible. But how to test ?
> >
> > Normal ISOs made with GNU/Linux will cause (entry == sua + sua_size) at
> > the end of the SUSP data. So provoking the problem and checking whether
> > it is solved will need a hacked ISO.
> > I will think about creating such an ISO by help of xorriso and dd.

Yeah, that would be perfect...

> > While exploring the SUSP/RRIP entry types which are interpreted by GRUB,
> > i got to more credulence towards the ISO producer.
> > E.g. in grub-core/fs/iso9660.c line 404 ff.
> >
> >       /* The 2nd data byte stored how many bytes are skipped every time
> > 	 to get to the SUA (System Usage Area).  */
> >       data->susp_skip = entry->data[2];
> >
> > This is a memory fault if (sua_size < 7). I see no check between
> >   sua = grub_malloc (sua_size);
> > and the read access to entry->data[2].
> >
> > Another example:
> > grub_iso9660_susp_iterate() calls its parameter hook() without checking
> > that the alleged entry size is within the range of sua_size. The hook()
> > function does not get sua_size to check on its own.

Huh! Could you fix these issues too?

> > In general:
> > How mistrusting should GRUB be towards the bytes in the filesystem ?

I think as little as possible. Especially if incorrect values may lead
to OOB writes...

Daniel


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-29  9:32       ` Fengtao (fengtao, Euler)
  2022-11-29 14:26         ` Daniel Kiper
@ 2022-11-29 18:47         ` Thomas Schmitt
  2022-12-12 14:32           ` Daniel Kiper
  1 sibling, 1 reply; 9+ messages in thread
From: Thomas Schmitt @ 2022-11-29 18:47 UTC (permalink / raw)
  To: grub-devel; +Cc: fengtao40, dkiper, yanan

Hi,

Fengtao wrote:
> I think:
>         (char *) entry < (char *) sua + sua_size - 3 && entry->len > 0
> is ok, or:
>         (char *) entry <= (char *) sua + sua_size - 4 && entry->len > 0

"4" would be overdone. There are SUSP and RRIP entries of length 4,
which would be ignored if appearing at the end of the SUSP controlled area.


> I am also not familiar with ISO format.

I seem to be the last active programmer on that topic.

As stated on 24 Nov, i see other potential memory faults in the code of
grub-core/fs/iso9660.c if the ISO image contains incorrect SUSP entries.

---------------------------------------------------------------------------

I began to hack an ISO image so that it shows non-SUSP data after the
SUSP data. (See below.)

But now i am having noob problems with grub-fstest.

I pulled the source from git://git.savannah.gnu.org/grub on Debian 11 and
built it as prescribed in INSTALL.
Nevertheless grub-fstest does not show a memory fault with:

  valgrind ./grub-fstest /dvdbuffer/grub_test_non_susp.iso ls /

gdb says that the execution enters grub_iso9660_susp_iterate()
  Breakpoint 1, 0x000055555557dde4 in grub_iso9660_susp_iterate ()
but gives no further information, because
  (No debugging symbols found in ./grub-fstest)

Next i tried to insert visible messages into grub_iso9660_susp_iterate():
  grub_error (GRUB_ERR_BAD_NUMBER, "grub_iso9660_susp_iterate: called");
  ...
  grub_error (GRUB_ERR_BAD_NUMBER, "grub_iso9660_susp_iterate: before loop");
  ...
    grub_error (GRUB_ERR_BAD_NUMBER,
                "grub_iso9660_susp_iterate: sua + sua_size - entry = %ld",
                (long int) ((char *) sua + sua_size - (char *) entry));
I do not see any of them when running with above arguments.

So how can i make grub-core/fs/iso9660.c debuggable or let it emit visible
messages ?

---------------------------------------------------------------------------
The test ISO is made by these commands in bash:

  # Create an ISO with a playground of SUSP data.
  echo dummy >dummy_file
  test -e grub_test_non_susp.iso && rm grub_test_non_susp.iso
  xorriso \
     -xattr on \
     -outdev grub_test_non_susp.iso \
     -map dummy_file /dummy_file \
     -setfattr user.x y /dummy_file -- \
     -padding 0

  # Search for the AL entry of length 0x0c which holds attribute user.x.
  # (AL is the entry type of my invention AAIP. It gets ignored by all
  #  readers except xorriso. So it is a good playground for manipulations.)
  # (There is also another AL entry of size 0x10 in the CE area of the root
  #  directory.)
  al=$(grep -a -o -b 'AL'$'\x0c'$'\x01' grub_test_non_susp.iso | \
       sed -e 's/:/ /' | awk '{print $1}')

  # Replace length field value 0x0c by 0x0a.
  # This leaves the last 2 bytes of the AL entry as trailing non-SUSP data
  # in the System Use field of the directory entry.
  al_length_offset=$(expr $al + 2)
  echo $'\x0a' | \
    dd of=grub_test_non_susp.iso \
       bs=1 count=1 seek="$al_length_offset" conv=notrunc

Inspection by a hex dumper shows that the AL entry indeed announces the
desired (short) length of 10.

---------------------------------------------------------------------------

I also learned by doing and then by reading specs that a padding byte after
the System Use data is present if needed to get an even number of bytes
as size of the directory record.

This could explain the existing "- 1" in GRUB's code.

Above ISO is supposed to show 3 non-SUSP bytes at the end of the System Use
field: 2 from my dd manipulation, 1 as regular padding.


Have a nice day :)

Thomas



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-29 14:26         ` Daniel Kiper
@ 2022-11-29 19:12           ` Thomas Schmitt
  0 siblings, 0 replies; 9+ messages in thread
From: Thomas Schmitt @ 2022-11-29 19:12 UTC (permalink / raw)
  To: grub-devel; +Cc: fengtao40, dkiper

Hi,

i wrote:
> > > I will think about creating such an ISO by help of xorriso and dd.

Daniel Kiper wrote:
> Yeah, that would be perfect...

I believe to have created one. But grub-fstest does not produce a memory
fault. See my mail
  Date: Tue, 29 Nov 2022 19:47:22 +0100
  Message-Id: <50363882005823433@scdbackup.webframe.org>
for the recipe to create that ISO.

I riddle:

- Would valgrind detect out-of-bounds reading in GRUB code ?
  (Or does the code under grub-fstest allocate a large memory chunk on
   which the memory management of GRUB operates ?)

- Is there a way to build the involved code for use under gdb ?

- How can i insert debug messages into grub-core/fs/iso9660.c ?


> > > [more opportunities to let the code derail]

> Huh! Could you fix these issues too?

I will try. But first i need to master grub-fstest or some other testbed
so that i can verify my theoretical considerations.

(The "- 1" problem is obvious from C code considerations. But the number
 to replace the "1" is not so obvious and in general we should not fix
 what is not broken.)


> > > In general:
> > > How mistrusting should GRUB be towards the bytes in the filesystem ?

> I think as little as possible. Especially if incorrect values may lead
> to OOB writes...

It is about out-of-bounds reads.

But i don't understand well the combination of your two sentences:
GRUB shall be credulent, especially if bad writes were involved ?
I would think that this is to be avoided most.

So please explain the philosopy a bit more verbous for an old programmer
or point me to examples.
(I would look into the other fs drivers if i would understand filesystems
 other than ISO 9660.)


Have a nice day :)

Thomas



^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Possible memory fault in fs/iso9660 (correction)
  2022-11-29 18:47         ` Thomas Schmitt
@ 2022-12-12 14:32           ` Daniel Kiper
  0 siblings, 0 replies; 9+ messages in thread
From: Daniel Kiper @ 2022-12-12 14:32 UTC (permalink / raw)
  To: Thomas Schmitt; +Cc: grub-devel, fengtao40, yanan

Hi,

Sorry for top posting...

I have just realized colleague of mine is doing some work in the ISO 9660
code including part which we are discussing here. I asked her to post the
patches on the grub-devel. You can expect them soon. Please take a look
at them and comment/review.

Daniel

On Tue, Nov 29, 2022 at 07:47:22PM +0100, Thomas Schmitt wrote:
> Hi,
>
> Fengtao wrote:
> > I think:
> >         (char *) entry < (char *) sua + sua_size - 3 && entry->len > 0
> > is ok, or:
> >         (char *) entry <= (char *) sua + sua_size - 4 && entry->len > 0
>
> "4" would be overdone. There are SUSP and RRIP entries of length 4,
> which would be ignored if appearing at the end of the SUSP controlled area.
>
>
> > I am also not familiar with ISO format.
>
> I seem to be the last active programmer on that topic.
>
> As stated on 24 Nov, i see other potential memory faults in the code of
> grub-core/fs/iso9660.c if the ISO image contains incorrect SUSP entries.
>
> ---------------------------------------------------------------------------
>
> I began to hack an ISO image so that it shows non-SUSP data after the
> SUSP data. (See below.)
>
> But now i am having noob problems with grub-fstest.
>
> I pulled the source from git://git.savannah.gnu.org/grub on Debian 11 and
> built it as prescribed in INSTALL.
> Nevertheless grub-fstest does not show a memory fault with:
>
>   valgrind ./grub-fstest /dvdbuffer/grub_test_non_susp.iso ls /
>
> gdb says that the execution enters grub_iso9660_susp_iterate()
>   Breakpoint 1, 0x000055555557dde4 in grub_iso9660_susp_iterate ()
> but gives no further information, because
>   (No debugging symbols found in ./grub-fstest)
>
> Next i tried to insert visible messages into grub_iso9660_susp_iterate():
>   grub_error (GRUB_ERR_BAD_NUMBER, "grub_iso9660_susp_iterate: called");
>   ...
>   grub_error (GRUB_ERR_BAD_NUMBER, "grub_iso9660_susp_iterate: before loop");
>   ...
>     grub_error (GRUB_ERR_BAD_NUMBER,
>                 "grub_iso9660_susp_iterate: sua + sua_size - entry = %ld",
>                 (long int) ((char *) sua + sua_size - (char *) entry));
> I do not see any of them when running with above arguments.
>
> So how can i make grub-core/fs/iso9660.c debuggable or let it emit visible
> messages ?
>
> ---------------------------------------------------------------------------
> The test ISO is made by these commands in bash:
>
>   # Create an ISO with a playground of SUSP data.
>   echo dummy >dummy_file
>   test -e grub_test_non_susp.iso && rm grub_test_non_susp.iso
>   xorriso \
>      -xattr on \
>      -outdev grub_test_non_susp.iso \
>      -map dummy_file /dummy_file \
>      -setfattr user.x y /dummy_file -- \
>      -padding 0
>
>   # Search for the AL entry of length 0x0c which holds attribute user.x.
>   # (AL is the entry type of my invention AAIP. It gets ignored by all
>   #  readers except xorriso. So it is a good playground for manipulations.)
>   # (There is also another AL entry of size 0x10 in the CE area of the root
>   #  directory.)
>   al=$(grep -a -o -b 'AL'$'\x0c'$'\x01' grub_test_non_susp.iso | \
>        sed -e 's/:/ /' | awk '{print $1}')
>
>   # Replace length field value 0x0c by 0x0a.
>   # This leaves the last 2 bytes of the AL entry as trailing non-SUSP data
>   # in the System Use field of the directory entry.
>   al_length_offset=$(expr $al + 2)
>   echo $'\x0a' | \
>     dd of=grub_test_non_susp.iso \
>        bs=1 count=1 seek="$al_length_offset" conv=notrunc
>
> Inspection by a hex dumper shows that the AL entry indeed announces the
> desired (short) length of 10.
>
> ---------------------------------------------------------------------------
>
> I also learned by doing and then by reading specs that a padding byte after
> the System Use data is present if needed to get an even number of bytes
> as size of the directory record.
>
> This could explain the existing "- 1" in GRUB's code.
>
> Above ISO is supposed to show 3 non-SUSP bytes at the end of the System Use
> field: 2 from my dd manipulation, 1 as regular padding.
>
> Have a nice day :)
>
> Thomas


^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2022-12-12 14:38 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-19 12:38 Possible memory fault in fs/iso9660 Thomas Schmitt
2022-11-19 12:57 ` Possible memory fault in fs/iso9660 (correction) Thomas Schmitt
2022-11-24 13:17   ` Daniel Kiper
2022-11-24 15:16     ` Thomas Schmitt
2022-11-29  9:32       ` Fengtao (fengtao, Euler)
2022-11-29 14:26         ` Daniel Kiper
2022-11-29 19:12           ` Thomas Schmitt
2022-11-29 18:47         ` Thomas Schmitt
2022-12-12 14:32           ` Daniel Kiper

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.