Have sandbox string protection include multi-valued parmeters.

This commit is contained in:
Nick Mathewson 2014-04-16 12:45:34 -04:00
parent f268101a61
commit 5aaac938a9

View File

@ -873,8 +873,13 @@ sandbox_intern_string(const char *str)
for (elem = filter_dynamic; elem != NULL; elem = elem->next) { for (elem = filter_dynamic; elem != NULL; elem = elem->next) {
smp_param_t *param = elem->param; smp_param_t *param = elem->param;
if (param->prot && !strcmp(str, (char*)(param->value))) { if (param->prot) {
return (char*)(param->value); if (!strcmp(str, (char*)(param->value))) {
return (char*)param->value;
}
if (param->value2 && !strcmp(str, (char*)param->value2)) {
return (char*)param->value2;
}
} }
} }
@ -882,6 +887,50 @@ sandbox_intern_string(const char *str)
return str; return str;
} }
/** DOCDOC */
static int
prot_strings_helper(strmap_t *locations,
char **pr_mem_next_p,
size_t *pr_mem_left_p,
intptr_t *value_p)
{
char *param_val;
size_t param_size;
void *location;
if (*value_p == 0)
return 0;
param_val = (char*) *value_p;
param_size = strlen(param_val) + 1;
location = strmap_get(locations, param_val);
if (location) {
// We already interned this string.
tor_free(param_val);
*value_p = (intptr_t) location;
return 0;
} else if (*pr_mem_left_p >= param_size) {
// copy to protected
location = *pr_mem_next_p;
memcpy(location, param_val, param_size);
// re-point el parameter to protected
tor_free(param_val);
*value_p = (intptr_t) location;
strmap_set(locations, location, location); /* good real estate advice */
// move next available protected memory
*pr_mem_next_p += param_size;
*pr_mem_left_p -= param_size;
return 0;
} else {
log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
return -1;
}
}
/** /**
* Protects all the strings in the sandbox's parameter list configuration. It * Protects all the strings in the sandbox's parameter list configuration. It
* works by calculating the total amount of memory required by the parameter * works by calculating the total amount of memory required by the parameter
@ -900,7 +949,8 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
// get total number of bytes required to mmap. (Overestimate.) // get total number of bytes required to mmap. (Overestimate.)
for (el = cfg; el != NULL; el = el->next) { for (el = cfg; el != NULL; el = el->next) {
pr_mem_size += strlen((char*) el->param->value) + 1; pr_mem_size += strlen((char*) el->param->value) + 1;
if (el->param->value2)
pr_mem_size += strlen((char*) el->param->value2) + 1;
} }
// allocate protected memory with MALLOC_MP_LIM canary // allocate protected memory with MALLOC_MP_LIM canary
@ -920,42 +970,17 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
// change el value pointer to protected // change el value pointer to protected
for (el = cfg; el != NULL; el = el->next) { for (el = cfg; el != NULL; el = el->next) {
char *param_val = (char*)(el->param)->value; if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
size_t param_size = strlen(param_val) + 1; &el->param->value) < 0) {
void *location = strmap_get(locations, param_val);
if (location) {
// We already interned this string.
{
void *old_val = (void *) el->param->value;
tor_free(old_val);
}
el->param->value = (intptr_t) location;
el->param->prot = 1;
} else if (pr_mem_left >= param_size) {
// copy to protected
memcpy(pr_mem_next, param_val, param_size);
// re-point el parameter to protected
{
void *old_val = (void *) el->param->value;
tor_free(old_val);
}
el->param->value = (intptr_t) pr_mem_next;
el->param->prot = 1;
strmap_set(locations, pr_mem_next, pr_mem_next);
// move next available protected memory
pr_mem_next += param_size;
pr_mem_left -= param_size;
} else {
log_err(LD_BUG,"(Sandbox) insufficient protected memory!");
ret = -2; ret = -2;
goto out; goto out;
} }
if (prot_strings_helper(locations, &pr_mem_next, &pr_mem_left,
&el->param->value2) < 0) {
ret = -2;
goto out;
}
el->param->prot = 1;
} }
// protecting from writes // protecting from writes
@ -995,7 +1020,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
* There is a restriction on how much you can mprotect with R|W up to the * There is a restriction on how much you can mprotect with R|W up to the
* size of the canary. * size of the canary.
*/ */
ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2, ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 3,
SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base), SCMP_CMP(0, SCMP_CMP_LT, (intptr_t) pr_mem_base),
SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM), SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),
SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE)); SCMP_CMP(2, SCMP_CMP_EQ, PROT_READ|PROT_WRITE));
@ -1004,7 +1029,7 @@ prot_strings(scmp_filter_ctx ctx, sandbox_cfg_t* cfg)
return ret; return ret;
} }
ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 2, ret = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(mprotect), 3,
SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size + SCMP_CMP(0, SCMP_CMP_GT, (intptr_t) pr_mem_base + pr_mem_size +
MALLOC_MP_LIM), MALLOC_MP_LIM),
SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM), SCMP_CMP(1, SCMP_CMP_LE, MALLOC_MP_LIM),