Browse Source

[prefix] Use CRC32 to verify each block prior to decompression

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 years ago
parent
commit
c4e8c40227
3 changed files with 160 additions and 45 deletions
  1. 65
    34
      src/arch/x86/prefix/libprefix.S
  2. 53
    1
      src/arch/x86/prefix/unlzma.S
  3. 42
    10
      src/util/zbin.c

+ 65
- 34
src/arch/x86/prefix/libprefix.S View File

341
  * Returns:
341
  * Returns:
342
  *   %esi : next source physical address
342
  *   %esi : next source physical address
343
  *   %edi : next destination physical address
343
  *   %edi : next destination physical address
344
+ *   CF : as returned by memcpy()-like function
344
  * Corrupts:
345
  * Corrupts:
345
  *   None
346
  *   None
346
  ****************************************************************************
347
  ****************************************************************************
356
 	pushl	%ebp
357
 	pushl	%ebp
357
 
358
 
358
 	/* Construct GDT on stack (since .prefix may not be writable) */
359
 	/* Construct GDT on stack (since .prefix may not be writable) */
360
+	.equ	GDT_LEN, 0x20
359
 	.equ	PM_DS, 0x18	/* Flat data segment */
361
 	.equ	PM_DS, 0x18	/* Flat data segment */
360
 	pushl	$0x00cf9300
362
 	pushl	$0x00cf9300
361
 	pushl	$0x0000ffff
363
 	pushl	$0x0000ffff
369
 	pushw	$0xffff
371
 	pushw	$0xffff
370
 	pushl	$0		/* Base and length */
372
 	pushl	$0		/* Base and length */
371
 	pushw	%ss
373
 	pushw	%ss
372
-	pushw	$0x1f
374
+	pushw	$( GDT_LEN - 1 )
373
 	movzwl	%sp, %ebp
375
 	movzwl	%sp, %ebp
374
 	shll	$4, 0x02(%bp)
376
 	shll	$4, 0x02(%bp)
375
 	addl	%ebp, 0x02(%bp)
377
 	addl	%ebp, 0x02(%bp)
407
 
409
 
408
 	/* Return to (flat) real mode */
410
 	/* Return to (flat) real mode */
409
 	movl	%cr0, %eax
411
 	movl	%cr0, %eax
412
+	pushfw
410
 	andb	$0!CR0_PE, %al
413
 	andb	$0!CR0_PE, %al
414
+	popfw
411
 	movl	%eax, %cr0
415
 	movl	%eax, %cr0
412
 	lret
416
 	lret
413
 2:	/* lret will ljmp to here */
417
 2:	/* lret will ljmp to here */
433
 
437
 
434
 	/* Restore GDT */
438
 	/* Restore GDT */
435
 	data32 lgdt -8(%bp)
439
 	data32 lgdt -8(%bp)
436
-	addw	$( 8 /* saved GDT */ + ( PM_DS + 8 ) /* GDT on stack */ ), %sp
440
+	leaw	GDT_LEN(%bp), %sp
437
 
441
 
438
 	/* Restore registers and return */
442
 	/* Restore registers and return */
439
 	popl	%ebp
443
 	popl	%ebp
461
 	call	*%bx
465
 	call	*%bx
462
 
466
 
463
 	/* Convert %ds:esi and %es:edi back to physical addresses */
467
 	/* Convert %ds:esi and %es:edi back to physical addresses */
468
+	pushfw
464
 	xorl	%eax, %eax
469
 	xorl	%eax, %eax
465
 	movw    %ds, %ax
470
 	movw    %ds, %ax
466
 	shll	$4, %eax
471
 	shll	$4, %eax
469
 	movw    %es, %ax
474
 	movw    %es, %ax
470
 	shll	$4, %eax
475
 	shll	$4, %eax
471
 	addl	%eax, %edi
476
 	addl	%eax, %edi
477
+	popfw
472
 
478
 
473
 	/* Restore registers and return */
479
 	/* Restore registers and return */
474
 	popw	%es
480
 	popw	%es
493
  * Returns:
499
  * Returns:
494
  *   %esi : next source physical address (will be a multiple of 16)
500
  *   %esi : next source physical address (will be a multiple of 16)
495
  *   %edi : next destination physical address (will be a multiple of 16)
501
  *   %edi : next destination physical address (will be a multiple of 16)
502
+ *   CF set on failure
496
  * Corrupts:
503
  * Corrupts:
497
  *   none
