Skip to content

Commit c4e8c40

Browse files
committed
[prefix] Use CRC32 to verify each block prior to decompression
Signed-off-by: Michael Brown <mcb30@ipxe.org>
1 parent 05027a7 commit c4e8c40

File tree

3 files changed

+160
-45
lines changed

3 files changed

+160
-45
lines changed

src/arch/x86/prefix/libprefix.S

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ zero_bytes:
341341
* Returns:
342342
* %esi : next source physical address
343343
* %edi : next destination physical address
344+
* CF : as returned by memcpy()-like function
344345
* Corrupts:
345346
* None
346347
****************************************************************************
@@ -356,6 +357,7 @@ process_bytes:
356357
pushl %ebp
357358

358359
/* Construct GDT on stack (since .prefix may not be writable) */
360+
.equ GDT_LEN, 0x20
359361
.equ PM_DS, 0x18 /* Flat data segment */
360362
pushl $0x00cf9300
361363
pushl $0x0000ffff
@@ -369,7 +371,7 @@ process_bytes:
369371
pushw $0xffff
370372
pushl $0 /* Base and length */
371373
pushw %ss
372-
pushw $0x1f
374+
pushw $( GDT_LEN - 1 )
373375
movzwl %sp, %ebp
374376
shll $4, 0x02(%bp)
375377
addl %ebp, 0x02(%bp)
@@ -407,7 +409,9 @@ process_bytes:
407409

408410
/* Return to (flat) real mode */
409411
movl %cr0, %eax
412+
pushfw
410413
andb $0!CR0_PE, %al
414+
popfw
411415
movl %eax, %cr0
412416
lret
413417
2: /* lret will ljmp to here */
@@ -433,7 +437,7 @@ process_bytes:
433437

