Browse Source

[settings] Avoid returning uninitialised data on error in fetch_xxx_setting()

Callers (e.g. usr/autoboot.c) may not check the return values from
fetch_xxx_setting(), assuming that in error cases the returned setting
value will be "empty" (for some sensible value of "empty").

In particular, if the DHCP server did not specify a next-server
address, this would result in gPXE using uninitialised data for the
TFTP server IP address.
tags/v0.9.6
Michael Brown 15 years ago
parent
commit
612f4e7a99
1 changed files with 15 additions and 5 deletions
  1. 15
    5
      src/core/settings.c

+ 15
- 5
src/core/settings.c View File

@@ -333,6 +333,9 @@ int fetch_setting ( struct settings *settings, struct setting *setting,
333 333
 	struct settings *child;
334 334
 	int ret;
335 335
 
336
+	/* Avoid returning uninitialised data on error */
337
+	memset ( data, 0, len );
338
+
336 339
 	/* NULL settings implies starting at the global settings root */
337 340
 	if ( ! settings )
338 341
 		settings = &settings_root;
@@ -381,7 +384,6 @@ int fetch_setting_len ( struct settings *settings, struct setting *setting ) {
381 384
  */
382 385
 int fetch_string_setting ( struct settings *settings, struct setting *setting,
383 386
 			   char *data, size_t len ) {
384
-	memset ( data, 0, len );
385 387
 	return fetch_setting ( settings, setting, data,
386 388
 			       ( ( len > 0 ) ? ( len - 1 ) : 0 ) );
387 389
 }
@@ -417,20 +419,23 @@ int fetch_ipv4_setting ( struct settings *settings, struct setting *setting,
417 419
 int fetch_int_setting ( struct settings *settings, struct setting *setting,
418 420
 			long *value ) {
419 421
 	union {
420
-		long value;
421 422
 		uint8_t u8[ sizeof ( long ) ];
422 423
 		int8_t s8[ sizeof ( long ) ];
423 424
 	} buf;
424 425
 	int len;
425 426
 	int i;
426 427
 
427
-	buf.value = 0;
428
+	/* Avoid returning uninitialised data on error */
429
+	*value = 0;
430
+
431
+	/* Fetch raw (network-ordered, variable-length) setting */
428 432
 	len = fetch_setting ( settings, setting, &buf, sizeof ( buf ) );
429 433
 	if ( len < 0 )
430 434
 		return len;
431 435
 	if ( len > ( int ) sizeof ( buf ) )
432 436
 		return -ERANGE;
433 437
 
438
+	/* Convert to host-ordered signed long */
434 439
 	*value = ( ( buf.s8[0] >= 0 ) ? 0 : -1L );
435 440
 	for ( i = 0 ; i < len ; i++ ) {
436 441
 		*value = ( ( *value << 8 ) | buf.u8[i] );
@@ -452,10 +457,15 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
452 457
 	long svalue;
453 458
 	int len;
454 459
 
460
+	/* Avoid returning uninitialised data on error */
461
+	*value = 0;
462
+
463
+	/* Fetch as a signed long */
455 464
 	len = fetch_int_setting ( settings, setting, &svalue );
456 465
 	if ( len < 0 )
457 466
 		return len;
458 467
 
468
+	/* Mask off sign-extended bits */
459 469
 	*value = ( svalue & ( -1UL >> ( sizeof ( long ) - len ) ) );
460 470
 
461 471
 	return len;
@@ -469,7 +479,7 @@ int fetch_uint_setting ( struct settings *settings, struct setting *setting,
469 479
  * @ret value		Setting value, or zero
470 480
  */
471 481
 long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
472
-	long value = 0;
482
+	long value;
473 483
 
474 484
 	fetch_int_setting ( settings, setting, &value );
475 485
 	return value;
@@ -484,7 +494,7 @@ long fetch_intz_setting ( struct settings *settings, struct setting *setting ){
484 494
  */
485 495
 unsigned long fetch_uintz_setting ( struct settings *settings,
486 496
 				    struct setting *setting ) {
487
-	unsigned long value = 0;
497
+	unsigned long value;
488 498
 
489 499
 	fetch_uint_setting ( settings, setting, &value );
490 500
 	return value;

Loading…
Cancel
Save