Applying Debians 12-zero-slot.dpatch by Karl Tomlinson
<karlt@karlt.net> to fix dosfsck zero slot crashes:
* Fixes crashes due to zero slot numbers causing a negative offset in
the call to copy_lfn_part in lfn_add_slot. On amd64 this results in
a SIGSEGV in copy_lfn_part. On x86 the result is heap corruption and
thus sometimes a SIGSEGV or double free abort later. (Closes:
#152550, #353198, #356377, #401798).
Signed-off-by: Daniel Baumann <mail@daniel-baumann.ch>
This commit is contained in:
parent
eec8585c73
commit
1b2c8ca3b4
@ -148,12 +148,15 @@ void lfn_reset( void )
|
||||
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
{
|
||||
LFN_ENT *lfn = (LFN_ENT *)de;
|
||||
int slot = lfn->id & LFN_ID_SLOTMASK;
|
||||
unsigned offset;
|
||||
|
||||
if (lfn_slot == 0) lfn_check_orphaned();
|
||||
|
||||
if (de->attr != VFAT_LN_ATTR)
|
||||
die("lfn_add_slot called with non-LFN directory entry");
|
||||
|
||||
if (lfn->id & LFN_ID_START) {
|
||||
if (lfn->id & LFN_ID_START && slot != 0) {
|
||||
if (lfn_slot != -1) {
|
||||
int can_clear = 0;
|
||||
/* There is already a LFN "in progess", so it is an error that a
|
||||
@ -165,7 +168,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
/* XXX: Should delay that until next LFN known (then can better
|
||||
* display the name) */
|
||||
printf( "A new long file name starts within an old one.\n" );
|
||||
if ((lfn->id & LFN_ID_SLOTMASK) == lfn_slot &&
|
||||
if (slot == lfn_slot &&
|
||||
lfn->alias_checksum == lfn_checksum) {
|
||||
char *part1 = CNV_THIS_PART(lfn);
|
||||
char *part2 = CNV_PARTS_SO_FAR();
|
||||
@ -197,13 +200,13 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
}
|
||||
}
|
||||
}
|
||||
lfn_slot = lfn->id & LFN_ID_SLOTMASK;
|
||||
lfn_slot = slot;
|
||||
lfn_checksum = lfn->alias_checksum;
|
||||
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
|
||||
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
|
||||
lfn_parts = 0;
|
||||
}
|
||||
else if (lfn_slot == -1) {
|
||||
else if (lfn_slot == -1 && slot != 0) {
|
||||
/* No LFN in progress, but slot found; start bit missing */
|
||||
/* Causes: 1) start bit got lost, 2) Previous slot with start bit got
|
||||
* lost */
|
||||
@ -217,8 +220,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
"3: Set start bit\n" );
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
if (interactive) {
|
||||
switch( get_key( "123", "?" )) {
|
||||
switch( interactive ? get_key( "123", "?" ) : '2') {
|
||||
case '1':
|
||||
if (!lfn_offsets)
|
||||
lfn_offsets = alloc( sizeof(loff_t) );
|
||||
@ -233,7 +235,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
lfn->id |= LFN_ID_START;
|
||||
fs_write( dir_offset+offsetof(LFN_ENT,id),
|
||||
sizeof(lfn->id), &lfn->id );
|
||||
lfn_slot = lfn->id & LFN_ID_SLOTMASK;
|
||||
lfn_slot = slot;
|
||||
lfn_checksum = lfn->alias_checksum;
|
||||
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
|
||||
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
|
||||
@ -241,8 +243,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) {
|
||||
else if (slot != lfn_slot) {
|
||||
/* wrong sequence number */
|
||||
/* Causes: 1) seq-no destroyed */
|
||||
/* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
|
||||
@ -251,8 +252,8 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
int can_fix = 0;
|
||||
printf( "Unexpected long filename sequence number "
|
||||
"(%d vs. expected %d).\n",
|
||||
(lfn->id & LFN_ID_SLOTMASK), lfn_slot );
|
||||
if (lfn->alias_checksum == lfn_checksum) {
|
||||
slot, lfn_slot );
|
||||
if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) {
|
||||
char *part1 = CNV_THIS_PART(lfn);
|
||||
char *part2 = CNV_PARTS_SO_FAR();
|
||||
printf( " It could be that just the number is wrong\n"
|
||||
@ -267,9 +268,12 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
printf( "3: Correct sequence number\n" );
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
if (interactive) {
|
||||
switch( get_key( can_fix ? "123" : "12", "?" )) {
|
||||
switch( interactive ? get_key( can_fix ? "123" : "12", "?" ) : '2') {
|
||||
case '1':
|
||||
if (!lfn_offsets) {
|
||||
lfn_offsets = alloc( sizeof(loff_t) );
|
||||
lfn_parts = 0;
|
||||
}
|
||||
lfn_offsets[lfn_parts++] = dir_offset;
|
||||
clear_lfn_slots( 0, lfn_parts-1 );
|
||||
lfn_reset();
|
||||
@ -284,7 +288,6 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lfn->alias_checksum != lfn_checksum) {
|
||||
/* checksum mismatch */
|
||||
@ -390,8 +393,7 @@ char *lfn_get( DIR_ENT *de )
|
||||
"it to short name %s)\n", short_name );
|
||||
}
|
||||
else printf( " Not auto-correcting this.\n" );
|
||||
if (interactive) {
|
||||
switch( get_key( "123", "?" )) {
|
||||
switch( interactive ? get_key( "123", "?" ) : '2') {
|
||||
case '1':
|
||||
clear_lfn_slots( 0, lfn_parts-1 );
|
||||
lfn_reset();
|
||||
@ -410,7 +412,6 @@ char *lfn_get( DIR_ENT *de )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (sum = 0, i = 0; i < 11; i++)
|
||||
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i];
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user