Fix compat32 on mips64

Summary:
Two bugs:
* Elf32_Auxinfo is broken, using pointers in the union, which are 64-bits not
  32.
* freebsd32_sysarch() doesn't update the 'user local' register when handling
  MIPS_SET_TLS, leading to a NULL pointer dereference in the 32-bit
  application.

Reviewed by:	#mips, brooks
MFC after:	1 week
Sponsored by:	Juniper Networks, Inc
Differential Revision:	https://reviews.freebsd.org/D26556
This commit is contained in:
Justin Hibbits 2020-09-25 17:13:45 +00:00
parent 01d0f9c0e4
commit 6d5ca5199c
2 changed files with 12 additions and 2 deletions

View File

@ -105,8 +105,6 @@ typedef struct { /* Auxiliary vector entry on initial stack */
int a_type; /* Entry type. */
union {
int a_val; /* Integer value. */
void *a_ptr; /* Address. */
void (*a_fcn)(void); /* Function pointer (not used). */
} a_un;
} Elf32_Auxinfo;

View File

@ -58,6 +58,7 @@
#include <vm/vm.h>
#include <vm/vm_param.h>
#include <machine/cpuinfo.h>
#include <machine/md_var.h>
#include <machine/reg.h>
#include <machine/sigframe.h>
@ -455,6 +456,17 @@ freebsd32_sysarch(struct thread *td, struct freebsd32_sysarch_args *uap)
switch (uap->op) {
case MIPS_SET_TLS:
td->td_md.md_tls = (void *)(intptr_t)uap->parms;
/*
* If there is an user local register implementation (ULRI)
* update it as well. Add the TLS and TCB offsets so the
* value in this register is adjusted like in the case of the
* rdhwr trap() instruction handler.
*/
if (cpuinfo.userlocal_reg == true) {
mips_wr_userlocal((unsigned long)(uap->parms +
td->td_md.md_tls_tcb_offset));
}
return (0);
case MIPS_GET_TLS:
tlsbase = (int32_t)(intptr_t)td->td_md.md_tls;