diff options
Diffstat (limited to 'libkmod/libkmod-module.c')
-rw-r--r-- | libkmod/libkmod-module.c | 395 |
1 files changed, 228 insertions, 167 deletions
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c index 9f33531..cc2c076 100644 --- a/libkmod/libkmod-module.c +++ b/libkmod/libkmod-module.c @@ -1,7 +1,7 @@ /* * libkmod - interface to kernel module operations * - * Copyright (C) 2011-2012 ProFUSION embedded systems + * Copyright (C) 2011-2013 ProFUSION embedded systems * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -33,10 +33,15 @@ #include <sys/stat.h> #include <sys/types.h> #include <sys/mman.h> +#include <sys/syscall.h> #include <sys/wait.h> #include <string.h> #include <fnmatch.h> +#ifdef HAVE_LINUX_MODULE_H +#include <linux/module.h> +#endif + #include "libkmod.h" #include "libkmod-private.h" @@ -60,6 +65,7 @@ struct kmod_module { const char *install_commands; /* owned by kmod_config */ const char *remove_commands; /* owned by kmod_config */ char *alias; /* only set if this module was created from an alias */ + struct kmod_file *file; int n_dep; int refcount; struct { @@ -436,6 +442,10 @@ KMOD_EXPORT struct kmod_module *kmod_module_unref(struct kmod_module *mod) kmod_pool_del_module(mod->ctx, mod, mod->hashkey); kmod_module_unref_list(mod->dep); + + if (mod->file) + kmod_file_unref(mod->file); + kmod_unref(mod->ctx); free(mod->options); free(mod->path); @@ -560,8 +570,7 @@ fail: * Drop a reference of each kmod module in @list and releases the resources * taken by the list itself. * - * Returns: NULL if @mod is NULL or if the module was released. Otherwise it - * returns the passed @mod with its refcount decremented. + * Returns: 0 */ KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list) { @@ -577,7 +586,7 @@ KMOD_EXPORT int kmod_module_unref_list(struct kmod_list *list) * @input: list of kmod_module to be filtered with blacklist * @output: where to save the new list * - * Deprecated: use kmod_module_apply_filter instead. + * This function should not be used. Use kmod_module_apply_filter instead. * * Given a list @input, this function filter it out with config's blacklist * and save it in @output. @@ -619,9 +628,8 @@ static const struct kmod_list *module_get_dependencies_noref(const struct kmod_m * The result is cached in @mod, so subsequent calls to this function will * return the already searched list of modules. * - * Returns: NULL on failure or if there are any dependencies. Otherwise it - * returns a list of kmod modules that can be released by calling - * kmod_module_unref_list(). + * Returns: NULL on failure. Otherwise it returns a list of kmod modules + * that can be released by calling kmod_module_unref_list(). */ KMOD_EXPORT struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod) { @@ -730,7 +738,15 @@ extern long delete_module(const char *name, unsigned int flags); /** * kmod_module_remove_module: * @mod: kmod module - * @flags: flags to pass to Linux kernel when removing the module + * @flags: flags to pass to Linux kernel when removing the module, valid flags are + * KMOD_REMOVE_FORCE: force remove module regardless if it's still in + * use by a kernel subsystem or other process; + * KMOD_REMOVE_NOWAIT: return immediately. It will fail if the module + * is in using and KMOD_REMOVE_FORCE is not specified. + * If this module is in use by any kernel subsystem or process, not using + * this flag will cause the call to block indefinitely, until the module + * is not in use anymore. Always use this flag, it's deprecated not using + * it and the default behavior might change in future to always set it. * * Remove a module from Linux kernel. * @@ -762,7 +778,9 @@ extern long init_module(const void *mem, unsigned long len, const char *args); * kmod_module_insert_module: * @mod: kmod module * @flags: flags are not passed to Linux Kernel, but instead they dictate the - * behavior of this function. + * behavior of this function, valid flags are + * KMOD_INSERT_FORCE_VERMAGIC: ignore kernel version magic; + * KMOD_INSERT_FORCE_MODVERSION: ignore symbol version hashes. * @options: module's options to pass to Linux Kernel. * * Insert a module in Linux kernel. It opens the file pointed by @mod, @@ -798,6 +816,19 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod, return err; } + if (kmod_file_get_direct(file)) { + unsigned int kernel_flags = 0; + + if (flags & KMOD_INSERT_FORCE_VERMAGIC) + kernel_flags |= MODULE_INIT_IGNORE_VERMAGIC; + if (flags & KMOD_INSERT_FORCE_MODVERSION) + kernel_flags |= MODULE_INIT_IGNORE_MODVERSIONS; + + err = finit_module(kmod_file_get_fd(file), args, kernel_flags); + if (err == 0 || errno != ENOSYS) + goto init_finished; + } + size = kmod_file_get_size(file); mem = kmod_file_get_contents(file); @@ -824,6 +855,7 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod, } err = init_module(mem, size, args); +init_finished: if (err < 0) { err = -errno; INFO(mod->ctx, "Failed to insert module '%s': %m\n", path); @@ -840,7 +872,8 @@ elf_failed: static bool module_is_blacklisted(struct kmod_module *mod) { struct kmod_ctx *ctx = mod->ctx; - const struct kmod_list *bl = kmod_get_blacklists(ctx); + const struct kmod_config *config = kmod_get_config(ctx); + const struct kmod_list *bl = config->blacklists; const struct kmod_list *l; kmod_list_foreach(l, bl) { @@ -856,7 +889,9 @@ static bool module_is_blacklisted(struct kmod_module *mod) /** * kmod_module_apply_filter * @ctx: kmod library context - * @filter_type: bitmask to filter modules on + * @filter_type: bitmask to filter modules out, valid types are + * KMOD_FILTER_BLACKLIST: filter modules in blacklist out; + * KMOD_FILTER_BUILTIN: filter builtin modules out. * @input: list of kmod_module to be filtered * @output: where to save the new list * @@ -888,8 +923,7 @@ KMOD_EXPORT int kmod_module_apply_filter(const struct kmod_ctx *ctx, module_is_blacklisted(mod)) continue; - if ((filter_type & KMOD_FILTER_BUILTIN) && - kmod_module_get_initstate(mod) == KMOD_MODULE_BUILTIN) + if ((filter_type & KMOD_FILTER_BUILTIN) && mod->builtin) continue; node = kmod_list_append(*output, mod); @@ -1128,7 +1162,25 @@ static int kmod_module_get_probe_list(struct kmod_module *mod, * kmod_module_probe_insert_module: * @mod: kmod module * @flags: flags are not passed to Linux Kernel, but instead they dictate the - * behavior of this function. + * behavior of this function, valid flags are + * KMOD_PROBE_FORCE_VERMAGIC: ignore kernel version magic; + * KMOD_PROBE_FORCE_MODVERSION: ignore symbol version hashes; + * KMOD_PROBE_IGNORE_COMMAND: whether the probe should ignore install + * commands and softdeps configured in the system; + * KMOD_PROBE_IGNORE_LOADED: do not check whether the module is already + * live in kernel or not; + * KMOD_PROBE_DRY_RUN: dry run, do not insert module, just call the + * associated callback function; + * KMOD_PROBE_FAIL_ON_LOADED: if KMOD_PROBE_IGNORE_LOADED is not specified + * and the module is already live in kernel, the function will fail if this + * flag is specified; + * KMOD_PROBE_APPLY_BLACKLIST_ALL: probe will apply KMOD_FILTER_BLACKLIST + * filter to this module and its dependencies. If any of the dependencies (or + * the module) is blacklisted, the probe will fail, unless the blacklisted + * module is already live in kernel; + * KMOD_PROBE_APPLY_BLACKLIST: probe will fail if the module is blacklisted; + * KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY: probe will fail if the module is an + * alias and is blacklisted. * @extra_options: module's options to pass to Linux Kernel. It applies only * to @mod, not to its dependencies. * @run_install: function to run when @mod is backed by an install command. @@ -1172,9 +1224,15 @@ KMOD_EXPORT int kmod_module_probe_insert_module(struct kmod_module *mod, return 0; } - err = flags & (KMOD_PROBE_APPLY_BLACKLIST | - KMOD_PROBE_APPLY_BLACKLIST_ALL); - if (err != 0) { + /* + * Ugly assignement + check. We need to check if we were told to check + * blacklist and also return the reason why we failed. + * KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY will take effect only if the + * module is an alias, so we also need to check it + */ + if ((mod->alias != NULL && ((err = flags & KMOD_PROBE_APPLY_BLACKLIST_ALIAS_ONLY))) + || (err = flags & KMOD_PROBE_APPLY_BLACKLIST_ALL) + || (err = flags & KMOD_PROBE_APPLY_BLACKLIST)) { if (module_is_blacklisted(mod)) return err; } @@ -1281,13 +1339,14 @@ KMOD_EXPORT const char *kmod_module_get_options(const struct kmod_module *mod) if (!mod->init.options) { /* lazy init */ struct kmod_module *m = (struct kmod_module *)mod; - const struct kmod_list *l, *ctx_options; + const struct kmod_list *l; + const struct kmod_config *config; char *opts = NULL; size_t optslen = 0; - ctx_options = kmod_get_options(mod->ctx); + config = kmod_get_config(mod->ctx); - kmod_list_foreach(l, ctx_options) { + kmod_list_foreach(l, config->options) { const char *modname = kmod_option_get_modname(l); const char *str; size_t len; @@ -1355,11 +1414,12 @@ KMOD_EXPORT const char *kmod_module_get_install_commands(const struct kmod_modul if (!mod->init.install_commands) { /* lazy init */ struct kmod_module *m = (struct kmod_module *)mod; - const struct kmod_list *l, *ctx_install_commands; + const struct kmod_list *l; + const struct kmod_config *config; - ctx_install_commands = kmod_get_install_commands(mod->ctx); + config = kmod_get_config(mod->ctx); - kmod_list_foreach(l, ctx_install_commands) { + kmod_list_foreach(l, config->install_commands) { const char *modname = kmod_command_get_modname(l); if (fnmatch(modname, mod->name, 0) != 0) @@ -1427,7 +1487,8 @@ KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod, struct kmod_list **pre, struct kmod_list **post) { - const struct kmod_list *l, *ctx_softdeps; + const struct kmod_list *l; + const struct kmod_config *config; if (mod == NULL || pre == NULL || post == NULL) return -ENOENT; @@ -1435,9 +1496,9 @@ KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod, assert(*pre == NULL); assert(*post == NULL); - ctx_softdeps = kmod_get_softdeps(mod->ctx); + config = kmod_get_config(mod->ctx); - kmod_list_foreach(l, ctx_softdeps) { + kmod_list_foreach(l, config->softdeps) { const char *modname = kmod_softdep_get_name(l); const char * const *array; unsigned count; @@ -1482,11 +1543,12 @@ KMOD_EXPORT const char *kmod_module_get_remove_commands(const struct kmod_module if (!mod->init.remove_commands) { /* lazy init */ struct kmod_module *m = (struct kmod_module *)mod; - const struct kmod_list *l, *ctx_remove_commands; + const struct kmod_list *l; + const struct kmod_config *config; - ctx_remove_commands = kmod_get_remove_commands(mod->ctx); + config = kmod_get_config(mod->ctx); - kmod_list_foreach(l, ctx_remove_commands) { + kmod_list_foreach(l, config->remove_commands) { const char *modname = kmod_command_get_modname(l); if (fnmatch(modname, mod->name, 0) != 0) @@ -1530,7 +1592,7 @@ void kmod_module_set_remove_commands(struct kmod_module *mod, const char *cmd) * Create a new list of kmod modules with all modules currently loaded in * kernel. It uses /proc/modules to get the names of loaded modules and to * create kmod modules by calling kmod_module_new_from_name() in each of them. - * They are put are put in @list in no particular order. + * They are put in @list in no particular order. * * The initial refcount is 1, and needs to be decremented to release the * resources of the kmod_module. The returned @list must be released by @@ -1618,7 +1680,11 @@ KMOD_EXPORT const char *kmod_module_initstate_str(enum kmod_module_initstate sta * Get the initstate of this @mod, as returned by Linux Kernel, by reading * /sys filesystem. * - * Returns: < 0 on error or enum kmod_initstate if module is found in kernel. + * Returns: < 0 on error or module state if module is found in kernel, valid states are + * KMOD_MODULE_BUILTIN: module is builtin; + * KMOD_MODULE_LIVE: module is live in kernel; + * KMOD_MODULE_COMING: module is being loaded; + * KMOD_MODULE_GOING: module is being unloaded. */ KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod) { @@ -1675,22 +1741,43 @@ KMOD_EXPORT int kmod_module_get_initstate(const struct kmod_module *mod) * kmod_module_get_size: * @mod: kmod module * - * Get the size of this kmod module as returned by Linux kernel. It reads the - * file /proc/modules to search for this module and get its size. + * Get the size of this kmod module as returned by Linux kernel. If supported, + * the size is read from the coresize attribute in /sys/module. For older + * kernels, this falls back on /proc/modules and searches for the specified + * module to get its size. * * Returns: the size of this kmod module. */ KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod) { - // FIXME TODO: this should be available from /sys/module/foo FILE *fp; char line[4096]; int lineno = 0; long size = -ENOENT; + int dfd, cfd; if (mod == NULL) return -ENOENT; + /* try to open the module dir in /sys. If this fails, don't + * bother trying to find the size as we know the module isn't + * loaded. + */ + snprintf(line, sizeof(line), "/sys/module/%s", mod->name); + dfd = open(line, O_RDONLY); + if (dfd < 0) + return -errno; + + /* available as of linux 3.3.x */ + cfd = openat(dfd, "coresize", O_RDONLY|O_CLOEXEC); + if (cfd >= 0) { + if (read_str_long(cfd, &size, 10) < 0) + ERR(mod->ctx, "failed to read coresize from %s\n", line); + close(cfd); + goto done; + } + + /* fall back on parsing /proc/modules */ fp = fopen("/proc/modules", "re"); if (fp == NULL) { int err = -errno; @@ -1725,6 +1812,9 @@ KMOD_EXPORT long kmod_module_get_size(const struct kmod_module *mod) break; } fclose(fp); + +done: + close(dfd); return size; } @@ -1750,7 +1840,7 @@ KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod) fd = open(path, O_RDONLY|O_CLOEXEC); if (fd < 0) { err = -errno; - ERR(mod->ctx, "could not open '%s': %s\n", + DBG(mod->ctx, "could not open '%s': %s\n", path, strerror(errno)); return err; } @@ -1781,7 +1871,7 @@ KMOD_EXPORT struct kmod_list *kmod_module_get_holders(const struct kmod_module * struct kmod_list *list = NULL; DIR *d; - if (mod == NULL) + if (mod == NULL || mod->ctx == NULL) return NULL; snprintf(dname, sizeof(dname), "/sys/module/%s/holders", mod->name); @@ -2009,6 +2099,25 @@ KMOD_EXPORT void kmod_module_section_free_list(struct kmod_list *list) } } +static struct kmod_elf *kmod_module_get_elf(const struct kmod_module *mod) +{ + if (mod->file == NULL) { + const char *path = kmod_module_get_path(mod); + + if (path == NULL) { + errno = ENOENT; + return NULL; + } + + ((struct kmod_module *)mod)->file = kmod_file_open(mod->ctx, + path); + if (mod->file == NULL) + return NULL; + } + + return kmod_file_get_elf(mod->file); +} + struct kmod_module_info { char *key; char value[]; @@ -2023,7 +2132,7 @@ static struct kmod_module_info *kmod_module_info_new(const char *key, size_t key return NULL; info->key = (char *)info + sizeof(struct kmod_module_info) - + valuelen + 1; + + valuelen + 1; memcpy(info->key, key, keylen); info->key[keylen] = '\0'; memcpy(info->value, value, valuelen); @@ -2036,6 +2145,22 @@ static void kmod_module_info_free(struct kmod_module_info *info) free(info); } +static struct kmod_list *kmod_module_info_append(struct kmod_list **list, const char *key, size_t keylen, const char *value, size_t valuelen) +{ + struct kmod_module_info *info; + struct kmod_list *n; + + info = kmod_module_info_new(key, keylen, value, valuelen); + if (info == NULL) + return NULL; + n = kmod_list_append(*list, info); + if (n != NULL) + *list = n; + else + kmod_module_info_free(info); + return n; +} + /** * kmod_module_get_info: * @mod: kmod module @@ -2046,7 +2171,9 @@ static void kmod_module_info_free(struct kmod_module_info *info) * * Get a list of entries in ELF section ".modinfo", these contain * alias, license, depends, vermagic and other keys with respective - * values. + * values. If the module is signed (CONFIG_MODULE_SIG), information + * about the module signature is included as well: signer, + * sig_key and sig_hashalgo. * * After use, free the @list by calling kmod_module_info_free_list(). * @@ -2054,44 +2181,25 @@ static void kmod_module_info_free(struct kmod_module_info *info) */ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_list **list) { - struct kmod_file *file; struct kmod_elf *elf; - const char *path; - const void *mem; char **strings; - size_t size; - int i, count, ret = 0; + int i, count, ret = -ENOMEM; + struct kmod_signature_info sig_info; if (mod == NULL || list == NULL) return -ENOENT; assert(*list == NULL); - path = kmod_module_get_path(mod); - if (path == NULL) - return -ENOENT; - - file = kmod_file_open(mod->ctx, path); - if (file == NULL) + elf = kmod_module_get_elf(mod); + if (elf == NULL) return -errno; - size = kmod_file_get_size(file); - mem = kmod_file_get_contents(file); - - elf = kmod_elf_new(mem, size); - if (elf == NULL) { - ret = -errno; - goto elf_open_error; - } - count = kmod_elf_get_strings(elf, ".modinfo", &strings); - if (count < 0) { - ret = count; - goto get_strings_error; - } + if (count < 0) + return count; for (i = 0; i < count; i++) { - struct kmod_module_info *info; struct kmod_list *n; const char *key, *value; size_t keylen, valuelen; @@ -2101,40 +2209,65 @@ KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_ if (value == NULL) { keylen = strlen(key); valuelen = 0; + value = key; } else { keylen = value - key; value++; valuelen = strlen(value); } - info = kmod_module_info_new(key, keylen, value, valuelen); - if (info == NULL) { - ret = -errno; - kmod_module_info_free_list(*list); - *list = NULL; + n = kmod_module_info_append(list, key, keylen, value, valuelen); + if (n == NULL) goto list_error; - } + } - n = kmod_list_append(*list, info); - if (n != NULL) - *list = n; - else { - kmod_module_info_free(info); - kmod_module_info_free_list(*list); - *list = NULL; - ret = -ENOMEM; + if (kmod_module_signature_info(mod->file, &sig_info)) { + struct kmod_list *n; + char *key_hex; + + n = kmod_module_info_append(list, "signer", strlen("signer"), + sig_info.signer, sig_info.signer_len); + if (n == NULL) + goto list_error; + count++; + + /* Display the key id as 01:12:DE:AD:BE:EF:... */ + key_hex = malloc(sig_info.key_id_len * 3); + if (key_hex == NULL) goto list_error; + for (i = 0; i < (int)sig_info.key_id_len; i++) { + sprintf(key_hex + i * 3, "%02X", + (unsigned char)sig_info.key_id[i]); + if (i < (int)sig_info.key_id_len - 1) + key_hex[i * 3 + 2] = ':'; } + n = kmod_module_info_append(list, "sig_key", strlen("sig_key"), + key_hex, sig_info.key_id_len * 3 - 1); + free(key_hex); + if (n == NULL) + goto list_error; + count++; + + n = kmod_module_info_append(list, + "sig_hashalgo", strlen("sig_hashalgo"), + sig_info.hash_algo, strlen(sig_info.hash_algo)); + if (n == NULL) + goto list_error; + count++; + + /* + * Omit sig_info.id_type and sig_info.algo for now, as these + * are currently constant. + */ } ret = count; list_error: + if (ret < 0) { + kmod_module_info_free_list(*list); + *list = NULL; + } free(strings); -get_strings_error: - kmod_elf_unref(elf); -elf_open_error: - kmod_file_unref(file); - return ret; } @@ -2232,12 +2365,8 @@ static void kmod_module_version_free(struct kmod_module_version *version) */ KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod, struct kmod_list **list) { - struct kmod_file *file; struct kmod_elf *elf; - const char *path; - const void *mem; struct kmod_modversion *versions; - size_t size; int i, count, ret = 0; if (mod == NULL || list == NULL) @@ -2245,28 +2374,13 @@ KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod, struct k assert(*list == NULL); - path = kmod_module_get_path(mod); - if (path == NULL) - return -ENOENT; - - file = kmod_file_open(mod->ctx, path); - if (file == NULL) + elf = kmod_module_get_elf(mod); + if (elf == NULL) return -errno; - size = kmod_file_get_size(file); - mem = kmod_file_get_contents(file); - - elf = kmod_elf_new(mem, size); - if (elf == NULL) { - ret = -errno; - goto elf_open_error; - } - count = kmod_elf_get_modversions(elf, &versions); - if (count < 0) { - ret = count; - goto get_strings_error; - } + if (count < 0) + return count; for (i = 0; i < count; i++) { struct kmod_module_version *mv; @@ -2295,16 +2409,11 @@ KMOD_EXPORT int kmod_module_get_versions(const struct kmod_module *mod, struct k list_error: free(versions); -get_strings_error: - kmod_elf_unref(elf); -elf_open_error: - kmod_file_unref(file); - return ret; } /** - * kmod_module_versions_get_symbol: + * kmod_module_version_get_symbol: * @entry: a list entry representing a kmod module versions * * Get the symbol of a kmod module versions. @@ -2397,12 +2506,8 @@ static void kmod_module_symbol_free(struct kmod_module_symbol *symbol) */ KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod, struct kmod_list **list) { - struct kmod_file *file; struct kmod_elf *elf; - const char *path; - const void *mem; struct kmod_modversion *symbols; - size_t size; int i, count, ret = 0; if (mod == NULL || list == NULL) @@ -2410,28 +2515,13 @@ KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod, struct km assert(*list == NULL); - path = kmod_module_get_path(mod); - if (path == NULL) - return -ENOENT; - - file = kmod_file_open(mod->ctx, path); - if (file == NULL) + elf = kmod_module_get_elf(mod); + if (elf == NULL) return -errno; - size = kmod_file_get_size(file); - mem = kmod_file_get_contents(file); - - elf = kmod_elf_new(mem, size); - if (elf == NULL) { - ret = -errno; - goto elf_open_error; - } - count = kmod_elf_get_symbols(elf, &symbols); - if (count < 0) { - ret = count; - goto get_strings_error; - } + if (count < 0) + return count; for (i = 0; i < count; i++) { struct kmod_module_symbol *mv; @@ -2460,11 +2550,6 @@ KMOD_EXPORT int kmod_module_get_symbols(const struct kmod_module *mod, struct km list_error: free(symbols); -get_strings_error: - kmod_elf_unref(elf); -elf_open_error: - kmod_file_unref(file); - return ret; } @@ -2565,12 +2650,8 @@ static void kmod_module_dependency_symbol_free(struct kmod_module_dependency_sym */ KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod, struct kmod_list **list) { - struct kmod_file *file; struct kmod_elf *elf; - const char *path; - const void *mem; struct kmod_modversion *symbols; - size_t size; int i, count, ret = 0; if (mod == NULL || list == NULL) @@ -2578,28 +2659,13 @@ KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod assert(*list == NULL); - path = kmod_module_get_path(mod); - if (path == NULL) - return -ENOENT; - - file = kmod_file_open(mod->ctx, path); - if (file == NULL) + elf = kmod_module_get_elf(mod); + if (elf == NULL) return -errno; - size = kmod_file_get_size(file); - mem = kmod_file_get_contents(file); - - elf = kmod_elf_new(mem, size); - if (elf == NULL) { - ret = -errno; - goto elf_open_error; - } - count = kmod_elf_get_dependency_symbols(elf, &symbols); - if (count < 0) { - ret = count; - goto get_strings_error; - } + if (count < 0) + return count; for (i = 0; i < count; i++) { struct kmod_module_dependency_symbol *mv; @@ -2630,11 +2696,6 @@ KMOD_EXPORT int kmod_module_get_dependency_symbols(const struct kmod_module *mod list_error: free(symbols); -get_strings_error: - kmod_elf_unref(elf); -elf_open_error: - kmod_file_unref(file); - return ret; } |