504
  *   none
498
  ****************************************************************************
505
  ****************************************************************************
511
 	movw	$copy_bytes, %bx
518
 	movw	$copy_bytes, %bx
512
 #endif
519
 #endif
513
 	call	process_bytes
520
 	call	process_bytes
521
+	jc	99f
514
 
522
 
515
 	/* Zero .bss portion */
523
 	/* Zero .bss portion */
516
 	negl	%ecx
524
 	negl	%ecx
522
 	addl	$0xf, %esi
530
 	addl	$0xf, %esi
523
 	andl	$~0xf, %esi
531
 	andl	$~0xf, %esi
524
 	addl	$0xf, %edi
532
 	addl	$0xf, %edi
525
-	andl	$~0xf, %edi
533
+	andl	$~0xf, %edi /* Will also clear CF */
526
 
534
 
527
-	/* Restore registers and return */
535
+99:	/* Restore registers and return */
528
 	popw	%bx
536
 	popw	%bx
529
 	popl	%ecx
537
 	popl	%ecx
530
 	ret
538
 	ret
730
 	movl	$_text16_early_filesz, %ecx
738
 	movl	$_text16_early_filesz, %ecx
731
 	movl	$_text16_early_memsz, %edx
739
 	movl	$_text16_early_memsz, %edx
732
 	call	install_block		/* .text16.early */
740
 	call	install_block		/* .text16.early */
741
+	jc	install_block_death
733
 	popl	%ecx			/* Calculate offset to next block */
742
 	popl	%ecx			/* Calculate offset to next block */
734
 	subl	%esi, %ecx
743
 	subl	%esi, %ecx
735
 	negl	%ecx
744
 	negl	%ecx
748
 	pushw	$access_highmem
757
 	pushw	$access_highmem
749
 	lret
758
 	lret
750
 1:	/* Die if we could not access high memory */
759
 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
+
762
 #endif
762
 #endif
763
 
763
 
764
 	/* Open payload (which may not yet be in memory) */
764
 	/* Open payload (which may not yet be in memory) */
769
 	pushw	$open_payload
769
 	pushw	$open_payload
770
 	lret
770
 	lret
771
 1:	/* Die if we could not access the payload */
771
 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
791
 
773
 
792
 	/* Calculate physical address of payload (i.e. first source) */
774
 	/* Calculate physical address of payload (i.e. first source) */
793
 	testl	%esi, %esi
775
 	testl	%esi, %esi
801
 	movl	$_text16_late_filesz, %ecx
783
 	movl	$_text16_late_filesz, %ecx
802
 	movl	$_text16_late_memsz, %edx
784
 	movl	$_text16_late_memsz, %edx
803
 	call	install_block		/* .text16.late */
785
 	call	install_block		/* .text16.late */
786
+	jc	install_block_death
804
 	progress "  .data16\n"
787
 	progress "  .data16\n"
805
 	movzwl	%bx, %edi
788
 	movzwl	%bx, %edi
806
 	shll	$4, %edi
789
 	shll	$4, %edi
807
 	movl	$_data16_filesz, %ecx
790
 	movl	$_data16_filesz, %ecx
808
 	movl	$_data16_filesz, %edx	/* do not zero our temporary stack */
791
 	movl	$_data16_filesz, %edx	/* do not zero our temporary stack */
809
 	call	install_block		/* .data16 */
792
 	call	install_block		/* .data16 */
793
+	jc	install_block_death
810
 
794
 
811
 	/* Set up %ds for access to .data16 */
795
 	/* Set up %ds for access to .data16 */
812
 	movw	%bx, %ds
796
 	movw	%bx, %ds
846
 	movl	$_textdata_filesz, %ecx
830
 	movl	$_textdata_filesz, %ecx
847
 	movl	$_textdata_memsz, %edx
831
 	movl	$_textdata_memsz, %edx
848
 	call	install_block
832
 	call	install_block
833
+	jc	install_block_death
849
 	popl	%edi
834
 	popl	%edi
850
 
835
 
851
 #endif /* KEEP_IT_REAL */
836
 #endif /* KEEP_IT_REAL */
960
 	.size	open_payload, . - open_payload
945
 	.size	open_payload, . - open_payload
961
 	.size	close_payload, . - close_payload
946
 	.size	close_payload, . - close_payload
962
 
