• Samuel Thibault's avatar
    [PATCH] Subject: cdrom.c get_last_written fixup · f0828420
    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: default avatarAndrew Morton <akpm@osdl.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
    f0828420
cdrom.c 89.7 KB