MFV r296306: 6604 harden DIF bounds checking
Reviewed by: Alex Wilson <alex.wilson@joyent.com> Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Reviewed by: Dan McDonald <danmcd@omniti.com> Approved by: Robert Mustacchi <rm@joyent.com> Author: Bryan Cantrill <bryan@joyent.com> illumos/illumos-gate@1c0cef67db MFC after: 2 weeks
This commit is contained in:
commit
acaa855f6e
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=296475
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2016, Joyent, Inc. All rights reserved.
|
||||
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
|
||||
*/
|
||||
|
||||
@ -678,10 +678,12 @@ dtrace_error(uint32_t *counter)
|
||||
* Use the DTRACE_LOADFUNC macro to define functions for each of loading a
|
||||
* uint8_t, a uint16_t, a uint32_t and a uint64_t.
|
||||
*/
|
||||
/* BEGIN CSTYLED */
|
||||
DTRACE_LOADFUNC(8)
|
||||
DTRACE_LOADFUNC(16)
|
||||
DTRACE_LOADFUNC(32)
|
||||
DTRACE_LOADFUNC(64)
|
||||
/* END CSTYLED */
|
||||
|
||||
static int
|
||||
dtrace_inscratch(uintptr_t dest, size_t size, dtrace_mstate_t *mstate)
|
||||
@ -765,6 +767,7 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
|
||||
uintptr_t base = (uintptr_t)dstate->dtds_base +
|
||||
(dstate->dtds_hashsize * sizeof (dtrace_dynhash_t));
|
||||
uintptr_t chunkoffs;
|
||||
dtrace_dynvar_t *dvar;
|
||||
|
||||
/*
|
||||
* Before we assume that we can store here, we need to make
|
||||
@ -781,6 +784,8 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
|
||||
*
|
||||
* (3) Not span a chunk boundary
|
||||
*
|
||||
* (4) Not be in the tuple space of a dynamic variable
|
||||
*
|
||||
*/
|
||||
if (addr < base)
|
||||
return (0);
|
||||
@ -793,6 +798,15 @@ dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
|
||||
if (chunkoffs + sz > dstate->dtds_chunksize)
|
||||
return (0);
|
||||
|
||||
dvar = (dtrace_dynvar_t *)((uintptr_t)addr - chunkoffs);
|
||||
|
||||
if (dvar->dtdv_hashval == DTRACE_DYNHASH_FREE)
|
||||
return (0);
|
||||
|
||||
if (chunkoffs < sizeof (dtrace_dynvar_t) +
|
||||
((dvar->dtdv_tuple.dtt_nkeys - 1) * sizeof (dtrace_key_t)))
|
||||
return (0);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
@ -5632,6 +5646,12 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
|
||||
ipaddr_t ip4;
|
||||
uint8_t *ptr8, val;
|
||||
|
||||
if (!dtrace_canload(tupregs[argi].dttk_value,
|
||||
sizeof (ipaddr_t), mstate, vstate)) {
|
||||
regs[rd] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely load the IPv4 address.
|
||||
*/
|
||||
@ -5685,6 +5705,12 @@ dtrace_dif_subr(uint_t subr, uint_t rd, uint64_t *regs,
|
||||
* just the IPv4 string is returned for inet_ntoa6.
|
||||
*/
|
||||
|
||||
if (!dtrace_canload(tupregs[argi].dttk_value,
|
||||
sizeof (struct in6_addr), mstate, vstate)) {
|
||||
regs[rd] = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely load the IPv6 address.
|
||||
*/
|
||||
@ -6248,6 +6274,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
|
||||
ASSERT(id >= DIF_VAR_OTHER_UBASE);
|
||||
id -= DIF_VAR_OTHER_UBASE;
|
||||
|
||||
VERIFY(id < vstate->dtvs_nglobals);
|
||||
svar = vstate->dtvs_globals[id];
|
||||
ASSERT(svar != NULL);
|
||||
v = &svar->dtsv_var;
|
||||
@ -6339,7 +6366,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
|
||||
|
||||
ASSERT(id >= DIF_VAR_OTHER_UBASE);
|
||||
id -= DIF_VAR_OTHER_UBASE;
|
||||
ASSERT(id < vstate->dtvs_nlocals);
|
||||
VERIFY(id < vstate->dtvs_nlocals);
|
||||
|
||||
ASSERT(vstate->dtvs_locals != NULL);
|
||||
svar = vstate->dtvs_locals[id];
|
||||
@ -6417,6 +6444,7 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
|
||||
id = DIF_INSTR_VAR(instr);
|
||||
ASSERT(id >= DIF_VAR_OTHER_UBASE);
|
||||
id -= DIF_VAR_OTHER_UBASE;
|
||||
VERIFY(id < vstate->dtvs_ntlocals);
|
||||
|
||||
key = &tupregs[DIF_DTR_NREGS];
|
||||
key[0].dttk_value = (uint64_t)id;
|
||||
@ -6530,8 +6558,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
|
||||
if (DIF_INSTR_OP(instr) == DIF_OP_LDTAA) {
|
||||
DTRACE_TLS_THRKEY(key[nkeys].dttk_value);
|
||||
key[nkeys++].dttk_size = 0;
|
||||
VERIFY(id < vstate->dtvs_ntlocals);
|
||||
v = &vstate->dtvs_tlocals[id];
|
||||
} else {
|
||||
VERIFY(id < vstate->dtvs_nglobals);
|
||||
v = &vstate->dtvs_globals[id]->dtsv_var;
|
||||
}
|
||||
|
||||
@ -6570,8 +6600,10 @@ dtrace_dif_emulate(dtrace_difo_t *difo, dtrace_mstate_t *mstate,
|
||||
if (DIF_INSTR_OP(instr) == DIF_OP_STTAA) {
|
||||
DTRACE_TLS_THRKEY(key[nkeys].dttk_value);
|
||||
key[nkeys++].dttk_size = 0;
|
||||
VERIFY(id < vstate->dtvs_ntlocals);
|
||||
v = &vstate->dtvs_tlocals[id];
|
||||
} else {
|
||||
VERIFY(id < vstate->dtvs_nglobals);
|
||||
v = &vstate->dtvs_globals[id]->dtsv_var;
|
||||
}
|
||||
|
||||
@ -9584,6 +9616,7 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
|
||||
int (*efunc)(uint_t pc, const char *, ...) = dtrace_difo_err;
|
||||
int kcheckload;
|
||||
uint_t pc;
|
||||
int maxglobal = -1, maxlocal = -1, maxtlocal = -1;
|
||||
|
||||
kcheckload = cr == NULL ||
|
||||
(vstate->dtvs_state->dts_cred.dcr_visible & DTRACE_CRV_KERNEL) == 0;
|
||||
@ -9913,6 +9946,9 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
|
||||
|
||||
switch (v->dtdv_scope) {
|
||||
case DIFV_SCOPE_GLOBAL:
|
||||
if (maxglobal == -1 || ndx > maxglobal)
|
||||
maxglobal = ndx;
|
||||
|
||||
if (ndx < vstate->dtvs_nglobals) {
|
||||
dtrace_statvar_t *svar;
|
||||
|
||||
@ -9923,11 +9959,17 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
|
||||
break;
|
||||
|
||||
case DIFV_SCOPE_THREAD:
|
||||
if (maxtlocal == -1 || ndx > maxtlocal)
|
||||
maxtlocal = ndx;
|
||||
|
||||
if (ndx < vstate->dtvs_ntlocals)
|
||||
existing = &vstate->dtvs_tlocals[ndx];
|
||||
break;
|
||||
|
||||
case DIFV_SCOPE_LOCAL:
|
||||
if (maxlocal == -1 || ndx > maxlocal)
|
||||
maxlocal = ndx;
|
||||
|
||||
if (ndx < vstate->dtvs_nlocals) {
|
||||
dtrace_statvar_t *svar;
|
||||
|
||||
@ -9976,6 +10018,37 @@ dtrace_difo_validate(dtrace_difo_t *dp, dtrace_vstate_t *vstate, uint_t nregs,
|
||||
}
|
||||
}
|
||||
|
||||
for (pc = 0; pc < dp->dtdo_len && err == 0; pc++) {
|
||||
dif_instr_t instr = dp->dtdo_buf[pc];
|
||||
|
||||
uint_t v = DIF_INSTR_VAR(instr);
|
||||
uint_t op = DIF_INSTR_OP(instr);
|
||||
|
||||
switch (op) {
|
||||
case DIF_OP_LDGS:
|
||||
case DIF_OP_LDGAA:
|
||||
case DIF_OP_STGS:
|
||||
case DIF_OP_STGAA:
|
||||
if (v > DIF_VAR_OTHER_UBASE + maxglobal)
|
||||
err += efunc(pc, "invalid variable %u\n", v);
|
||||
break;
|
||||
case DIF_OP_LDTS:
|
||||
case DIF_OP_LDTAA:
|
||||
case DIF_OP_STTS:
|
||||
case DIF_OP_STTAA:
|
||||
if (v > DIF_VAR_OTHER_UBASE + maxtlocal)
|
||||
err += efunc(pc, "invalid variable %u\n", v);
|
||||
break;
|
||||
case DIF_OP_LDLS:
|
||||
case DIF_OP_STLS:
|
||||
if (v > DIF_VAR_OTHER_UBASE + maxlocal)
|
||||
err += efunc(pc, "invalid variable %u\n", v);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (err);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user