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) {
- free(abspath);
- return err;
+ m->path = abspath;
}
- m->path = abspath;
+ m->builtin = KMOD_MODULE_BUILTIN_NO;
*mod = m;
return 0;
err = kmod_lookup_alias_from_aliases_file(ctx, alias, list);
CHECK_ERR_AND_FINISH(err, fail, list, finish);
- DBG(ctx, "lookup modules.builtin %s\n", alias);
- err = kmod_lookup_alias_from_builtin_file(ctx, alias, list);
+ DBG(ctx, "lookup modules.builtin.modinfo %s\n", alias);
+ err = kmod_lookup_alias_from_kernel_builtin_file(ctx, alias, list);
+ if (err == -ENOSYS) {
+ /* Optional index missing, try the old one */
+ 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);
+
finish:
DBG(ctx, "lookup %s=%d, list=%p\n", alias, err, *list);
return err;
return -ENOENT;
}
- mod->file = kmod_file_open(mod->ctx, path);
- if (mod->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(mod->file)) {
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 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);
}
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);
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;
list = kmod_list_remove(list);
}
}
+
+/**
+ * kmod_module_get_builtin:
+ * @ctx: kmod library context
+ * @list: where to save the builtin module list
+ *
+ * Returns: 0 on success or < 0 otherwise.
+ */
+int kmod_module_get_builtin(struct kmod_ctx *ctx, struct kmod_list **list)
+{
+ struct kmod_builtin_iter *iter;
+ int err = 0;
+
+ iter = kmod_builtin_iter_new(ctx);
+ if (!iter)
+ return -errno;
+
+ while (kmod_builtin_iter_next(iter)) {
+ struct kmod_module *mod = NULL;
+ char modname[PATH_MAX];
+
+ if (!kmod_builtin_iter_get_modname(iter, modname)) {
+ err = -errno;
+ goto fail;
+ }
+
+ err = kmod_module_new_from_name(ctx, modname, &mod);
+ if (err < 0)
+ goto fail;
+
+ kmod_module_set_builtin(mod, true);
+
+ *list = kmod_list_append(*list, mod);
+ }
+
+ kmod_builtin_iter_free(iter);
+ return err;
+fail:
+ kmod_builtin_iter_free(iter);
+ kmod_module_unref_list(*list);
+ *list = NULL;
+ return err;
+}