434438
/* Restore GDT */
435439
data32 lgdt -8(%bp)
436-
addw $( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
440+
leaw GDT_LEN(%bp), %sp
437441

438442
/* Restore registers and return */
439443
popl %ebp
@@ -461,6 +465,7 @@ process_bytes:
461465
call *%bx
462466

463467
/* Convert %ds:esi and %es:edi back to physical addresses */
468+
pushfw
464469
xorl %eax, %eax
465470
movw %ds, %ax
466471
shll $4, %eax
@@ -469,6 +474,7 @@ process_bytes:
469474
movw %es, %ax
470475
shll $4, %eax
471476
addl %eax, %edi
477+
popfw
472478

473479
/* Restore registers and return */
474480
popw %es
@@ -493,6 +499,7 @@ process_bytes:
493499
* Returns:
494500
* %esi : next source physical address (will be a multiple of 16)
495501
* %edi : next destination physical address (will be a multiple of 16)
502+
* CF set on failure
496503
* Corrupts:
497504
* none
498505
****************************************************************************
@@ -511,6 +518,7 @@ install_block:
511518
movw $copy_bytes, %bx
512519
#endif
513520
call process_bytes
521+
jc 99f
514522

515523
/* Zero .bss portion */
516524
negl %ecx
@@ -522,9 +530,9 @@ install_block:
522530
addl $0xf, %esi
523531
andl $~0xf, %esi
524532
addl $0xf, %edi
525-
andl $~0xf, %edi
533+
andl $~0xf, %edi /* Will also clear CF */
526534

527-
/* Restore registers and return */
535+
99: /* Restore registers and return */
528536
popw %bx
529537
popl %ecx
530538
ret
@@ -730,6 +738,7 @@ install_prealloc:
730738
movl $_text16_early_filesz, %ecx
731739
movl $_text16_early_memsz, %edx
732740
call install_block /* .text16.early */
741+
jc install_block_death
733742
popl %ecx /* Calculate offset to next block */
734743
subl %esi, %ecx
735744
negl %ecx
@@ -748,17 +757,8 @@ install_prealloc:
748757
pushw $access_highmem
749758
lret
750759
1: /* Die if we could not access high memory */
751-
jnc 3f
752-
movw $a20_death_message, %si
753-
xorw %di, %di
754-
call print_message
755-
2: jmp 2b
756-
.section ".prefix.data.a20_death_message", "aw", @progbits
757-
a20_death_message:
758-
.asciz "\nHigh memory inaccessible - cannot continue\n"
759-
.size a20_death_message, . - a20_death_message
760-
.previous
761-
3:
760+
jc access_highmem_death
761+
762762
#endif
763763

764764
/* Open payload (which may not yet be in memory) */
@@ -769,25 +769,7 @@ a20_death_message:
769769
pushw $open_payload
770770
lret
771771
1: /* Die if we could not access the payload */
772-
jnc 3f
773-
xorw %di, %di
774-
movl %esi, %eax
775-
call print_hex_dword
776-
call print_space
777-
movl %ecx, %eax
778-
call print_hex_dword
779-
movw $payload_death_message, %si
780-
call print_message
781-
2: /* Halt system */
782-
cli
783-
hlt
784-
jmp 2b
785-
.section ".prefix.data.payload_death_message", "aw", @progbits
786-
payload_death_message:
787-
.asciz "\nPayload inaccessible - cannot continue\n"
788-
.size payload_death_message, . - payload_death_message
789-
.previous
790-
3:
772+
jc open_payload_death
791773

792774
/* Calculate physical address of payload (i.e. first source) */
793775
testl %esi, %esi
@@ -801,12 +783,14 @@ payload_death_message:
801783
movl $_text16_late_filesz, %ecx
802784
movl $_text16_late_memsz, %edx
803785
call install_block /* .text16.late */
786+
jc install_block_death
804787
progress " .data16\n"
805788
movzwl %bx, %edi
806789
shll $4, %edi
807790
movl $_data16_filesz, %ecx
808791
movl $_data16_filesz, %edx /* do not zero our temporary stack */
809792
call install_block /* .data16 */
793+
jc install_block_death
810794

811795
/* Set up %ds for access to .data16 */
812796
movw %bx, %ds
@@ -846,6 +830,7 @@ payload_death_message:
846830
movl $_textdata_filesz, %ecx
847831
movl $_textdata_memsz, %edx
848832
call install_block
833+
jc install_block_death
849834
popl %edi
850835

851836
#endif /* KEEP_IT_REAL */
@@ -960,6 +945,52 @@ close_payload:
960945
.size open_payload, . - open_payload
961946
.size close_payload, . - close_payload
962947

948+
/* Report installation failure */
949+
.section ".prefix.install_death", "ax", @progbits
950+
install_death:
951+
pushw %cs
952+
popw %ds
953+
xorw %di, %di
954+
call print_hex_dword
955+
call print_space
956+
movl %esi, %eax
957+
call print_hex_dword
958+
call print_space
959+
movl %ecx, %eax
960+
call print_hex_dword
961+
movw $install_death_message, %si
962+
call print_message
963+
2: /* Halt system */
964+
cli
965+
hlt
966+
jmp 2b
967+
.size install_death, . - install_death
968+
.section ".prefix.data.install_death_message", "aw", @progbits
969+
install_death_message:
970+
.asciz "\nInstallation failed - cannot continue\n"
971+
.size install_death_message, . - install_death_message
972+
973+
/* Report failure to access high memory */
974+
.section ".prefix.install_block_death", "ax", @progbits
975+
install_block_death:
976+
movl $0x1b101b10, %eax
977+
jmp install_death
978+
.size install_block_death, . - install_block_death
979+
980+
/* Report failure to access high memory */
981+
.section ".prefix.access_highmem_death", "ax", @progbits
982+
access_highmem_death:
983+
movl $0x0a200a20, %eax
984+
jmp install_death
985+
.size access_highmem_death, . - access_highmem_death
986+
987+
/* Report failure to open payload */
988+
.section ".prefix.open_payload_death", "ax", @progbits
989+
open_payload_death:
990+
xorl %eax, %eax
991+
jmp install_death
992+
.size open_payload_death, . - open_payload_death
993+
963994
/****************************************************************************
964995
* uninstall
965996
*

src/arch/x86/prefix/unlzma.S

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
5858
.code32
5959
#endif /* CODE16 */
6060

61+
#define CRCPOLY 0xedb88320
62+
#define CRCSEED 0xffffffff
63+
6164
/****************************************************************************
6265
* Debugging
6366
****************************************************************************
@@ -862,6 +865,44 @@ bcj_filter:
862865
ret
863866
.size bcj_filter, . - bcj_filter
864867

868+
/****************************************************************************
869+
* Verify CRC32
870+
*
871+
* Parameters:
872+
* %ds:%esi : Start of compressed input data
873+
* %edx : Length of compressed input data (including CRC)
874+
* Returns:
875+
* CF clear if CRC32 is zero
876+
* All other registers are preserved
877+
* Corrupts:
878+
* %eax
879+
* %ebx
880+
* %ecx
881+
* %edx
882+
* %esi
883+
****************************************************************************
884+
*/
885+
verify_crc32:
886+
/* Calculate CRC */
887+
addl %esi, %edx
888+
movl $CRCSEED, %ebx
889+
1: ADDR32 lodsb
890+
xorb %al, %bl
891+
movw $8, %cx
892+
2: rcrl %ebx
893+
jnc 3f
894+
xorl $CRCPOLY, %ebx
895+
3: ADDR16 loop 2b
896+
cmpl %esi, %edx
897+
jne 1b
898+
/* Set CF if result is nonzero */
899+
testl %ebx, %ebx
900+
jz 1f
901+
stc
902+
1: /* Return */
903+
ret
904+
.size verify_crc32, . - verify_crc32
905+
865906
/****************************************************************************
866907
* decompress (real-mode or 16/32-bit protected-mode near call)
867908
*
@@ -873,6 +914,7 @@ bcj_filter:
873914
* Returns:
874915
* %ds:%esi - End of compressed input data
875916
* %es:%edi - End of decompressed output data
917+
* CF set if CRC32 was incorrect
876918
* All other registers are preserved
877919
*
878920
* NOTE: It would be possible to build a smaller version of the
@@ -888,6 +930,13 @@ decompress:
888930
pushl %ecx
889931
pushl %edx
890932
pushl %ebp
933+
/* Verify CRC32 */
934+
ADDR32 lodsl
935+
movl %eax, %edx
936+
pushl %esi
937+
call verify_crc32
938+
popl %esi
939+
jc 99f
891940
/* Allocate parameter block */
892941
subl $sizeof__lzma_dec, %esp
893942
movl %esp, %ebp
@@ -928,8 +977,11 @@ decompress:
928977
movl out_start(%ebp), %esi
929978
call bcj_filter
930979
popl %esi
931-
/* Restore registers and return */
980+
/* Skip CRC */
981+
ADDR32 lodsl
982+
/* Free parameter block (and clear CF) */
932983
addl $sizeof__lzma_dec, %esp
984+
99: /* Restore registers and return */
933985
popl %ebp
934986
popl %edx
935987
popl %ecx

0 commit comments

Comments
 (0)