* 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.