Changeset View
Changeset View
Standalone View
Standalone View
sys/mips/mips/sys_machdep.c
Show First 20 Lines • Show All 51 Lines • ▼ Show 20 Lines | struct sysarch_args { | ||||
int op; | int op; | ||||
char *parms; | char *parms; | ||||
}; | }; | ||||
#endif | #endif | ||||
int | int | ||||
sysarch(struct thread *td, struct sysarch_args *uap) | sysarch(struct thread *td, struct sysarch_args *uap) | ||||
{ | { | ||||
int error; | int error; | ||||
void *tlsbase; | void *tlsbase; | ||||
#ifdef MIPS_TCB_DYNAMIC | |||||
int tcbsize; | |||||
uintptr_t **tp; | |||||
uintptr_t *dtv, tls; | |||||
#endif | |||||
switch (uap->op) { | switch (uap->op) { | ||||
case MIPS_SET_TLS: | case MIPS_SET_TLS: | ||||
td->td_md.md_tls = uap->parms; | td->td_md.md_tls = uap->parms; | ||||
#ifdef MIPS_TCB_DYNAMIC | |||||
/* | |||||
* Default TCB size is constant TLS_TCB_SIZE, but | |||||
* due to alignment TCB may be larger. To identify | |||||
* actual size, check first index of dtv array. | |||||
*/ | |||||
tp = td->td_md.md_tls; | |||||
dtv = *tp; | |||||
#define MIPS_MAX_TCB_SIZE 0x1000 | |||||
tls = dtv[2]; | |||||
mmel: You can never directly dereference the usermode pointer from the kernel. Malicious program can… | |||||
if ((tls > (uintptr_t)tp + TLS_TCB_SIZE) && | |||||
((uintptr_t)tp + MIPS_MAX_TCB_SIZE > tls)) | |||||
{ | |||||
/* At index 0 we found shift of TCB, so let's adjust it */ | |||||
tcbsize = tls - (uintptr_t)tp; | |||||
} else { | |||||
tcbsize = TLS_TCB_SIZE; | |||||
} | |||||
#undef MIPS_MAX_TCB_SIZE | |||||
td->td_md.md_tls_tcb_offset = tcbsize + TLS_TP_OFFSET; | |||||
#endif /* MIPS_TCB_DYNAMIC */ | |||||
/* | /* | ||||
* If there is an user local register implementation (ULRI) | * If there is an user local register implementation (ULRI) | ||||
* update it as well. Add the TLS and TCB offsets so the | * update it as well. Add the TLS and TCB offsets so the | ||||
* value in this register is adjusted like in the case of the | * value in this register is adjusted like in the case of the | ||||
* rdhwr trap() instruction handler. | * rdhwr trap() instruction handler. | ||||
*/ | */ | ||||
if (cpuinfo.userlocal_reg == true) { | if (cpuinfo.userlocal_reg == true) { | ||||
Show All 27 Lines |
You can never directly dereference the usermode pointer from the kernel. Malicious program can pass invalid or kernel address in tcb/dtv which can leads to panic or it can have security implication. Use fueword*() or copyin() for this.
Also, it seems that mips ABI expects dtv[] pointers are biased by TLS_DTP_OFFSET. We have implemented this bias in libexec/rtld, but our libc/gen/tls.c ignores it.