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

Loading…
Cancel
Save