[PowerPC] Implement Secure-PLT jump table processing for ppc32.
Due to clang and LLD's tendency to use a PLT for builtins, and as they don't have full support for EABI, we sometimes have to deal with a PLT in .ko files in a clang-built kernel. As such, augment the in-kernel linker to support jump table processing. As there is no particular reason to support lazy binding in kernel modules, only implement Secure-PLT immediate binding. As part of these changes, add elf_cpu_parse_dynamic() to the MD API of the in-kernel linker (except on platforms that use raw object files.) The new function will allow MD code to act on MD tags in _DYNAMIC. Use this new function in the PowerPC MD code to ensure BSS-PLT modules using PLT will be rejected during insertion, and to poison the runtime resolver to ensure we get a clear panic reason if a call is made to the resolver. Reviewed by: jhibbits Differential Revision: https://reviews.freebsd.org/D22608
This commit is contained in:
parent
f5ead20562
commit
7821a820d0
@ -320,6 +320,13 @@ elf_cpu_load_file(linker_file_t lf)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf __unused, Elf_Dyn *dynamic __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_unload_file(linker_file_t lf)
|
||||
{
|
||||
|
@ -216,3 +216,10 @@ elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf __unused, Elf_Dyn *dynamic __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -295,3 +295,10 @@ elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf __unused, Elf_Dyn *dynamic __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -611,7 +611,7 @@ parse_dynamic(elf_file_t ef)
|
||||
ef->ddbstrtab = ef->strtab;
|
||||
ef->ddbstrcnt = ef->strsz;
|
||||
|
||||
return (0);
|
||||
return elf_cpu_parse_dynamic(&ef->lf, ef->dynamic);
|
||||
}
|
||||
|
||||
#define LS_PADDING 0x90909090
|
||||
|
@ -63,6 +63,7 @@
|
||||
|
||||
extern const char *freebsd32_syscallnames[];
|
||||
static void ppc32_fixlimit(struct rlimit *rl, int which);
|
||||
static void ppc32_runtime_resolve(void);
|
||||
|
||||
static SYSCTL_NODE(_compat, OID_AUTO, ppc32, CTLFLAG_RW, 0, "32-bit mode");
|
||||
|
||||
@ -296,6 +297,20 @@ elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
*where = elf_relocaddr(lf, relocbase + addend);
|
||||
break;
|
||||
|
||||
case R_PPC_JMP_SLOT: /* PLT jump slot entry */
|
||||
/*
|
||||
* We currently only support Secure-PLT jump slots.
|
||||
* Given that we reject BSS-PLT modules during load, we
|
||||
* don't need to check again.
|
||||
* The method we are using here is equivilent to
|
||||
* LD_BIND_NOW.
|
||||
*/
|
||||
error = lookup(lf, symidx, 1, &addr);
|
||||
if (error != 0)
|
||||
return -1;
|
||||
*where = elf_relocaddr(lf, addr + addend);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("kldload: unexpected relocation type %d\n",
|
||||
(int) rtype);
|
||||
@ -356,6 +371,7 @@ elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data,
|
||||
int
|
||||
elf_cpu_load_file(linker_file_t lf)
|
||||
{
|
||||
|
||||
/* Only sync the cache for non-kernel modules */
|
||||
if (lf->id != 1)
|
||||
__syncicache(lf->address, lf->size);
|
||||
@ -368,6 +384,47 @@ elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
ppc32_runtime_resolve()
|
||||
{
|
||||
|
||||
/*
|
||||
* Since we don't support lazy binding, panic immediately if anyone
|
||||
* manages to call the runtime resolver.
|
||||
*/
|
||||
panic("kldload: Runtime resolver was called unexpectedly!");
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf, Elf_Dyn *dynamic)
|
||||
{
|
||||
Elf_Dyn *dp;
|
||||
bool has_plt = false;
|
||||
bool secure_plt = false;
|
||||
Elf_Addr *got;
|
||||
|
||||
for (dp = dynamic; dp->d_tag != DT_NULL; dp++) {
|
||||
switch (dp->d_tag) {
|
||||
case DT_PPC_GOT:
|
||||
secure_plt = true;
|
||||
got = (Elf_Addr *)(lf->address + dp->d_un.d_ptr);
|
||||
/* Install runtime resolver canary. */
|
||||
got[1] = (Elf_Addr)ppc32_runtime_resolve;
|
||||
got[2] = (Elf_Addr)0;
|
||||
break;
|
||||
case DT_PLTGOT:
|
||||
has_plt = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_plt && !secure_plt) {
|
||||
printf("kldload: BSS-PLT modules are not supported.\n");
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc64__
|
||||
|
@ -410,3 +410,10 @@ elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf __unused, Elf_Dyn *dynamic __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -504,3 +504,10 @@ elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf __unused, Elf_Dyn *dynamic __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -429,3 +429,10 @@ elf_cpu_unload_file(linker_file_t lf __unused)
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
elf_cpu_parse_dynamic(linker_file_t lf __unused, Elf_Dyn *dynamic __unused)
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -305,6 +305,10 @@ int linker_ctf_get(linker_file_t, linker_ctf_t *);
|
||||
|
||||
int elf_cpu_load_file(linker_file_t);
|
||||
int elf_cpu_unload_file(linker_file_t);
|
||||
/* amd64 and mips use objects instead of shared libraries */
|
||||
#if !defined(__amd64__) && !defined(__mips__)
|
||||
int elf_cpu_parse_dynamic(linker_file_t, Elf_Dyn *);
|
||||
#endif
|
||||
|
||||
/* values for type */
|
||||
#define ELF_RELOC_REL 1
|
||||
|
Loading…
Reference in New Issue
Block a user