947
 
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
+
963
 /****************************************************************************
994
 /****************************************************************************
964
  * uninstall
995
  * uninstall
965
  *
996
  *

+ 53
- 1
src/arch/x86/prefix/unlzma.S View File

58
 	.code32
58
 	.code32
59
 #endif /* CODE16 */
59
 #endif /* CODE16 */
60
 
60
 
61
+#define CRCPOLY 0xedb88320
62
+#define CRCSEED 0xffffffff
63
+
61
 /****************************************************************************
64
 /****************************************************************************
62
  * Debugging
65
  * Debugging
63
  ****************************************************************************
66
  ****************************************************************************
862
 	ret
865
 	ret
863
 	.size	bcj_filter, . - bcj_filter
866
 	.size	bcj_filter, . - bcj_filter
864
 
867
 
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
+
865
 /****************************************************************************
906
 /****************************************************************************
866
  * decompress (real-mode or 16/32-bit protected-mode near call)
907
  * decompress (real-mode or 16/32-bit protected-mode near call)
867
  *
908
  *
873
  * Returns:
914
  * Returns:
874
  *   %ds:%esi - End of compressed input data
915
  *   %ds:%esi - End of compressed input data
875
  *   %es:%edi - End of decompressed output data
916
  *   %es:%edi - End of decompressed output data
917
+ *   CF set if CRC32 was incorrect
876
  *   All other registers are preserved
918
  *   All other registers are preserved
877
  *
919
  *
878
  * NOTE: It would be possible to build a smaller version of the
920
  * NOTE: It would be possible to build a smaller version of the
888
 	pushl	%ecx
930
 	pushl	%ecx
889
 	pushl	%edx
931
 	pushl	%edx
890
 	pushl	%ebp
932
 	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
891
 	/* Allocate parameter block */
940
 	/* Allocate parameter block */
892
 	subl	$sizeof__lzma_dec, %esp
941
 	subl	$sizeof__lzma_dec, %esp
893
 	movl	%esp, %ebp
942
 	movl	%esp, %ebp
928
 	movl	out_start(%ebp), %esi
977
 	movl	out_start(%ebp), %esi
929
 	call	bcj_filter
978
 	call	bcj_filter
930
 	popl	%esi
979
 	popl	%esi
931
-	/* Restore registers and return */
980
+	/* Skip CRC */
981
+	ADDR32 lodsl
982
+	/* Free parameter block (and clear CF) */
932
 	addl	$sizeof__lzma_dec, %esp
983
 	addl	$sizeof__lzma_dec, %esp
984
+99:	/* Restore registers and return */
933
 	popl	%ebp
985
 	popl	%ebp
934
 	popl	%edx
986
 	popl	%edx
935
 	popl	%ecx
987
 	popl	%ecx

+ 42
- 10
src/util/zbin.c View File

144
 
144
 
145
 static int alloc_output_file ( size_t max_len, struct output_file *output ) {
145
 static int alloc_output_file ( size_t max_len, struct output_file *output ) {
146
 	output->len = 0;
146
 	output->len = 0;
147
+	output->hdr_len = 0;
147
 	output->max_len = ( max_len );
148
 	output->max_len = ( max_len );
148
 	output->buf = malloc ( max_len );
149
 	output->buf = malloc ( max_len );
149
 	if ( ! output->buf ) {
150
 	if ( ! output->buf ) {
241
 	};
242
 	};
242
 }
243
 }
243
 
244
 
