-
Samuel Thibault authored
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; cgc.buflen = be16_to_cpu(ti->track_information_length) + sizeof(ti->track_information_length); if (cgc.buflen > sizeof(track_information)) cgc.buflen = sizeof(track_information); cgc.cmd[8] = cgc.buflen; return cdo->generic_packet(cdi, &cgc); 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>
f0828420