Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 351b0940 authored by Paul Burton's avatar Paul Burton Committed by Ralf Baechle
Browse files

MIPS: module: Ensure we always clean up r_mips_hi16_list



If we hit an error whilst processing a reloc then we would return early
from apply_relocate & potentially not free entries in r_mips_hi16_list,
thereby leaking memory. Fix this by ensuring that we always run the code
to free r_mipps_hi16_list when errors occur.

Signed-off-by: default avatarPaul Burton <paul.burton@imgtec.com>
Fixes: 861667dc ("MIPS: Fix race condition in module relocation code.")
Fixes: 04211a57 ("MIPS: Bail on unsupported module relocs")
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/15831/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 59baa24d
Loading
Loading
Loading
Loading
+16 −12
Original line number Original line Diff line number Diff line
@@ -251,7 +251,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
	u32 *location;
	u32 *location;
	unsigned int i, type;
	unsigned int i, type;
	Elf_Addr v;
	Elf_Addr v;
	int res;
	int err = 0;


	pr_debug("Applying relocate section %u to %u\n", relsec,
	pr_debug("Applying relocate section %u to %u\n", relsec,
	       sechdrs[relsec].sh_info);
	       sechdrs[relsec].sh_info);
@@ -270,7 +270,8 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
				continue;
				continue;
			pr_warn("%s: Unknown symbol %s\n",
			pr_warn("%s: Unknown symbol %s\n",
				me->name, strtab + sym->st_name);
				me->name, strtab + sym->st_name);
			return -ENOENT;
			err = -ENOENT;
			goto out;
		}
		}


		type = ELF_MIPS_R_TYPE(rel[i]);
		type = ELF_MIPS_R_TYPE(rel[i]);
@@ -283,29 +284,32 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
		if (!handler) {
		if (!handler) {
			pr_err("%s: Unknown relocation type %u\n",
			pr_err("%s: Unknown relocation type %u\n",
			       me->name, type);
			       me->name, type);
			return -EINVAL;
			err = -EINVAL;
			goto out;
		}
		}


		v = sym->st_value;
		v = sym->st_value;
		res = handler(me, location, v);
		err = handler(me, location, v);
		if (res)
		if (err)
			return res;
			goto out;
	}
	}


out:
	/*
	/*
	 * Normally the hi16 list should be deallocated at this point. A
	 * Normally the hi16 list should be deallocated at this point. A
	 * malformed binary however could contain a series of R_MIPS_HI16
	 * malformed binary however could contain a series of R_MIPS_HI16
	 * relocations not followed by a R_MIPS_LO16 relocation.  In that
	 * relocations not followed by a R_MIPS_LO16 relocation, or if we hit
	 * case, free up the list and return an error.
	 * an error processing a reloc we might have gotten here before
	 * reaching the R_MIPS_LO16. In either case, free up the list and
	 * return an error.
	 */
	 */
	if (me->arch.r_mips_hi16_list) {
	if (me->arch.r_mips_hi16_list) {
		free_relocation_chain(me->arch.r_mips_hi16_list);
		free_relocation_chain(me->arch.r_mips_hi16_list);
		me->arch.r_mips_hi16_list = NULL;
		me->arch.r_mips_hi16_list = NULL;

		err = err ?: -ENOEXEC;
		return -ENOEXEC;
	}
	}


	return 0;
	return err;
}
}


/* Given an address, look for it in the module exception tables. */
/* Given an address, look for it in the module exception tables. */