]> git.ipfire.org Git - thirdparty/kmod.git/commitdiff
libkmod: Do not inititialize file->memory on open
authorLucas De Marchi <lucas.de.marchi@gmail.com>
Thu, 1 Jun 2023 22:39:57 +0000 (15:39 -0700)
committerLucas De Marchi <lucas.de.marchi@gmail.com>
Fri, 9 Jun 2023 17:45:51 +0000 (10:45 -0700)
Add a separate function to load the file contents when it's needed.
When it's not needed on the path of loading modules via finit_module(),
there is no need to mmap the file. This will help support loading
modules with the in-kernel compression support.

This is done differently than the lazy initialization for
kmod_file_get_elf() because on the contents case there is also the
file->size to be updated. It would be a weird API to return the pointer
and have the size changed as a side-effect.

Signed-off-by: Lucas De Marchi <lucas.de.marchi@gmail.com>
libkmod/libkmod-elf.c
libkmod/libkmod-file.c
libkmod/libkmod-internal.h
libkmod/libkmod-module.c

index fb2e3d9293c04bc03bd8c53e2c0c7feb82f1010a..933825be2d04c2790bf463797fdef65be99921f0 100644 (file)
@@ -281,6 +281,11 @@ struct kmod_elf *kmod_elf_new(const void *memory, off_t size)
        assert_cc(sizeof(uint32_t) == sizeof(Elf32_Word));
        assert_cc(sizeof(uint32_t) == sizeof(Elf64_Word));
 
+       if (!memory) {
+               errno = -EINVAL;
+               return NULL;
+       }
+
        class = elf_identify(memory, size);
        if (class < 0) {
                errno = -class;
index b6a8cc9579f73d38681ee1d4461f9e758c54dbaa..08adea9bd35e58bb88d72ce1eb5a12a766f23537 100644 (file)
@@ -421,6 +421,7 @@ struct kmod_elf *kmod_file_get_elf(struct kmod_file *file)
        if (file->elf)
                return file->elf;
 
+       kmod_file_load_contents(file);
        file->elf = kmod_elf_new(file->memory, file->size);
        return file->elf;
 }
@@ -431,7 +432,7 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
        struct kmod_file *file = calloc(1, sizeof(struct kmod_file));
        const struct comp_type *itr;
        size_t magic_size_max = 0;
-       int err;
+       int err = 0;
 
        if (file == NULL)
                return NULL;
@@ -477,8 +478,8 @@ struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx,
        if (file->ops == NULL)
                file->ops = &reg_ops;
 
-       err = file->ops->load(file);
        file->ctx = ctx;
+
 error:
        if (err < 0) {
                if (file->fd >= 0)
@@ -491,6 +492,18 @@ error:
        return file;
 }
 
+/*
+ *  Callers should just check file->memory got updated
+ */
+void kmod_file_load_contents(struct kmod_file *file)
+{
+       if (file->memory)
+               return;
+
+       /*  The load functions already log possible errors. */
+       file->ops->load(file);
+}
+
 void *kmod_file_get_contents(const struct kmod_file *file)
 {
        return file->memory;
@@ -516,7 +529,9 @@ void kmod_file_unref(struct kmod_file *file)
        if (file->elf)
                kmod_elf_unref(file->elf);
 
-       file->ops->unload(file);
+       if (file->memory)
+               file->ops->unload(file);
+
        if (file->fd >= 0)
                close(file->fd);
        free(file);
index 4a4af58d68fe4491c88945f03003f9ce74d5d2b9..3275bc5fd677550ce777cd13a214142b98e50a6e 100644 (file)
@@ -152,6 +152,7 @@ bool kmod_module_is_builtin(struct kmod_module *mod) __attribute__((nonnull(1)))
 /* libkmod-file.c */
 struct kmod_file *kmod_file_open(const struct kmod_ctx *ctx, const char *filename) _must_check_ __attribute__((nonnull(1,2)));
 struct kmod_elf *kmod_file_get_elf(struct kmod_file *file) __attribute__((nonnull(1)));
+void kmod_file_load_contents(struct kmod_file *file) __attribute__((nonnull(1)));
 void *kmod_file_get_contents(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 off_t kmod_file_get_size(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
 bool kmod_file_get_direct(const struct kmod_file *file) _must_check_ __attribute__((nonnull(1)));
@@ -166,7 +167,7 @@ struct kmod_modversion {
        char *symbol;
 };
 
-struct kmod_elf *kmod_elf_new(const void *memory, off_t size) _must_check_ __attribute__((nonnull(1)));
+struct kmod_elf *kmod_elf_new(const void *memory, off_t size) _must_check_;
 void kmod_elf_unref(struct kmod_elf *elf) __attribute__((nonnull(1)));
 const void *kmod_elf_get_memory(const struct kmod_elf *elf) _must_check_ __attribute__((nonnull(1)));
 int kmod_elf_get_strings(const struct kmod_elf *elf, const char *section, char ***array) _must_check_ __attribute__((nonnull(1,2,3)));
index 7736b7e106ccd7d9a5b3394088cacc2e9cfdb40a..f352fe12dcf1c0a7b6d160e30f4c2bacbdb6975c 100644 (file)
@@ -917,6 +917,8 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
                        goto init_finished;
        }
 
+       kmod_file_load_contents(mod->file);
+
        if (flags & (KMOD_INSERT_FORCE_VERMAGIC | KMOD_INSERT_FORCE_MODVERSION)) {
                elf = kmod_file_get_elf(mod->file);
                if (elf == NULL) {