Fix a panic on boot introduced by 555a861d68
First, an sbuf_new() in device_get_path() shadows the sb passed in by dev_wired_cache_add(), leaving its sb in an unfinished state, leading to a failed KASSERT(). Fixing this is as simple as removing the sbuf_new() from device_get_path() Second, we cannot simply take a pointer to the sbuf memory and store it in the device location cache, because that sbuf is freed immediately after we add data to the cache, leading to a use-after-free and eventually a double-free. Fixing this requires allocating memory for the path. After a discussion with jhb, we decided that one malloc was better than two in dev_wired_cache_add, which is why it changed so much. Reviewed by: jhb Sponsored by: Netflix MFC after: 14 days
This commit is contained in:
parent
7366c0a49c
commit
8b19898a78
@ -5310,7 +5310,7 @@ device_get_path(device_t dev, const char *locator, struct sbuf *sb)
|
||||
device_t parent;
|
||||
int error;
|
||||
|
||||
sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND | SBUF_INCLUDENUL);
|
||||
KASSERT(sb != NULL, ("sb is NULL"));
|
||||
parent = device_get_parent(dev);
|
||||
if (parent == NULL) {
|
||||
error = sbuf_printf(sb, "/");
|
||||
@ -5663,8 +5663,6 @@ dev_wired_cache_fini(device_location_cache_t *dcp)
|
||||
struct device_location_node *dln, *tdln;
|
||||
|
||||
TAILQ_FOREACH_SAFE(dln, &dcp->dlc_list, dln_link, tdln) {
|
||||
/* Note: one allocation for both node and locator, but not path */
|
||||
free(__DECONST(void *, dln->dln_path), M_BUS);
|
||||
free(dln, M_BUS);
|
||||
}
|
||||
free(dcp, M_BUS);
|
||||
@ -5687,12 +5685,15 @@ static struct device_location_node *
|
||||
dev_wired_cache_add(device_location_cache_t *dcp, const char *locator, const char *path)
|
||||
{
|
||||
struct device_location_node *dln;
|
||||
char *l;
|
||||
size_t loclen, pathlen;
|
||||
|
||||
dln = malloc(sizeof(*dln) + strlen(locator) + 1, M_BUS, M_WAITOK | M_ZERO);
|
||||
dln->dln_locator = l = (char *)(dln + 1);
|
||||
memcpy(l, locator, strlen(locator) + 1);
|
||||
dln->dln_path = path;
|
||||
loclen = strlen(locator) + 1;
|
||||
pathlen = strlen(path) + 1;
|
||||
dln = malloc(sizeof(*dln) + loclen + pathlen, M_BUS, M_WAITOK | M_ZERO);
|
||||
dln->dln_locator = (char *)(dln + 1);
|
||||
memcpy(__DECONST(char *, dln->dln_locator), locator, loclen);
|
||||
dln->dln_path = dln->dln_locator + loclen;
|
||||
memcpy(__DECONST(char *, dln->dln_path), path, pathlen);
|
||||
TAILQ_INSERT_HEAD(&dcp->dlc_list, dln, dln_link);
|
||||
|
||||
return (dln);
|
||||
|
Loading…
Reference in New Issue
Block a user