Bug 238748 - several race conditions in nandsim
Summary: several race conditions in nandsim
Status: Closed Overcome By Events
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.0-RELEASE
Hardware: Any Any
: --- Affects Only Me
Assignee: Mark Linimon
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-06-21 14:12 UTC by Ed Maste
Modified: 2019-07-04 11:09 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ed Maste freebsd_committer freebsd_triage 2019-06-21 14:12:47 UTC
Reported to secteam (admbugs 795) but does not need to be treated as a security issue because the NAND framework is not built by default, nandsim is not intended for production use, and the device is root-only.

Reported by: Ilja Van Sprundel <ivansprundel@ioactive.com>

the nandsim driver has a global variable called crtls. when it's used no locks are held. this can cause race conditions in several places leading -among other things- to: 
- double free 
- NULL deref 
- memory leak 

freebsd-master\sys\dev\nand\nandsim.c
static int
nandsim_create_chip(struct sim_chip *chip)
{
struct sim_chip *sim_chip;

nand_debug(NDBG_SIM,"create chip num:%d at ctrl:%d", chip->num,
   chip->ctrl_num);

if (chip->ctrl_num >= MAX_SIM_DEV ||
   chip->num >= MAX_CTRL_CS) {
return (EINVAL);
}

if (ctrls[chip->ctrl_num].chips[chip->num]) {
return (EEXIST);
}

sim_chip = malloc(sizeof(*sim_chip), M_NANDSIM,
   M_WAITOK);
if (sim_chip == NULL) {
return (ENOMEM);
}

memcpy(sim_chip, chip, sizeof(*sim_chip));
ctrls[chip->ctrl_num].chips[chip->num] = sim_chip; <-- <-- no ctrls lock held, this can leak 
sim_chip->created = 1;

return (0);
}


static int
nandsim_destroy_chip(struct sim_ctrl_chip *chip)
{
struct sim_ctrl_conf *ctrl_conf;

nand_debug(NDBG_SIM,"destroy chip num:%d at ctrl:%d", chip->chip_num,
   chip->ctrl_num);

if (chip->ctrl_num >= MAX_SIM_DEV ||
   chip->chip_num >= MAX_CTRL_CS)
return (EINVAL);

ctrl_conf = &ctrls[chip->ctrl_num];

if (!ctrl_conf->created || !ctrl_conf->chips[chip->chip_num])
return (ENODEV);

if (ctrl_conf->running)
return (EBUSY);

free(ctrl_conf->chips[chip->chip_num], M_NANDSIM); <-- no ctrls lock held, this could double free
ctrl_conf->chips[chip->chip_num] = NULL;

return (0);
}


static int
nandsim_modify(struct sim_mod *mod)
{
struct sim_chip *sim_conf = NULL;
struct nandsim_chip *sim_chip = NULL;

nand_debug(NDBG_SIM,"modify ctlr %d chip %d", mod->ctrl_num,
   mod->chip_num);

if (mod->field != SIM_MOD_LOG_LEVEL) {
if (mod->ctrl_num >= MAX_SIM_DEV ||
   mod->chip_num >= MAX_CTRL_CS)
return (EINVAL);

sim_conf = ctrls[mod->ctrl_num].chips[mod->chip_num]; <-- can be NULL!
sim_chip = get_nandsim_chip(mod->ctrl_num, mod->chip_num); <-- can be NULL!
}

switch (mod->field) {
case SIM_MOD_LOG_LEVEL:
nandsim_log_level = mod->new_value; <-- NULL deref
break;
case SIM_MOD_ERASE_TIME:
sim_conf->erase_time = sim_chip->erase_delay = mod->new_value; <-- NULL deref
break;
case SIM_MOD_PROG_TIME:
sim_conf->prog_time = sim_chip->prog_delay = mod->new_value; <-- NULL deref
break;
case SIM_MOD_READ_TIME:
sim_conf->read_time = sim_chip->read_delay = mod->new_value; <-- NULL deref
break;
case SIM_MOD_ERROR_RATIO:
sim_conf->error_ratio = mod->new_value; <-- NULL deref
sim_chip->error_ratio = mod->new_value;
break;
default:
break;
}

return (0);
}
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2019-07-04 11:09:31 UTC
The known-broken nand code was removed at r349352.