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 )
|
void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
||||||
{
|
{
|
||||||
LFN_ENT *lfn = (LFN_ENT *)de;
|
LFN_ENT *lfn = (LFN_ENT *)de;
|
||||||
|
int slot = lfn->id & LFN_ID_SLOTMASK;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
|
|
||||||
|
if (lfn_slot == 0) lfn_check_orphaned();
|
||||||
|
|
||||||
if (de->attr != VFAT_LN_ATTR)
|
if (de->attr != VFAT_LN_ATTR)
|
||||||
die("lfn_add_slot called with non-LFN directory entry");
|
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) {
|
if (lfn_slot != -1) {
|
||||||
int can_clear = 0;
|
int can_clear = 0;
|
||||||
/* There is already a LFN "in progess", so it is an error that a
|
/* 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
|
/* XXX: Should delay that until next LFN known (then can better
|
||||||
* display the name) */
|
* display the name) */
|
||||||
printf( "A new long file name starts within an old one.\n" );
|
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) {
|
lfn->alias_checksum == lfn_checksum) {
|
||||||
char *part1 = CNV_THIS_PART(lfn);
|
char *part1 = CNV_THIS_PART(lfn);
|
||||||
char *part2 = CNV_PARTS_SO_FAR();
|
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_checksum = lfn->alias_checksum;
|
||||||
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
|
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
|
||||||
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
|
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
|
||||||
lfn_parts = 0;
|
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 */
|
/* No LFN in progress, but slot found; start bit missing */
|
||||||
/* Causes: 1) start bit got lost, 2) Previous slot with start bit got
|
/* Causes: 1) start bit got lost, 2) Previous slot with start bit got
|
||||||
* lost */
|
* lost */
|
||||||
@ -217,8 +220,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
|||||||
"3: Set start bit\n" );
|
"3: Set start bit\n" );
|
||||||
}
|
}
|
||||||
else printf( " Not auto-correcting this.\n" );
|
else printf( " Not auto-correcting this.\n" );
|
||||||
if (interactive) {
|
switch( interactive ? get_key( "123", "?" ) : '2') {
|
||||||
switch( get_key( "123", "?" )) {
|
|
||||||
case '1':
|
case '1':
|
||||||
if (!lfn_offsets)
|
if (!lfn_offsets)
|
||||||
lfn_offsets = alloc( sizeof(loff_t) );
|
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;
|
lfn->id |= LFN_ID_START;
|
||||||
fs_write( dir_offset+offsetof(LFN_ENT,id),
|
fs_write( dir_offset+offsetof(LFN_ENT,id),
|
||||||
sizeof(lfn->id), &lfn->id );
|
sizeof(lfn->id), &lfn->id );
|
||||||
lfn_slot = lfn->id & LFN_ID_SLOTMASK;
|
lfn_slot = slot;
|
||||||
lfn_checksum = lfn->alias_checksum;
|
lfn_checksum = lfn->alias_checksum;
|
||||||
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
|
lfn_unicode = alloc( (lfn_slot*CHARS_PER_LFN+1)*2 );
|
||||||
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
|
lfn_offsets = alloc( lfn_slot*sizeof(loff_t) );
|
||||||
@ -241,8 +243,7 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if (slot != lfn_slot) {
|
||||||
else if ((lfn->id & LFN_ID_SLOTMASK) != lfn_slot) {
|
|
||||||
/* wrong sequence number */
|
/* wrong sequence number */
|
||||||
/* Causes: 1) seq-no destroyed */
|
/* Causes: 1) seq-no destroyed */
|
||||||
/* Fixes: 1) delete LFN, 2) fix number (maybe only if following parts
|
/* 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;
|
int can_fix = 0;
|
||||||
printf( "Unexpected long filename sequence number "
|
printf( "Unexpected long filename sequence number "
|
||||||
"(%d vs. expected %d).\n",
|
"(%d vs. expected %d).\n",
|
||||||
(lfn->id & LFN_ID_SLOTMASK), lfn_slot );
|
slot, lfn_slot );
|
||||||
if (lfn->alias_checksum == lfn_checksum) {
|
if (lfn->alias_checksum == lfn_checksum && lfn_slot > 0) {
|
||||||
char *part1 = CNV_THIS_PART(lfn);
|
char *part1 = CNV_THIS_PART(lfn);
|
||||||
char *part2 = CNV_PARTS_SO_FAR();
|
char *part2 = CNV_PARTS_SO_FAR();
|
||||||
printf( " It could be that just the number is wrong\n"
|
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" );
|
printf( "3: Correct sequence number\n" );
|
||||||
}
|
}
|
||||||
else printf( " Not auto-correcting this.\n" );
|
else printf( " Not auto-correcting this.\n" );
|
||||||
if (interactive) {
|
switch( interactive ? get_key( can_fix ? "123" : "12", "?" ) : '2') {
|
||||||
switch( get_key( can_fix ? "123" : "12", "?" )) {
|
|
||||||
case '1':
|
case '1':
|
||||||
|
if (!lfn_offsets) {
|
||||||
|
lfn_offsets = alloc( sizeof(loff_t) );
|
||||||
|
lfn_parts = 0;
|
||||||
|
}
|
||||||
lfn_offsets[lfn_parts++] = dir_offset;
|
lfn_offsets[lfn_parts++] = dir_offset;
|
||||||
clear_lfn_slots( 0, lfn_parts-1 );
|
clear_lfn_slots( 0, lfn_parts-1 );
|
||||||
lfn_reset();
|
lfn_reset();
|
||||||
@ -284,7 +288,6 @@ void lfn_add_slot( DIR_ENT *de, loff_t dir_offset )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (lfn->alias_checksum != lfn_checksum) {
|
if (lfn->alias_checksum != lfn_checksum) {
|
||||||
/* checksum mismatch */
|
/* checksum mismatch */
|
||||||
@ -390,8 +393,7 @@ char *lfn_get( DIR_ENT *de )
|
|||||||
"it to short name %s)\n", short_name );
|
"it to short name %s)\n", short_name );
|
||||||
}
|
}
|
||||||
else printf( " Not auto-correcting this.\n" );
|
else printf( " Not auto-correcting this.\n" );
|
||||||
if (interactive) {
|
switch( interactive ? get_key( "123", "?" ) : '2') {
|
||||||
switch( get_key( "123", "?" )) {
|
|
||||||
case '1':
|
case '1':
|
||||||
clear_lfn_slots( 0, lfn_parts-1 );
|
clear_lfn_slots( 0, lfn_parts-1 );
|
||||||
lfn_reset();
|
lfn_reset();
|
||||||
@ -410,7 +412,6 @@ char *lfn_get( DIR_ENT *de )
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
for (sum = 0, i = 0; i < 11; i++)
|
for (sum = 0, i = 0; i < 11; i++)
|
||||||
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i];
|
sum = (((sum&1) << 7) | ((sum&0xfe) >> 1)) + de->name[i];
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user