There's something wrong in cdrom.c: cdrom_get_last_written() for instance
calls cdrom_get_disc_info() and cdrom_get_track_info() to get information
about tracks, but these functions don't ensure that all the
track_information or disc_information structure is filled:
/* (buflen was first set to 8 to get track_information_length field) */
if ((ret = cdo->generic_packet(cdi, &cgc)))
return ret;
The second test ensures that at least we won't overflow the structure, but
nothing ensures that all the structure will be filled.
And indeed, we have a drive here that won't fill it all: the returned
track_information_length field will be *less than*
sizeof(track_information) - sizeof(ti->track_information_length), so that
cdrom_get_last_written() reads values that weren't filled in! As a result,
we are sometimes unable to read some parts of CDROMs, depending on the
uninitialized state of the structure...
Here is a patch that adds filling checks: cdrom_get_disc_info() and
cdrom_get_track_info() return the actual filled length, and it's up to the
caller to check that this is enough for him to get the values it wants.
Note: adding something like a
#define spanof(TYPE, MEMBER) ((size_t) ((&((TYPE *)0)->MEMBER)+1))
definition just near that of offsetof() in include/linux/stddef.h would
make it more pretty, but still it won't help for bitfields :/
Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>