From 3bd7187ff549a2ef2441dcddabf382cc53cf6f22 Mon Sep 17 00:00:00 2001 From: Lucas De Marchi Date: Mon, 9 Mar 2020 22:00:27 -0700 Subject: libkmod: fix return error when opening index When calling kmod_load_resources() we could end up getting a bogus return value -ENOMEM due to several other reasons, like the index not existing. Change index_mm_open() to propagate the failure reason so we can take actions on it or return to the caller. --- libkmod/libkmod-index.c | 31 +++++++++++++++++++------------ libkmod/libkmod-index.h | 4 ++-- libkmod/libkmod.c | 16 ++++++++-------- 3 files changed, 29 insertions(+), 22 deletions(-) diff --git a/libkmod/libkmod-index.c b/libkmod/libkmod-index.c index 1f3351a..6a34c8d 100644 --- a/libkmod/libkmod-index.c +++ b/libkmod/libkmod-index.c @@ -611,7 +611,7 @@ struct index_value *index_searchwild(struct index_file *in, const char *key) static const char _idx_empty_str[] = ""; struct index_mm { - struct kmod_ctx *ctx; + const struct kmod_ctx *ctx; void *mm; uint32_t root_offset; size_t size; @@ -739,10 +739,10 @@ static void index_mm_free_node(struct index_mm_node *node) free(node); } -struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename, - unsigned long long *stamp) +int index_mm_open(const struct kmod_ctx *ctx, const char *filename, + unsigned long long *stamp, struct index_mm **pidx) { - int fd; + int fd, err; struct stat st; struct index_mm *idx; struct { @@ -752,28 +752,32 @@ struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename, } hdr; void *p; + assert(pidx != NULL); + DBG(ctx, "file=%s\n", filename); idx = malloc(sizeof(*idx)); if (idx == NULL) { ERR(ctx, "malloc: %m\n"); - return NULL; + return -ENOMEM; } if ((fd = open(filename, O_RDONLY|O_CLOEXEC)) < 0) { DBG(ctx, "open(%s, O_RDONLY|O_CLOEXEC): %m\n", filename); + err = -errno; goto fail_open; } - if (fstat(fd, &st) < 0) - goto fail_nommap; - if ((size_t) st.st_size < sizeof(hdr)) + if (fstat(fd, &st) < 0 || (size_t) st.st_size < sizeof(hdr)) { + err = -EINVAL; goto fail_nommap; + } - if ((idx->mm = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) - == MAP_FAILED) { + idx->mm = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (idx->mm == MAP_FAILED) { ERR(ctx, "mmap(NULL, %"PRIu64", PROT_READ, %d, MAP_PRIVATE, 0): %m\n", st.st_size, fd); + err = -errno; goto fail_nommap; } @@ -785,12 +789,14 @@ struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename, if (hdr.magic != INDEX_MAGIC) { ERR(ctx, "magic check fail: %x instead of %x\n", hdr.magic, INDEX_MAGIC); + err = -EINVAL; goto fail; } if (hdr.version >> 16 != INDEX_VERSION_MAJOR) { ERR(ctx, "major version check fail: %u instead of %u\n", hdr.version >> 16, INDEX_VERSION_MAJOR); + err = -EINVAL; goto fail; } @@ -800,8 +806,9 @@ struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename, close(fd); *stamp = stat_mstamp(&st); + *pidx = idx; - return idx; + return 0; fail: munmap(idx->mm, st.st_size); @@ -809,7 +816,7 @@ fail_nommap: close(fd); fail_open: free(idx); - return NULL; + return err; } void index_mm_close(struct index_mm *idx) diff --git a/libkmod/libkmod-index.h b/libkmod/libkmod-index.h index 52aebac..db671b0 100644 --- a/libkmod/libkmod-index.h +++ b/libkmod/libkmod-index.h @@ -40,8 +40,8 @@ void index_values_free(struct index_value *values); /* Implementation using mmap */ struct index_mm; -struct index_mm *index_mm_open(struct kmod_ctx *ctx, const char *filename, - unsigned long long *stamp); +int index_mm_open(const struct kmod_ctx *ctx, const char *filename, + unsigned long long *stamp, struct index_mm **pidx); void index_mm_close(struct index_mm *index); char *index_mm_search(struct index_mm *idx, const char *key); struct index_value *index_mm_searchwild(struct index_mm *idx, const char *key); diff --git a/libkmod/libkmod.c b/libkmod/libkmod.c index 39f58d9..ab5c1e8 100644 --- a/libkmod/libkmod.c +++ b/libkmod/libkmod.c @@ -856,6 +856,7 @@ KMOD_EXPORT int kmod_validate_resources(struct kmod_ctx *ctx) KMOD_EXPORT int kmod_load_resources(struct kmod_ctx *ctx) { size_t i; + int ret; if (ctx == NULL) return -ENOENT; @@ -871,17 +872,16 @@ KMOD_EXPORT int kmod_load_resources(struct kmod_ctx *ctx) snprintf(path, sizeof(path), "%s/%s.bin", ctx->dirname, index_files[i].fn); - ctx->indexes[i] = index_mm_open(ctx, path, - &ctx->indexes_stamp[i]); - if (ctx->indexes[i] == NULL) - goto fail; + ret = index_mm_open(ctx, path, &ctx->indexes_stamp[i], + &ctx->indexes[i]); + if (ret) + break; } - return 0; + if (ret) + kmod_unload_resources(ctx); -fail: - kmod_unload_resources(ctx); - return -ENOMEM; + return ret; } /** -- cgit v1.2.3