diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2022-10-07 01:25:37 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2022-10-19 16:39:26 +0000 |
commit | d9c5a9ea498aa1872b909fae16babf4b292d4e70 (patch) | |
tree | 74f84e05214de6e0966c75f002e49e74917b1987 | |
parent | 23d2fcfbb29dd924f91a039f6d468b430279cfa3 (diff) | |
download | src-d9c5a9ea498aa1872b909fae16babf4b292d4e70.tar.gz src-d9c5a9ea498aa1872b909fae16babf4b292d4e70.zip |
device_get_path(): do not drop the error from BUS_GET_DEVICE_PATH()
Later it would silently converted to ENOMEM always, because any error
was reported as NULL return path.
Reviewed by: jhb, takawata
Discussed with: imp
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Differential revision: https://reviews.freebsd.org/D36899
-rw-r--r-- | sys/kern/subr_bus.c | 49 |
1 files changed, 28 insertions, 21 deletions
diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 3ba68ba78781..b083411f9876 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -5304,27 +5304,33 @@ device_do_deferred_actions(void) bus_data_generation_update(); } -static char * -device_get_path(device_t dev, const char *locator) +static int +device_get_path(device_t dev, const char *locator, char **rvp) { struct sbuf *sb; + char *s; ssize_t len; - char *rv = NULL; int error; sb = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND | SBUF_INCLUDENUL); error = BUS_GET_DEVICE_PATH(device_get_parent(dev), dev, locator, sb); sbuf_finish(sb); /* Note: errors checked with sbuf_len() below */ - if (error != 0) - goto out; - len = sbuf_len(sb); - if (len <= 1) - goto out; - rv = malloc(len, M_BUS, M_NOWAIT); - memcpy(rv, sbuf_data(sb), len); -out: + if (error == 0) { + len = sbuf_len(sb); + if (len <= 1) { + error = EIO; + } else { + s = malloc(len, M_BUS, M_NOWAIT); + if (s == NULL) { + error = ENOMEM; + } else { + memcpy(s, sbuf_data(sb), len); + *rvp = s; + } + } + } sbuf_delete(sb); - return (rv); + return (error); } static int @@ -5595,11 +5601,9 @@ devctl2_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, sizeof(locator), NULL); if (error != 0) break; - path = device_get_path(dev, locator); - if (path == NULL) { - error = ENOMEM; + error = device_get_path(dev, locator, &path); + if (error != 0) break; - } len = strlen(path) + 1; if (req->dr_buffer.length < len) { error = ENAMETOOLONG; @@ -5702,9 +5706,10 @@ bool dev_wired_cache_match(device_location_cache_t *dcp, device_t dev, const char *at) { - const char *cp, *path; + const char *cp; + char *path; char locator[32]; - int len; + int error, len; struct device_location_node *res; cp = strchr(at, ':'); @@ -5717,13 +5722,15 @@ dev_wired_cache_match(device_location_cache_t *dcp, device_t dev, locator[len] = '\0'; cp++; + error = 0; /* maybe cache this inside device_t and look that up, but not yet */ res = dev_wired_cache_lookup(dcp, locator); if (res == NULL) { - path = device_get_path(dev, locator); - res = dev_wired_cache_add(dcp, locator, path); + error = device_get_path(dev, locator, &path); + if (error == 0) + res = dev_wired_cache_add(dcp, locator, path); } - if (res == NULL || res->dln_path == NULL) + if (error != 0 || res == NULL || res->dln_path == NULL) return (false); return (strcmp(res->dln_path, cp) == 0); |