Subject: Opus 400 - ld misses a couple overflow checks (#400)
Index:	bin/ld.c 2.11BSD

Description:
	The linker ('ld') fails to print an error in some cases when the 
	base segment of an overlaid program (or kernel) overflows 64kb.

Repeat-By:
	Place too many drivers into the base segment of the kernel.  If
	the size of the kernel base segment wraps 64kb no error will be
	given by 'ld'.  Rather 'netbind' (which performs the symbol cross
	checking between the kernel and networking images) will print out
	many undefined symbols with garbage names.

Fix:
	Tim Shoppa encountered this problem and provided the fix.  There
	were two places in 'ld' which were missing the check for the base
	segment size overflowing.  

	'ld' would catch those size errors which caused the base segment 
	to be between 56kb and 64kb but the checks for the size wrapping around
	64k (0) were missing.

	Not content to simply fix ld.c (and this being update #400 which I
	felt called for at least a little extra effort on my part ;-)) the
	data size of 'ld' was reduced by rearranging the error message strings
	passed to the 'add()' function.  Also, to continue the migration of
	the manpages (to the source directory of the program they belong to)
	the manpage for ld(1) was moved into the ld/ source directory.

	Originally there were plans for a more elaborate "celebration" of
	"Opus 400" (the 400th update to 2.11 since its release) but alas,
	dealing with SoilRus at work has drained the creative effort lately
	on the 2BSD front.  Perhaps later in the year 2.11 will receive the
	attention it deserves.

	To install this update cut where indicated,  saving to a file (/tmp/400)
	and then:

		cd /tmp
		sh 400
		patch -p0 < 400.patch
		chmod +x 400.sh
		./400.sh

	400.sh is a one line shell script which relocates 'ld.1' from the
	/usr/src/man/man1 directory to the src/bin/ld directory - you can, if
	so inclined simply run the 'mv' manually.

	Then:

		cd /usr/src/bin/ld
		make clean
		make install
		make clean

	As always this and previous updates to 2.11BSD are available via
	anonymous FTP to either FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the
	directory /pub/2.11BSD.

=============================cut here=============================
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	400.patch
#	400.sh
# This archive created: Sat Jan 24 22:14:20 1998
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f '400.patch'
then
	echo shar: "will not over-write existing file '400.patch'"
