From 153da67042852b7667ce4479d14835450c908417 Mon Sep 17 00:00:00 2001
From: Michal Marek <mmarek@suse.cz>
Date: Wed, 5 Mar 2014 14:40:14 +0100
Subject: [PATCH 3/5] libkmod: Implement filtering of unsupported modules (off
 by default)

References: fate#316971
Patch-mainline: never
---
 libkmod/libkmod-config.c   | 12 ++++++++++--
 libkmod/libkmod-internal.h |  1 +
 libkmod/libkmod-module.c   | 31 +++++++++++++++++++++++++++++++
 3 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c
index 79bfb9b..9f47cfd 100644
--- a/libkmod/libkmod-config.c
+++ b/libkmod/libkmod-config.c
@@ -668,8 +668,16 @@ static int kmod_config_parse(struct kmod_config *config, int fd,
 			ERR(ctx, "%s: command %s is deprecated and not parsed anymore\n",
 								filename, cmd);
 		} else if (streq(cmd, "allow_unsupported_modules")) {
-			/* dummy option for now */
-			;
+			char *param = strtok_r(NULL, "\t ", &saveptr);
+
+			if (param == NULL)
+				goto syntax_error;
+			if (streq(param, "yes") || streq(param, "1"))
+				config->block_unsupported = 0;
+			else if (streq(param, "no") || streq(param, "0"))
+				config->block_unsupported = 1;
+			else
+				goto syntax_error;
 		} else {
 syntax_error:
 			ERR(ctx, "%s line %u: ignoring bad line starting with '%s'\n",
diff --git a/libkmod/libkmod-internal.h b/libkmod/libkmod-internal.h
index 93a00c1..3a46b6b 100644
--- a/libkmod/libkmod-internal.h
+++ b/libkmod/libkmod-internal.h
@@ -119,6 +119,7 @@ struct kmod_config {
 	struct kmod_list *softdeps;
 
 	struct kmod_list *paths;
+	int block_unsupported;
 };
 
 int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **config, const char * const *config_paths) __attribute__((nonnull(1, 2,3)));
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index e3cc5a7..3a9ce7c 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -782,6 +782,24 @@ KMOD_EXPORT int kmod_module_remove_module(struct kmod_module *mod,
 
 extern long init_module(const void *mem, unsigned long len, const char *args);
 
+static int check_module_supported(struct kmod_module *mod)
+{
+	char **strings;
+	int i, count;
+	struct kmod_elf *elf;
+
+	elf = kmod_file_get_elf(mod->file);
+	count = kmod_elf_get_strings(elf, ".modinfo", &strings);
+	if (count < 0)
+		return count;
+	for (i = 0; i < count; i++)
+		if (streq(strings[i], "supported=yes") ||
+		    streq(strings[i], "supported=external")) {
+			return 1;
+		}
+	return 0;
+}
+
 /**
  * kmod_module_insert_module:
  * @mod: kmod module
@@ -807,6 +825,7 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
 	struct kmod_elf *elf;
 	const char *path;
 	const char *args = options ? options : "";
+	const struct kmod_config *config = kmod_get_config(mod->ctx);
 
 	if (mod == NULL)
 		return -ENOENT;
@@ -823,6 +842,18 @@ KMOD_EXPORT int kmod_module_insert_module(struct kmod_module *mod,
 		return err;
 	}
 
+	if (config->block_unsupported) {
+		err = check_module_supported(mod);
+		if (err < 0)
+			return err;
+		else if (err == 0) {
+			ERR(mod->ctx, "module '%s' is unsupported\n", mod->name);
+			ERR(mod->ctx, "Use --allow-unsupported or set allow_unsupported_modules 1 in\n");
+			ERR(mod->ctx, "/etc/modprobe.d/10-unsupported-modules.conf\n");
+			return -EPERM;
+		}
+	}
+
 	if (kmod_file_get_direct(mod->file)) {
 		unsigned int kernel_flags = 0;
 
-- 
1.8.4.5