kern/118222: [pxeboot] FreeBSD 7.0 PXE NFS / "Can't work out which disk we are booting from" on AMD CPU

Luigi Rizzo rizzo at iet.unipi.it
Tue Nov 18 08:40:03 PST 2008


The following reply was made to PR kern/118222; it has been noted by GNATS.

From: Luigi Rizzo <rizzo at iet.unipi.it>
To: bug-followup at FreeBSD.org,
	"http://www.freebsd.org/send-pr.html"@FreeBSD.org
Cc:  
Subject: Re: kern/118222: [pxeboot] FreeBSD 7.0 PXE   NFS / "Can't work out which disk we are booting from" on AMD CPU
Date: Tue, 18 Nov 2008 17:23:24 +0100

 We have identified the problem as related to a heap overflow:
 instrumenting the code at
 
         /usr/src/sys/boot/common/interp.c::include()
 
 you will see that at some point the call to malloc
 
         sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
 
 at some point will not return and cause the pxeboot to be restarted.
 
 Tracking the values returned by malloc() we found that the last
 successful return is something around 0x77384, with the stack
 being dangerously close to it (somewhere around 0x77900 on the first
 call to include but the function is recursive and has a 256 byte
 local variable).
 When the heap overflows, my system is processing line 1500 of
 file /boot/support.4th, which is 1700 lines long and is the last
 (third or fourth) of a set of nested includes.
 
 Why this occurs only on AMD64 is not completely clear, but probably
 it is related to less memory made available by the bios on those
 boards compared to the i386 machines.
 
 In any case the following patch is enough to save enough memory
 so that pxeboot run to completion with our set of includes,
 and it does this by not saving empty lines (about 200 of them in
 the offending file, which saves some 6k of memory) and making
 a buffer static (saving another 1-2k of memory due to the recursive
 calls).
 
 Clearly, this is not the way to go on a system with 2GB of memory,
 and we need to make the entire system more robust :)
 
 	cheers
 	luigi
 
 
 Index: common/interp.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/boot/common/interp.c,v
 retrieving revision 1.29
 diff -u -r1.29 interp.c
 --- common/interp.c	25 Aug 2003 23:30:41 -0000	1.29
 +++ common/interp.c	18 Nov 2008 16:00:57 -0000
 @@ -192,7 +192,7 @@
  include(const char *filename)
  {
      struct includeline	*script, *se, *sp;
 -    char		input[256];			/* big enough? */
 +    static char	input[256];			/* big enough? */
  #ifdef BOOT_FORTH
      int			res;
      char		*cp;
 @@ -236,6 +239,8 @@
  	}
  #endif
  	/* Allocate script line structure and copy line, flags */
 +	if (*cp == '\0')
 +		continue;
  	sp = malloc(sizeof(struct includeline) + strlen(cp) + 1);
  	sp->text = (char *)sp + sizeof(struct includeline);
  	strcpy(sp->text, cp);


More information about the freebsd-bugs mailing list