DragonFlyBSD Kernel Audit
DF-0042 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c
--- a/sys/kern/link_elf_obj.c
+++ b/sys/kern/link_elf_obj.c
@@ -938,14 +938,16 @@
 }
 
 static Elf_Addr
-findbase(elf_file_t ef, int sec)
+findbase(elf_file_t ef, int sec, Elf_Size *secsize)
 {
 	int i;
 	Elf_Addr base = 0;
 
+	*secsize = 0;
 	for (i = 0; i < ef->nprogtab; i++) {
 		if (sec == ef->progtab[i].sec) {
 			base = (Elf_Addr)ef->progtab[i].addr;
+			*secsize = ef->progtab[i].size;
 			break;
 		}
 	}
@@ -957,6 +959,7 @@
 {
 	elf_file_t	ef = lf->priv;
 	const Elf_Rel *rellim;
+	Elf_Size	secsize;
 	const Elf_Rel *rel;
 	const Elf_Rela *relalim;
 	const Elf_Rela *rela;
@@ -972,13 +975,15 @@
 		if (rel == NULL)
 			panic("lost a reltab!");
 		rellim = rel + ef->reltab[i].nrel;
-		base = findbase(ef, ef->reltab[i].sec);
+		base = findbase(ef, ef->reltab[i].sec, &secsize);
 		if (base == 0)
 			panic("lost base for reltab");
 		for ( ; rel < rellim; rel++) {
 			symidx = ELF_R_SYM(rel->r_info);
 			if (symidx >= ef->ddbsymcnt)
 				continue;
+			if (rel->r_offset >= secsize)
+				continue;
 			sym = ef->ddbsymtab + symidx;
 			/* Local relocs are already done */
 			if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
@@ -999,13 +1004,15 @@
 		if (rela == NULL)
 			panic("lost a relatab!");
 		relalim = rela + ef->relatab[i].nrela;
-		base = findbase(ef, ef->relatab[i].sec);
+		base = findbase(ef, ef->relatab[i].sec, &secsize);
 		if (base == 0)
 			panic("lost base for relatab");
 		for ( ; rela < relalim; rela++) {
 			symidx = ELF_R_SYM(rela->r_info);
 			if (symidx >= ef->ddbsymcnt)
 				continue;
+			if (rela->r_offset >= secsize)
+				continue;
 			sym = ef->ddbsymtab + symidx;
 			/* Local relocs are already done */
 			if (ELF_ST_BIND(sym->st_info) == STB_LOCAL)
@@ -1231,6 +1238,7 @@
 	Elf_Addr base;
 	int i;
 	Elf_Size symidx;
+	Elf_Size secsize;
 
 	link_elf_obj_fix_link_set(ef);
 
@@ -1240,13 +1248,15 @@
 		if (rel == NULL)
 			panic("lost a reltab!");
 		rellim = rel + ef->reltab[i].nrel;
-		base = findbase(ef, ef->reltab[i].sec);
+		base = findbase(ef, ef->reltab[i].sec, &secsize);
 		if (base == 0)
 			panic("lost base for reltab");
 		for ( ; rel < rellim; rel++) {
 			symidx = ELF_R_SYM(rel->r_info);
 			if (symidx >= ef->ddbsymcnt)
 				continue;
+			if (rel->r_offset >= secsize)
+				continue;
 			sym = ef->ddbsymtab + symidx;
 			/* Only do local relocs */
 			if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)
@@ -1262,13 +1272,15 @@
 		if (rela == NULL)
 			panic("lost a relatab!");
 		relalim = rela + ef->relatab[i].nrela;
-		base = findbase(ef, ef->relatab[i].sec);
+		base = findbase(ef, ef->relatab[i].sec, &secsize);
 		if (base == 0)
 			panic("lost base for relatab");
 		for ( ; rela < relalim; rela++) {
 			symidx = ELF_R_SYM(rela->r_info);
 			if (symidx >= ef->ddbsymcnt)
 				continue;
+			if (rela->r_offset >= secsize)
+				continue;
 			sym = ef->ddbsymtab + symidx;
 			/* Only do local relocs */
 			if (ELF_ST_BIND(sym->st_info) != STB_LOCAL)