245
+#define CRCPOLY 0xedb88320
246
+#define CRCSEED 0xffffffff
247
+
248
+static uint32_t crc32_le ( uint32_t crc, const void *data, size_t len ) {
249
+	const uint8_t *src = data;
250
+	uint32_t mult;
251
+	unsigned int i;
252
+
253
+	while ( len-- ) {
254
+		crc ^= *(src++);
255
+		for ( i = 0 ; i < 8 ; i++ ) {
256
+			mult = ( ( crc & 1 ) ? CRCPOLY : 0 );
257
+			crc = ( ( crc >> 1 ) ^ mult );
258
+		}
259
+	}
260
+	return crc;
261
+}
262
+
244
 static int process_zinfo_pack ( struct input_file *input,
263
 static int process_zinfo_pack ( struct input_file *input,
245
 				struct output_file *output,
264
 				struct output_file *output,
246
 				union zinfo_record *zinfo ) {
265
 				union zinfo_record *zinfo ) {
247
 	struct zinfo_pack *pack = &zinfo->pack;
266
 	struct zinfo_pack *pack = &zinfo->pack;
248
 	size_t offset = pack->offset;
267
 	size_t offset = pack->offset;
249
 	size_t len = pack->len;
268
 	size_t len = pack->len;
269
+	size_t start_len;
250
 	size_t packed_len = 0;
270
 	size_t packed_len = 0;
251
-	size_t remaining = ( output->max_len - output->len );
271
+	size_t remaining;
252
 	lzma_options_lzma options;
272
 	lzma_options_lzma options;
253
 	const lzma_filter filters[] = {
273
 	const lzma_filter filters[] = {
254
 		{ .id = LZMA_FILTER_LZMA1, .options = &options },
274
 		{ .id = LZMA_FILTER_LZMA1, .options = &options },
255
 		{ .id = LZMA_VLI_UNKNOWN }
275
 		{ .id = LZMA_VLI_UNKNOWN }
256
 	};
276
 	};
277
+	void *packed;
278
+	uint32_t *len32;
279
+	uint32_t *crc32;
257
 
280
 
258
 	if ( ( offset + len ) > input->len ) {
281
 	if ( ( offset + len ) > input->len ) {
259
 		fprintf ( stderr, "Input buffer overrun on pack\n" );
282
 		fprintf ( stderr, "Input buffer overrun on pack\n" );
261
 	}
284
 	}
262
 
285
 
263
 	output->len = align ( output->len, pack->align );
286
 	output->len = align ( output->len, pack->align );
287
+	start_len = output->len;
288
+	len32 = ( output->buf + output->len );
289
+	output->len += sizeof ( *len32 );
264
 	if ( output->len > output->max_len ) {
290
 	if ( output->len > output->max_len ) {
265
 		fprintf ( stderr, "Output buffer overrun on pack\n" );
291
 		fprintf ( stderr, "Output buffer overrun on pack\n" );
266
 		return -1;
292
 		return -1;
268
 
294
 
269
 	bcj_filter ( ( input->buf + offset ), len );
295
 	bcj_filter ( ( input->buf + offset ), len );
270
 
296
 
297
+	packed = ( output->buf + output->len );
298
+	remaining = ( output->max_len - output->len );
271
 	lzma_lzma_preset ( &options, LZMA_PRESET );
299
 	lzma_lzma_preset ( &options, LZMA_PRESET );
272
 	options.lc = LZMA_LC;
300
 	options.lc = LZMA_LC;
273
 	options.lp = LZMA_LP;
301
 	options.lp = LZMA_LP;
274
 	options.pb = LZMA_PB;
302
 	options.pb = LZMA_PB;
275
 	if ( lzma_raw_buffer_encode ( filters, NULL, ( input->buf + offset ),
303
 	if ( lzma_raw_buffer_encode ( filters, NULL, ( input->buf + offset ),
276
-				      len, ( output->buf + output->len ),
277
-				      &packed_len, remaining ) != LZMA_OK ) {
304
+				      len, packed, &packed_len,
305
+				      remaining ) != LZMA_OK ) {
278
 		fprintf ( stderr, "Compression failure\n" );
306
 		fprintf ( stderr, "Compression failure\n" );
279
 		return -1;
307
 		return -1;
280
 	}
308
 	}
281
-
282
-	if ( DEBUG ) {
283
-		fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx)\n",
284
-			  offset, ( offset + len ), output->len,
285
-			  ( output->len + packed_len ) );
286
-	}
287
-
288
 	output->len += packed_len;
309
 	output->len += packed_len;
310
+
311
+	crc32 = ( output->buf + output->len );
312
+	output->len += sizeof ( *crc32 );
289
 	if ( output->len > output->max_len ) {
313
 	if ( output->len > output->max_len ) {
290
 		fprintf ( stderr, "Output buffer overrun on pack\n" );
314
 		fprintf ( stderr, "Output buffer overrun on pack\n" );
291
 		return -1;
315
 		return -1;
292
 	}
316
 	}
317
+	*len32 = ( packed_len + sizeof ( *crc32 ) );
318
+	*crc32 = crc32_le ( CRCSEED, packed, packed_len );
319
+
320
+	if ( DEBUG ) {
321
+		fprintf ( stderr, "PACK [%#zx,%#zx) to [%#zx,%#zx) crc %#08x\n",
322
+			  offset, ( offset + len ), start_len, output->len,
323
+			  *crc32 );
324
+	}
293
 
325
 
294
 	return 0;
326
 	return 0;
295
 }
327
 }

Loading…
Cancel
Save