else
sed 's/^Z//' << \SHAR_EOF > '400.patch'
Z*** /usr/src/bin/ld/ld.c.old	Fri Oct 31 22:56:47 1997
Z--- /usr/src/bin/ld/ld.c	Sat Jan 24 20:39:49 1998
Z***************
Z*** 1,8 ****
Z  #if	defined(DOSCCS) && !defined(lint)
Z! static char *sccsid = "@(#)ld.c	4.5 1997/10/31";
Z  #endif
Z  
Z  /*
Z   * 4.5 1997/10/31 - sms
Z   *	Minor cleanup.  Use unistd.h and stdlib.h instead of local definitions.
Z   *	Correct comment about number of VM pages.
Z--- 1,15 ----
Z  #if	defined(DOSCCS) && !defined(lint)
Z! static char *sccsid = "@(#)ld.c	4.6 1998/01/19";
Z  #endif
Z  
Z  /*
Z+  * 4.6 1998/01/19 - Tim Shoppa (shoppa@triumf.ca)
Z+  *      Minor bug fix: when tsize was being incremented by THUNKSZ,
Z+  *      no check was being made for 16-bit overflow.  Fix was to
Z+  *      call add().  Same was done for the round up to the nearest
Z+  *      0100 on tsize.  Modify add()'s error reporting to reduce memory 
Z+  *	usage - sms.
Z+  *
Z   * 4.5 1997/10/31 - sms
Z   *	Minor cleanup.  Use unistd.h and stdlib.h instead of local definitions.
Z   *	Correct comment about number of VM pages.
Z***************
Z*** 938,946 ****
Z  		}
Z  
Z  	if (libflg==0 || ndef) {
Z! 		tsize = add(tsize,filhdr.e.a_text,"text overflow");
Z! 		dsize = add(dsize,filhdr.e.a_data,"data overflow");
Z! 		bsize = add(bsize,filhdr.e.a_bss,"bss overflow");
Z  		ssize += nlocal;
Z  		return (1);
Z  	}
Z--- 945,953 ----
Z  		}
Z  
Z  	if (libflg==0 || ndef) {
Z! 		tsize = add(tsize,filhdr.e.a_text,"text");
Z! 		dsize = add(dsize,filhdr.e.a_data,"data");
Z! 		bsize = add(bsize,filhdr.e.a_bss,"bss");
Z  		ssize += nlocal;
Z  		return (1);
Z  	}
Z***************
Z*** 1030,1036 ****
Z  				sp->n_value = csize;
Z  				sp->n_type = N_EXT+N_COMM;
Z  				VMMODIFY(seg);
Z! 				csize = add(csize, t, "bss overflow");
Z  			}
Z  		}
Z  	}
Z--- 1037,1043 ----
Z  				sp->n_value = csize;
Z  				sp->n_type = N_EXT+N_COMM;
Z  				VMMODIFY(seg);
Z! 				csize = add(csize, t, "bss");
Z  			}
Z  		}
Z  	}
Z***************
Z*** 1046,1052 ****
Z  				sp->sovalue = sp->n_value;
Z  				sp->n_value = tsize;
Z  				VMMODIFY(seg);
Z! 				tsize += THUNKSIZ;
Z  				if (trace)
Z  					printf("relocating %.*s in overlay %d from %o to %o\n",
Z  						NNAMESIZE,sp->n_name,sp->n_ovly,
Z--- 1053,1059 ----
Z  				sp->sovalue = sp->n_value;
Z  				sp->n_value = tsize;
Z  				VMMODIFY(seg);
Z! 				tsize = add(tsize, THUNKSIZ, "text");
Z  				if (trace)
Z  					printf("relocating %.*s in overlay %d from %o to %o\n",
Z  						NNAMESIZE,sp->n_name,sp->n_ovly,
Z***************
Z*** 1058,1064 ****
Z  	 * Now set symbols to their final value
Z  	 */
Z  	if (nflag || iflag)
Z! 		tsize = (tsize + 077) & ~077;
Z  	ttsize = tsize;
Z  	if (numov) {
Z  		register int i;
Z--- 1065,1071 ----
Z  	 * Now set symbols to their final value
Z  	 */
Z  	if (nflag || iflag)
Z! 		tsize = add(tsize, 077, "text") & ~077;
Z  	ttsize = tsize;
Z  	if (numov) {
Z  		register int i;
Z***************
Z*** 1141,1147 ****
Z  	}
Z  	if (sflag || xflag)
Z  		ssize = 0;
Z! 	bsize = add(bsize, csize, "bss overflow");
Z  	nsym = ssize / (sizeof cursym);
Z  }
Z  
Z--- 1148,1154 ----
Z  	}
Z  	if (sflag || xflag)
Z  		ssize = 0;
Z! 	bsize = add(bsize, csize, "bss");
Z  	nsym = ssize / (sizeof cursym);
Z  }
Z  
Z***************
Z*** 2004,2013 ****
Z  char *s;
Z  {
Z  	long r;
Z  
Z  	r = (long)(u_int)a + (u_int)b;
Z  	if (r >= 0200000)
Z! 		error(1,s);
Z  	return(r);
Z  }
Z  
Z--- 2011,2026 ----
Z  char *s;
Z  {
Z  	long r;
Z+ 	register char *ap;
Z  
Z  	r = (long)(u_int)a + (u_int)b;
Z  	if (r >= 0200000)
Z! 		{
Z! 		ap = (char *)alloca(strlen(s) + 1 + sizeof (" overflow"));
Z! 		strcpy(ap, s);
Z! 		strcat(ap, " overflow");
Z! 		error(1, ap);
Z! 		}
Z  	return(r);
Z  }
Z  
Z*** /usr/src/bin/ld/Makefile.old	Thu Jan 19 21:55:45 1995
Z--- /usr/src/bin/ld/Makefile	Sat Jan 24 21:41:21 1998
Z***************
Z*** 1,19 ****
Z! # Version 2.1 January 19, 1994
Z  
Z  SRCS=	ld.c
Z  OBJS=	ld.o
Z  CFLAGS=	-O -I../ar -DNUM_VM_PAGES=20
Z  
Z! all:	ld
Z  
Z  ld: ${OBJS}
Z  	cc -i -o ld ${OBJS} -lvmf
Z  
Z! install:
Z  	install -c -s -o bin -g bin -m 755 ld ${DESTDIR}/bin/ld
Z  
Z  lint:
Z  	lint -havx -I../ar ${SRCS}
Z  
Z  clean:
Z! 	rm -f *.o *.0 ld
Z--- 1,25 ----
Z! # Version 2.2 January 24, 1998
Z  
Z  SRCS=	ld.c
Z  OBJS=	ld.o
Z+ MAN=	ld.0
Z+ MANSRC=	ld.1
Z  CFLAGS=	-O -I../ar -DNUM_VM_PAGES=20
Z  
Z! all:	ld ld.0
Z  
Z  ld: ${OBJS}
Z  	cc -i -o ld ${OBJS} -lvmf
Z  
Z! install: all
Z  	install -c -s -o bin -g bin -m 755 ld ${DESTDIR}/bin/ld
Z+ 	install -c -o bin -g bin -m 444 ${MAN} ${DESTDIR}/usr/man/cat1
Z  
Z  lint:
Z  	lint -havx -I../ar ${SRCS}
Z  
Z  clean:
Z! 	rm -f ${OBJS} ${MAN} ld
Z! 
Z! ${MAN}: ${MANSRC}
Z! 	/usr/man/manroff ${MANSRC} > ${MAN}
Z*** /usr/src/man/man1/Makefile.old	Fri Jun 27 20:19:13 1997
Z--- /usr/src/man/man1/Makefile	Sat Jan 24 20:44:46 1998
Z***************
Z*** 14,20 ****
Z  # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Z  # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Z  #
Z! #	@(#)Makefile	1.8 (2.11BSD) 1997/6/27
Z  #
Z  MDIR=	/usr/man/cat1
Z  SRCS=	adb.1 addbib.1 apply.1 apropos.1 as.1 at.1 atq.1 atrm.1 \
Z--- 14,20 ----
Z  # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
Z  # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
Z  #
Z! #	@(#)Makefile	1.9 (2.11BSD) 1998/1/24
Z  #
Z  MDIR=	/usr/man/cat1
Z  SRCS=	adb.1 addbib.1 apply.1 apropos.1 as.1 at.1 atq.1 atrm.1 \
Z***************
Z*** 25,31 ****
Z  	efl.1 eqn.1 error.1 ex.1 expand.1 expr.1 f77.1 false.1 file.1 \
Z  	find.1 fmt.1 fold.1 fpr.1 from.1 fsplit.1 gcore.1 \
Z  	graph.1 grep.1 head.1 hostid.1 indent.1 \
Z! 	intro.1 iostat.1 join.1 kill.1 last.1 lastcomm.1 ld.1 \
Z  	learn.1 leave.1 lex.1 lint.1 lisp.1 ln.1 logger.1 login.1 \
Z  	look.1 lookbib.1 lorder.1 lpq.1 lpr.1 lprm.1 lptest.1 ls.1 \
Z  	lxref.1 m4.1 mail.1 make.1 man.1 mesg.1 mkdep.1 mkdir.1 mkstr.1 \
Z--- 25,31 ----
Z  	efl.1 eqn.1 error.1 ex.1 expand.1 expr.1 f77.1 false.1 file.1 \
Z  	find.1 fmt.1 fold.1 fpr.1 from.1 fsplit.1 gcore.1 \
Z  	graph.1 grep.1 head.1 hostid.1 indent.1 \
Z! 	intro.1 iostat.1 join.1 kill.1 last.1 lastcomm.1 \
Z  	learn.1 leave.1 lex.1 lint.1 lisp.1 ln.1 logger.1 login.1 \
Z  	look.1 lookbib.1 lorder.1 lpq.1 lpr.1 lprm.1 lptest.1 ls.1 \
Z  	lxref.1 m4.1 mail.1 make.1 man.1 mesg.1 mkdep.1 mkdir.1 mkstr.1 \
Z***************
Z*** 53,59 ****
Z  	efl.0 eqn.0 error.0 ex.0 expand.0 expr.0 f77.0 false.0 file.0 \
Z  	find.0 fmt.0 fold.0 fpr.0 from.0 fsplit.0 gcore.0 \
Z  	graph.0 grep.0 head.0 hostid.0 indent.0 \
Z! 	intro.0 iostat.0 join.0 kill.0 last.0 lastcomm.0 ld.0 \
Z  	learn.0 leave.0 lex.0 lint.0 lisp.0 ln.0 logger.0 login.0 \
Z  	look.0 lookbib.0 lorder.0 lpq.0 lpr.0 lprm.0 lptest.0 ls.0 \
Z  	lxref.0 m4.0 mail.0 make.0 man.0 mesg.0 mkdep.0 mkdir.0 mkstr.0 \
Z--- 53,59 ----
Z  	efl.0 eqn.0 error.0 ex.0 expand.0 expr.0 f77.0 false.0 file.0 \
Z  	find.0 fmt.0 fold.0 fpr.0 from.0 fsplit.0 gcore.0 \
Z  	graph.0 grep.0 head.0 hostid.0 indent.0 \
Z! 	intro.0 iostat.0 join.0 kill.0 last.0 lastcomm.0 \
Z  	learn.0 leave.0 lex.0 lint.0 lisp.0 ln.0 logger.0 login.0 \
Z  	look.0 lookbib.0 lorder.0 lpq.0 lpr.0 lprm.0 lptest.0 ls.0 \
Z  	lxref.0 m4.0 mail.0 make.0 man.0 mesg.0 mkdep.0 mkdir.0 mkstr.0 \
Z*** /VERSION.old	Sat Jan  3 22:25:30 1998
Z--- /VERSION	Sat Jan 24 20:13:15 1998
Z***************
Z*** 1,5 ****
Z! Current Patch Level: 399
Z! Date: January 3, 1998
Z  
Z  2.11 BSD
Z  ============
Z--- 1,5 ----
Z! Current Patch Level: 400
Z! Date: January 24, 1998
Z  
Z  2.11 BSD
Z  ============
SHAR_EOF
chmod 644 '400.patch'
fi
if test -f '400.sh'
then
	echo shar: "will not over-write existing file '400.sh'"
else
sed 's/^Z//' << \SHAR_EOF > '400.sh'
Z#!/bin/sh -x
Z
Zmv /usr/src/man/man1/ld.1 /usr/src/bin/ld/ld.1
Zexit 0
SHAR_EOF
chmod 755 '400.sh'
fi
exit 0
#	End of shell archive
