* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdarg.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fnmatch.h>
#include <inttypes.h>
#include <limits.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
#include <sys/mman.h>
+#include <sys/stat.h>
#include <sys/syscall.h>
+#include <sys/types.h>
#include <sys/wait.h>
-#include <string.h>
-#include <fnmatch.h>
-
#ifdef HAVE_LINUX_MODULE_H
#include <linux/module.h>
#endif
+#include <shared/util.h>
+
#include "libkmod.h"
#include "libkmod-internal.h"
* @short_description: operate on kernel modules
*/
+enum kmod_module_builtin {
+ KMOD_MODULE_BUILTIN_UNKNOWN,
+ KMOD_MODULE_BUILTIN_NO,
+ KMOD_MODULE_BUILTIN_YES,
+};
+
/**
* kmod_module:
*
bool remove_commands : 1;
} init;
+ /*
+ * mark if module is builtin, i.e. it's present on modules.builtin
+ * file. This is set as soon as it is needed or as soon as we know
+ * about it, i.e. the module was created from builtin lookup.
+ */
+ enum kmod_module_builtin builtin;
+
/*
* private field used by kmod_module_get_probe_list() to detect
* dependency loops
bool ignorecmd : 1;
/*
- * if module was created by searching the modules.builtin file, this
- * is set. There's nothing much useful one can do with such a
- * "module", except knowing it's builtin.
+ * set by kmod_module_get_probe_list: indicates whether this is the
+ * module the user asked for or its dependency, or whether this
+ * is a softdep only
*/
- bool builtin : 1;
+ bool required : 1;
};
static inline const char *path_join(const char *path, size_t prefixlen,
p++;
for (p = strtok_r(p, " \t", &saveptr); p != NULL;
p = strtok_r(NULL, " \t", &saveptr)) {
- struct kmod_module *depmod;
+ struct kmod_module *depmod = NULL;
const char *path;
path = path_join(p, dirnamelen, buf);
void kmod_module_set_builtin(struct kmod_module *mod, bool builtin)
{
- mod->builtin = builtin;
+ mod->builtin =
+ builtin ? KMOD_MODULE_BUILTIN_YES : KMOD_MODULE_BUILTIN_NO;
}
+void kmod_module_set_required(struct kmod_module *mod, bool required)
+{
+ mod->required = required;
+}
+
+bool kmod_module_is_builtin(struct kmod_module *mod)
+{
+ if (mod->builtin == KMOD_MODULE_BUILTIN_UNKNOWN) {
+ kmod_module_set_builtin(mod,
+ kmod_lookup_alias_is_builtin(mod->ctx, mod->name));
+ }
+
+ return mod->builtin == KMOD_MODULE_BUILTIN_YES;
+}
/*
* Memory layout with alias:
*
keylen = namelen + aliaslen + 1;
m = malloc(sizeof(*m) + (alias == NULL ? 1 : 2) * (keylen + 1));
- if (m == NULL) {
- free(m);
+ if (m == NULL)
return -ENOMEM;
- }
memset(m, 0, sizeof(*m));
return -EEXIST;
}
- *mod = kmod_module_ref(m);
- return 0;
- }
+ kmod_module_ref(m);
+ } else {
+ err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m);
+ if (err < 0) {
+ free(abspath);
+ return err;
+ }
- err = kmod_module_new(ctx, name, name, namelen, NULL, 0, &m);
- if (err < 0)
- return err;
+ m->path = abspath;
+ }
- m->path = abspath;
+ m->builtin = KMOD_MODULE_BUILTIN_NO;
*mod = m;
return 0;
return mod;
}
-#define CHECK_ERR_AND_FINISH(_err, _label_err, _list, label_finish) \
- do { \
- if ((_err) < 0) \
- goto _label_err; \
- if (*(_list) != NULL) \
- goto finish; \
- } while (0)
+typedef int (*lookup_func)(struct kmod_ctx *ctx, const char *name, struct kmod_list **list) __attribute__((nonnull(1, 2, 3)));
+
+static int __kmod_module_new_from_lookup(struct kmod_ctx *ctx, const lookup_func lookup[],
+ size_t lookup_count, const char *s,
+ struct kmod_list **list)
+{
+ unsigned int i;
+
+ for (i = 0; i < lookup_count; i++) {
+ int err;
+
+ err = lookup[i](ctx, s, list);
+ if (err < 0 && err != -ENOSYS)
+ return err;
+ else if (*list != NULL)
+ return 0;
+ }
+
+ return 0;
+}
/**
* kmod_module_new_from_lookup:
*
* The search order is: 1. aliases in configuration file; 2. module names in
* modules.dep index; 3. symbol aliases in modules.symbols index; 4. aliases
- * in modules.alias index.
+ * from install commands; 5. builtin indexes from kernel.
*
* 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
const char *given_alias,
struct kmod_list **list)
{
- int err;
+ static const lookup_func lookup[] = {
+ kmod_lookup_alias_from_config,
+ kmod_lookup_alias_from_moddep_file,
+ kmod_lookup_alias_from_symbols_file,
+ kmod_lookup_alias_from_commands,
+ kmod_lookup_alias_from_aliases_file,
+ kmod_lookup_alias_from_builtin_file,
+ kmod_lookup_alias_from_kernel_builtin_file,
+ };
char alias[PATH_MAX];
+ int err;
if (ctx == NULL || given_alias == NULL)
return -ENOENT;
DBG(ctx, "input alias=%s, normalized=%s\n", given_alias, alias);
- /* Aliases from config file override all the others */
- err = kmod_lookup_alias_from_config(ctx, alias, list);
- CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup),
+ alias, list);
+
+ DBG(ctx, "lookup=%s found=%d\n", alias, err >= 0 && *list);
+
+ if (err < 0) {
+ kmod_module_unref_list(*list);
+ *list = NULL;
+ }
+
+ return err;
+}
+
+/**
+ * kmod_module_new_from_name_lookup:
+ * @ctx: kmod library context
+ * @modname: module name to look for
+ * @mod: returned module on success
+ *
+ * Lookup by module name, without considering possible aliases. This is similar
+ * to kmod_module_new_from_lookup(), but don't consider as source indexes and
+ * configurations that work with aliases. When succesful, this always resolves
+ * to one and only one module.
+ *
+ * The search order is: 1. module names in modules.dep index;
+ * 2. builtin indexes from kernel.
+ *
+ * The initial refcount is 1, and needs to be decremented to release the
+ * resources of the kmod_module. Since libkmod keeps track of all
+ * kmod_modules created, they are all released upon @ctx destruction too. Do
+ * not unref @ctx before all the desired operations with the returned list are
+ * completed.
+ *
+ * Returns: 0 on success or < 0 otherwise. It fails if any of the lookup
+ * methods failed, which is basically due to memory allocation failure. If
+ * module is not found, it still returns 0, but @mod is left untouched.
+ */
+KMOD_EXPORT int kmod_module_new_from_name_lookup(struct kmod_ctx *ctx,
+ const char *modname,
+ struct kmod_module **mod)
+{
+ static const lookup_func lookup[] = {
+ kmod_lookup_alias_from_moddep_file,
+ kmod_lookup_alias_from_builtin_file,
+ kmod_lookup_alias_from_kernel_builtin_file,
+ };
+ char name_norm[PATH_MAX];
+ struct kmod_list *list = NULL;
+ int err;
- DBG(ctx, "lookup modules.dep %s\n", alias);
- err = kmod_lookup_alias_from_moddep_file(ctx, alias, list);
- CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ if (ctx == NULL || modname == NULL || mod == NULL)
+ return -ENOENT;
- DBG(ctx, "lookup modules.symbols %s\n", alias);
- err = kmod_lookup_alias_from_symbols_file(ctx, alias, list);
- CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ modname_normalize(modname, name_norm, NULL);
- DBG(ctx, "lookup install and remove commands %s\n", alias);
- err = kmod_lookup_alias_from_commands(ctx, alias, list);
- CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ DBG(ctx, "input modname=%s, normalized=%s\n", modname, name_norm);
- DBG(ctx, "lookup modules.aliases %s\n", alias);
- err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
- CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ err = __kmod_module_new_from_lookup(ctx, lookup, ARRAY_SIZE(lookup),
+ name_norm, &list);
- DBG(ctx, "lookup modules.builtin %s\n", alias);
- err = kmod_lookup_alias_from_builtin_file(ctx, alias, list);
- CHECK_ERR_AND_FINISH(err, fail, list, finish);
+ DBG(ctx, "lookup=%s found=%d\n", name_norm, err >= 0 && list);
+
+ if (err >= 0 && list != NULL)
+ *mod = kmod_module_get_module(list);
+
+ kmod_module_unref_list(list);
-finish:
- DBG(ctx, "lookup %s=%d, list=%p\n", alias, err, *list);
- return err;
-fail:
- DBG(ctx, "Failed to lookup %s\n", alias);
- kmod_module_unref_list(*list);
- *list = NULL;
return err;
}
-#undef CHECK_ERR_AND_FINISH
/**
* kmod_module_unref_list:
/**
* kmod_module_remove_module:
* @mod: kmod module
- * @flags: flags to pass to Linux kernel when removing the module. The only valid flag is
+ * @flags: flags used when removing the module.
* KMOD_REMOVE_FORCE: force remove module regardless if it's still in
- * use by a kernel subsystem or other process;
- * KMOD_REMOVE_NOWAIT is always enforced, causing us to pass O_NONBLOCK to
+ * use by a kernel subsystem or other process; passed directly to Linux kernel
+ * KMOD_REMOVE_NOWAIT: is always enforced, causing us to pass O_NONBLOCK to
* delete_module(2).
+ * KMOD_REMOVE_NOLOG: when module removal fails, do not log anything as the
+ * caller may want to handle retries and log when appropriate.
*
* Remove a module from Linux kernel.
*
KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
unsigned int flags)
{
+ unsigned int libkmod_flags = flags & 0xff;
+
int err;
if (mod == NULL)
err = delete_module(mod->name, flags);
if (err != 0) {
err = -errno;
- ERR(mod->ctx, "could not remove '%s': %m\n", mod->name);
+ if (!(libkmod_flags & KMOD_REMOVE_NOLOG))
+ ERR(mod->ctx, "could not remove '%s': %m\n", mod->name);
}
return err;
int err;
const void *mem;
off_t size;
- struct kmod_file *file;
- struct kmod_elf *elf = NULL;
+ struct kmod_elf *elf;
const char *path;
const char *args = options ? options : "";
path = kmod_module_get_path(mod);
if (path == NULL) {
ERR(mod->ctx, "could not find module by name='%s'\n", mod->name);
- return -ENOSYS;
+ return -ENOENT;
}
- file = kmod_file_open(mod->ctx, path);
- if (file == NULL) {
- err = -errno;
- return err;
+ if (!mod->file) {
+ mod->file = kmod_file_open(mod->ctx, path);
+ if (mod->file == NULL) {
+ err = -errno;
+ return err;
+ }
}
- if (kmod_file_get_direct(file)) {
+ if (kmod_file_get_direct(mod->file)) {
unsigned int kernel_flags = 0;
if (flags & KMOD_INSERT_FORCE_VERMAGIC)
if (flags & KMOD_INSERT_FORCE_MODVERSION)
kernel_flags |= MODULE_INIT_IGNORE_MODVERSIONS;
- err = finit_module(kmod_file_get_fd(file), args, kernel_flags);
+ err = finit_module(kmod_file_get_fd(mod->file), args, kernel_flags);
if (err == 0 || errno != ENOSYS)
goto init_finished;
}
- size = kmod_file_get_size(file);
- mem = kmod_file_get_contents(file);
+ kmod_file_load_contents(mod->file);
if (flags & (KMOD_INSERT_FORCE_VERMAGIC | KMOD_INSERT_FORCE_MODVERSION)) {
- elf = kmod_elf_new(mem, size);
+ elf = kmod_file_get_elf(mod->file);
if (elf == NULL) {
err = -errno;
- goto elf_failed;
+ return err;
}
if (flags & KMOD_INSERT_FORCE_MODVERSION) {
}
mem = kmod_elf_get_memory(elf);
+ } else {
+ mem = kmod_file_get_contents(mod->file);
}
+ size = kmod_file_get_size(mod->file);
err = init_module(mem, size, args);
init_finished:
err = -errno;
INFO(mod->ctx, "Failed to insert module '%s': %m\n", path);
}
-
- if (elf != NULL)
- kmod_elf_unref(elf);
-elf_failed:
- kmod_file_unref(file);
-
return err;
}
module_is_blacklisted(mod))
continue;
- if ((filter_type & KMOD_FILTER_BUILTIN) && mod->builtin)
+ if ((filter_type & KMOD_FILTER_BUILTIN)
+ && kmod_module_is_builtin(mod))
continue;
node = kmod_list_append(*output, mod);
err = system(cmd);
unsetenv("MODPROBE_MODULE");
- if (err == -1 || WEXITSTATUS(err)) {
- ERR(mod->ctx, "Error running %s command for %s\n",
- type, modname);
- if (err != -1)
- err = -WEXITSTATUS(err);
+ if (err == -1) {
+ ERR(mod->ctx, "Could not run %s command '%s' for module %s: %m\n",
+ type, cmd, modname);
+ return -EINVAL;
}
- return err;
+ if (WEXITSTATUS(err)) {
+ ERR(mod->ctx, "Error running %s command '%s' for module %s: retcode %d\n",
+ type, cmd, modname, WEXITSTATUS(err));
+ return -EINVAL;
+ }
+
+ return 0;
}
struct probe_insert_cb {
struct probe_insert_cb *cb)
{
const char *command = kmod_module_get_install_commands(mod);
- char *p, *cmd;
+ char *p;
+ _cleanup_free_ char *cmd;
int err;
size_t cmdlen, options_len, varlen;
size_t slen = cmdlen - varlen + options_len;
char *suffix = p + varlen;
char *s = malloc(slen + 1);
- if (s == NULL) {
- free(cmd);
+ if (!s)
return -ENOMEM;
- }
+
memcpy(s, cmd, p - cmd);
memcpy(s + prefixlen, options, options_len);
memcpy(s + prefixlen + options_len, suffix, suffixlen);
else
err = command_do(mod, "install", cmd);
- free(cmd);
-
return err;
}
}
static int __kmod_module_get_probe_list(struct kmod_module *mod,
+ bool required,
bool ignorecmd,
struct kmod_list **list);
kmod_list_foreach(l, pre) {
struct kmod_module *m = l->data;
- err = __kmod_module_get_probe_list(m, false, list);
+ err = __kmod_module_get_probe_list(m, false, false, list);
if (err < 0)
goto fail;
}
kmod_list_foreach(l, post) {
struct kmod_module *m = l->data;
- err = __kmod_module_get_probe_list(m, false, list);
+ err = __kmod_module_get_probe_list(m, false, false, list);
if (err < 0)
goto fail;
}
/* re-entrant */
static int __kmod_module_get_probe_list(struct kmod_module *mod,
+ bool required,
bool ignorecmd,
struct kmod_list **list)
{
mod->visited = true;
dep = kmod_module_get_dependencies(mod);
+ if (required) {
+ /*
+ * Called from kmod_module_probe_insert_module(); set the
+ * ->required flag on mod and all its dependencies before
+ * they are possibly visited through some softdeps.
+ */
+ mod->required = true;
+ kmod_list_foreach(l, dep) {
+ struct kmod_module *m = l->data;
+ m->required = true;
+ }
+ }
+
kmod_list_foreach(l, dep) {
struct kmod_module *m = l->data;
err = __kmod_module_fill_softdep(m, list);
* Make sure we don't get screwed by previous calls to this function
*/
kmod_set_modules_visited(mod->ctx, false);
+ kmod_set_modules_required(mod->ctx, false);
- err = __kmod_module_get_probe_list(mod, ignorecmd, list);
+ err = __kmod_module_get_probe_list(mod, true, ignorecmd, list);
if (err < 0) {
kmod_module_unref_list(*list);
*list = NULL;
(flags & KMOD_PROBE_FAIL_ON_LOADED))
break;
- if (err == -EEXIST)
+ /*
+ * Ignore errors from softdeps
+ */
+ if (err == -EEXIST || !m->required)
err = 0;
+
else if (err < 0)
break;
}
struct kmod_module *m;
struct kmod_list *node;
int err;
+ size_t len = strlen(line);
char *saveptr, *name = strtok_r(line, " \t", &saveptr);
err = kmod_module_new_from_name(ctx, name, &m);
if (err < 0) {
ERR(ctx, "could not get module from name '%s': %s\n",
name, strerror(-err));
- continue;
+ goto eat_line;
}
node = kmod_list_append(l, m);
ERR(ctx, "out of memory\n");
kmod_module_unref(m);
}
+eat_line:
+ while (line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
+ len = strlen(line);
}
fclose(fp);
if (mod == NULL)
return -ENOENT;
- if (mod->builtin)
+ /* remove const: this can only change internal state */
+ if (kmod_module_is_builtin((struct kmod_module *)mod))
return KMOD_MODULE_BUILTIN;
pathlen = snprintf(path, sizeof(path),
"/sys/module/%s/initstate", mod->name);
+ if (pathlen >= (int)sizeof(path)) {
+ /* Too long path was truncated */
+ return -ENAMETOOLONG;
+ }
fd = open(path, O_RDONLY|O_CLOEXEC);
if (fd < 0) {
err = -errno;
struct stat st;
path[pathlen - (sizeof("/initstate") - 1)] = '\0';
if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
- return KMOD_MODULE_BUILTIN;
+ return KMOD_MODULE_COMING;
}
DBG(mod->ctx, "could not open '%s': %s\n",
* loaded.
*/
snprintf(line, sizeof(line), "/sys/module/%s", mod->name);
- dfd = open(line, O_RDONLY);
+ dfd = open(line, O_RDONLY|O_CLOEXEC);
if (dfd < 0)
return -errno;
int err = -errno;
ERR(mod->ctx,
"could not open /proc/modules: %s\n", strerror(errno));
+ close(dfd);
return err;
}
while (fgets(line, sizeof(line), fp)) {
+ size_t len = strlen(line);
char *saveptr, *endptr, *tok = strtok_r(line, " \t", &saveptr);
long value;
lineno++;
if (tok == NULL || !streq(tok, mod->name))
- continue;
+ goto eat_line;
tok = strtok_r(NULL, " \t", &saveptr);
if (tok == NULL) {
size = value;
break;
+eat_line:
+ while (line[len - 1] != '\n' && fgets(line, sizeof(line), fp))
+ len = strlen(line);
}
fclose(fp);
* Get the ref count of this @mod, as returned by Linux Kernel, by reading
* /sys filesystem.
*
- * Returns: 0 on success or < 0 on failure.
+ * Returns: the reference count on success or < 0 on failure.
*/
KMOD_EXPORT int kmod_module_get_refcnt(const struct kmod_module *mod)
{
return n;
}
+static char *kmod_module_hex_to_str(const char *hex, size_t len)
+{
+ char *str;
+ int i;
+ int j;
+ const size_t line_limit = 20;
+ size_t str_len;
+
+ str_len = len * 3; /* XX: or XX\0 */
+ str_len += ((str_len + line_limit - 1) / line_limit - 1) * 3; /* \n\t\t */
+
+ str = malloc(str_len);
+ if (str == NULL)
+ return NULL;
+
+ for (i = 0, j = 0; i < (int)len; i++) {
+ j += sprintf(str + j, "%02X", (unsigned char)hex[i]);
+ if (i < (int)len - 1) {
+ str[j++] = ':';
+
+ if ((i + 1) % line_limit == 0)
+ j += sprintf(str + j, "\n\t\t");
+ }
+ }
+ return str;
+}
+
+static struct kmod_list *kmod_module_info_append_hex(struct kmod_list **list,
+ const char *key,
+ size_t keylen,
+ const char *value,
+ size_t valuelen)
+{
+ char *hex;
+ struct kmod_list *n;
+
+ if (valuelen > 0) {
+ /* Display as 01:12:DE:AD:BE:EF:... */
+ hex = kmod_module_hex_to_str(value, valuelen);
+ if (hex == NULL)
+ goto list_error;
+ n = kmod_module_info_append(list, key, keylen, hex, strlen(hex));
+ free(hex);
+ if (n == NULL)
+ goto list_error;
+ } else {
+ n = kmod_module_info_append(list, key, keylen, NULL, 0);
+ if (n == NULL)
+ goto list_error;
+ }
+
+ return n;
+
+list_error:
+ return NULL;
+}
+
/**
* kmod_module_get_info:
* @mod: kmod module
*
* After use, free the @list by calling kmod_module_info_free_list().
*
- * Returns: 0 on success or < 0 otherwise.
+ * Returns: number of entries in @list on success or < 0 otherwise.
*/
KMOD_EXPORT int kmod_module_get_info(const struct kmod_module *mod, struct kmod_list **list)
{
struct kmod_elf *elf;
char **strings;
int i, count, ret = -ENOMEM;
- struct kmod_signature_info sig_info;
+ struct kmod_signature_info sig_info = {};
if (mod == NULL || list == NULL)
return -ENOENT;
assert(*list == NULL);
- elf = kmod_module_get_elf(mod);
- if (elf == NULL)
- return -errno;
+ /* remove const: this can only change internal state */
+ if (kmod_module_is_builtin((struct kmod_module *)mod)) {
+ count = kmod_builtin_get_modinfo(mod->ctx,
+ kmod_module_get_name(mod),
+ &strings);
+ if (count < 0)
+ return count;
+ } else {
+ elf = kmod_module_get_elf(mod);
+ if (elf == NULL)
+ return -errno;
- count = kmod_elf_get_strings(elf, ".modinfo", &strings);
- if (count < 0)
- return count;
+ count = kmod_elf_get_strings(elf, ".modinfo", &strings);
+ if (count < 0)
+ return count;
+ }
for (i = 0; i < count; i++) {
struct kmod_list *n;
goto list_error;
}
- if (kmod_module_signature_info(mod->file, &sig_info)) {
+ if (mod->file && kmod_module_signature_info(mod->file, &sig_info)) {
struct kmod_list *n;
- char *key_hex;
+
+ n = kmod_module_info_append(list, "sig_id", strlen("sig_id"),
+ sig_info.id_type, strlen(sig_info.id_type));
+ if (n == NULL)
+ goto list_error;
+ count++;
n = kmod_module_info_append(list, "signer", strlen("signer"),
sig_info.signer, sig_info.signer_len);
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);
+
+ n = kmod_module_info_append_hex(list, "sig_key", strlen("sig_key"),
+ sig_info.key_id,
+ sig_info.key_id_len);
if (n == NULL)
goto list_error;
count++;
count++;
/*
- * Omit sig_info.id_type and sig_info.algo for now, as these
+ * Omit sig_info.algo for now, as these
* are currently constant.
*/
+ n = kmod_module_info_append_hex(list, "signature",
+ strlen("signature"),
+ sig_info.sig,
+ sig_info.sig_len);
+
+ if (n == NULL)
+ goto list_error;
+ count++;
+
}
ret = count;
list_error:
+ /* aux structures freed in normal case also */
+ kmod_module_signature_info_free(&sig_info);
+
if (ret < 0) {
kmod_module_info_free_list(*list);
*list = NULL;
{
struct kmod_module_version *version;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return NULL;
version = entry->data;
*
* Get the crc of a kmod module version.
*
- * Returns: the crc of this kmod module version on success or NULL on
- * failure. The string is owned by the version, do not free it.
+ * Returns: the crc of this kmod module version if available, otherwise default to 0.
*/
KMOD_EXPORT uint64_t kmod_module_version_get_crc(const struct kmod_list *entry)
{
struct kmod_module_version *version;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return 0;
version = entry->data;
{
struct kmod_module_symbol *symbol;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return NULL;
symbol = entry->data;
*
* Get the crc of a kmod module symbol.
*
- * Returns: the crc of this kmod module symbol on success or NULL on
- * failure. The string is owned by the symbol, do not free it.
+ * Returns: the crc of this kmod module symbol if available, otherwise default to 0.
*/
KMOD_EXPORT uint64_t kmod_module_symbol_get_crc(const struct kmod_list *entry)
{
struct kmod_module_symbol *symbol;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return 0;
symbol = entry->data;
{
struct kmod_module_dependency_symbol *dependency_symbol;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return NULL;
dependency_symbol = entry->data;
*
* Get the crc of a kmod module dependency_symbol.
*
- * Returns: the crc of this kmod module dependency_symbol on success or NULL on
- * failure. The string is owned by the dependency_symbol, do not free it.
+ * Returns: the crc of this kmod module dependency_symbol if available, otherwise default to 0.
*/
KMOD_EXPORT uint64_t kmod_module_dependency_symbol_get_crc(const struct kmod_list *entry)
{
struct kmod_module_dependency_symbol *dependency_symbol;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return 0;
dependency_symbol = entry->data;
{
struct kmod_module_dependency_symbol *dependency_symbol;
- if (entry == NULL)
+ if (entry == NULL || entry->data == NULL)
return 0;
dependency_symbol = entry->data;