diff --git a/libkmod/docs/libkmod-sections.txt b/libkmod/docs/libkmod-sections.txt
index 33d9eec..04743e4 100644
--- a/libkmod/docs/libkmod-sections.txt
+++ b/libkmod/docs/libkmod-sections.txt
@@ -62,6 +62,7 @@ kmod_module_remove_module
 kmod_module_get_module
 kmod_module_get_dependencies
 kmod_module_get_softdeps
+kmod_module_get_user_softdeps
 kmod_module_apply_filter
 kmod_module_get_filtered_blacklist
 kmod_module_get_install_commands
diff --git a/libkmod/libkmod-config.c b/libkmod/libkmod-config.c
index e83621b..c0e15be 100644
--- a/libkmod/libkmod-config.c
+++ b/libkmod/libkmod-config.c
@@ -54,8 +54,10 @@ struct kmod_softdep {
 	char *name;
 	const char **pre;
 	const char **post;
+	const char **user;
 	unsigned int n_pre;
 	unsigned int n_post;
+	unsigned int n_user;
 };
 
 const char *kmod_blacklist_get_modname(const struct kmod_list *l)
@@ -110,6 +112,12 @@ const char * const *kmod_softdep_get_post(const struct kmod_list *l, unsigned in
 	return dep->post;
 }
 
+const char * const *kmod_softdep_get_user(const struct kmod_list *l, unsigned int *count) {
+	const struct kmod_softdep *dep = l->data;
+	*count = dep->n_user;
+	return dep->user;
+}
+
 static int kmod_config_add_command(struct kmod_config *config,
 						const char *modname,
 						const char *command,
@@ -263,11 +271,11 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 	struct kmod_softdep *dep;
 	const char *s, *p;
 	char *itr;
-	unsigned int n_pre = 0, n_post = 0;
+	unsigned int n_pre = 0, n_post = 0, n_user = 0;
 	size_t modnamelen = strlen(modname) + 1;
 	size_t buflen = 0;
 	bool was_space = false;
-	enum { S_NONE, S_PRE, S_POST } mode = S_NONE;
+	enum { S_NONE, S_PRE, S_POST, S_USER } mode = S_NONE;
 
 	DBG(config->ctx, "modname=%s\n", modname);
 
@@ -298,6 +306,9 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 		else if (plen == sizeof("post:") - 1 &&
 				memcmp(p, "post:", sizeof("post:") - 1) == 0)
 			mode = S_POST;
+		else if (plen == sizeof("user:") - 1 &&
+				memcmp(p, "user:", sizeof("user:") - 1) == 0)
+			mode = S_USER;
 		else if (*s != '\0' || (*s == '\0' && !was_space)) {
 			if (mode == S_PRE) {
 				buflen += plen + 1;
@@ -305,6 +316,9 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 			} else if (mode == S_POST) {
 				buflen += plen + 1;
 				n_post++;
+			} else if (mode == S_USER) {
+				buflen += plen + 1;
+				n_user++;
 			}
 		}
 		p = s + 1;
@@ -312,11 +326,12 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 			break;
 	}
 
-	DBG(config->ctx, "%u pre, %u post\n", n_pre, n_post);
+	DBG(config->ctx, "%u pre, %u post, %u user\n", n_pre, n_post, n_user);
 
 	dep = malloc(sizeof(struct kmod_softdep) + modnamelen +
 		     n_pre * sizeof(const char *) +
 		     n_post * sizeof(const char *) +
+		     n_user * sizeof(const char *) +
 		     buflen);
 	if (dep == NULL) {
 		ERR(config->ctx, "out-of-memory modname=%s\n", modname);
@@ -324,9 +339,11 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 	}
 	dep->n_pre = n_pre;
 	dep->n_post = n_post;
+	dep->n_user = n_user;
 	dep->pre = (const char **)((char *)dep + sizeof(struct kmod_softdep));
 	dep->post = dep->pre + n_pre;
-	dep->name = (char *)(dep->post + n_post);
+	dep->user = dep->post + n_post;
+	dep->name = (char *)(dep->user + n_user);
 
 	memcpy(dep->name, modname, modnamelen);
 
@@ -334,6 +351,7 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 	itr = dep->name + modnamelen;
 	n_pre = 0;
 	n_post = 0;
+	n_user = 0;
 	mode = S_NONE;
 	was_space = false;
 	for (p = s = line; ; s++) {
@@ -362,6 +380,9 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 		else if (plen == sizeof("post:") - 1 &&
 				memcmp(p, "post:", sizeof("post:") - 1) == 0)
 			mode = S_POST;
+		else if (plen == sizeof("user:") - 1 &&
+				memcmp(p, "user:", sizeof("user:") - 1) == 0)
+			mode = S_USER;
 		else if (*s != '\0' || (*s == '\0' && !was_space)) {
 			if (mode == S_PRE) {
 				dep->pre[n_pre] = itr;
@@ -375,6 +396,12 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 				itr[plen] = '\0';
 				itr += plen + 1;
 				n_post++;
+			} else if (mode == S_USER) {
+				dep->user[n_user] = itr;
+				memcpy(itr, p, plen);
+				itr[plen] = '\0';
+				itr += plen + 1;
+				n_user++;
 			}
 		}
 		p = s + 1;
@@ -395,14 +422,15 @@ static int kmod_config_add_softdep(struct kmod_config *config,
 static char *softdep_to_char(struct kmod_softdep *dep) {
 	const size_t sz_preprefix = sizeof("pre: ") - 1;
 	const size_t sz_postprefix = sizeof("post: ") - 1;
+	const size_t sz_userprefix = sizeof("user: ") - 1;
 	size_t sz = 1; /* at least '\0' */
-	size_t sz_pre, sz_post;
+	size_t sz_pre, sz_post, sz_user;
 	const char *start, *end;
 	char *s, *itr;
 
 	/*
-	 * Rely on the fact that dep->pre[] and dep->post[] are strv's that
-	 * point to a contiguous buffer
+	 * Rely on the fact that dep->pre[] dep->post[] and dep->user[]
+	 * are strv's that point to a contiguous buffer
 	 */
 	if (dep->n_pre > 0) {
 		start = dep->pre[0];
@@ -422,6 +450,15 @@ static char *softdep_to_char(struct kmod_softdep *dep) {
 	} else
 		sz_post = 0;
 
+	if (dep->n_user > 0) {
+		start = dep->user[0];
+		end = dep->user[dep->n_user - 1]
+					+ strlen(dep->user[dep->n_user - 1]);
+		sz_user = end - start;
+		sz += sz_user + sz_userprefix;
+	} else
+		sz_user = 0;
+
 	itr = s = malloc(sz);
 	if (s == NULL)
 		return NULL;
@@ -456,6 +493,21 @@ static char *softdep_to_char(struct kmod_softdep *dep) {
 		itr = p;
 	}
 
+	if (sz_user) {
+		char *p;
+
+		memcpy(itr, "user: ", sz_userprefix);
+		itr += sz_userprefix;
+
+		/* include last '\0' */
+		memcpy(itr, dep->user[0], sz_user + 1);
+		for (p = itr; p < itr + sz_user; p++) {
+			if (*p == '\0')
+				*p = ' ';
+		}
+		itr = p;
+	}
+
 	*itr = '\0';
 
 	return s;
diff --git a/libkmod/libkmod-internal.h b/libkmod/libkmod-internal.h
index 26a7e28..8e4f112 100644
--- a/libkmod/libkmod-internal.h
+++ b/libkmod/libkmod-internal.h
@@ -145,6 +145,7 @@ const char *kmod_command_get_modname(const struct kmod_list *l) __attribute__((n
 const char *kmod_softdep_get_name(const struct kmod_list *l) __attribute__((nonnull(1)));
 const char * const *kmod_softdep_get_pre(const struct kmod_list *l, unsigned int *count) __attribute__((nonnull(1, 2)));
 const char * const *kmod_softdep_get_post(const struct kmod_list *l, unsigned int *count);
+const char * const *kmod_softdep_get_user(const struct kmod_list *l, unsigned int *count);
 
 
 /* libkmod-module.c */
diff --git a/libkmod/libkmod-module.c b/libkmod/libkmod-module.c
index 585da41..dbe676c 100644
--- a/libkmod/libkmod-module.c
+++ b/libkmod/libkmod-module.c
@@ -1664,6 +1664,56 @@ KMOD_EXPORT int kmod_module_get_softdeps(const struct kmod_module *mod,
 	return 0;
 }
 
+/**
+ * kmod_module_get_user_softdeps:
+ * @mod: kmod module
+ * @user: where to save the list of user soft dependencies.
+ *
+ * Get user dependencies for this kmod module. Soft dependencies come
+ * from configuration file and are not cached in @mod because it may include
+ * dependency cycles that would make we leak kmod_module. Any call
+ * to this function will search for this module in configuration, allocate a
+ * list and return the result.
+ *
+ * @user is newly created list of kmod_module and
+ * should be unreferenced with kmod_module_unref_list().
+ *
+ * Returns: 0 on success or < 0 otherwise.
+ */
+KMOD_EXPORT int kmod_module_get_user_softdeps(const struct kmod_module *mod,
+						struct kmod_list **user)
+{
+	const struct kmod_list *l;
+	const struct kmod_config *config;
+
+	if (mod == NULL || user == NULL)
+		return -ENOENT;
+
+	assert(*user == NULL);
+
+	config = kmod_get_config(mod->ctx);
+
+	kmod_list_foreach(l, config->softdeps) {
+		const char *modname = kmod_softdep_get_name(l);
+		const char * const *array;
+		unsigned count;
+
+		if (fnmatch(modname, mod->name, 0) != 0)
+			continue;
+
+		array = kmod_softdep_get_user(l, &count);
+		*user = lookup_softdep(mod->ctx, array, count);
+
+		/*
+		 * find only the first command, as modprobe from
+		 * module-init-tools does
+		 */
+		break;
+	}
+
+	return 0;
+}
+
 /**
  * kmod_module_get_remove_commands:
  * @mod: kmod module
diff --git a/libkmod/libkmod.h b/libkmod/libkmod.h
index 7251aa7..ec6d270 100644
--- a/libkmod/libkmod.h
+++ b/libkmod/libkmod.h
@@ -196,6 +196,8 @@ const char *kmod_module_get_remove_commands(const struct kmod_module *mod);
 struct kmod_list *kmod_module_get_dependencies(const struct kmod_module *mod);
 int kmod_module_get_softdeps(const struct kmod_module *mod,
 				struct kmod_list **pre, struct kmod_list **post);
+int kmod_module_get_user_softdeps(const struct kmod_module *mod,
+					struct kmod_list **user);
 int kmod_module_get_filtered_blacklist(const struct kmod_ctx *ctx,
 					const struct kmod_list *input,
 					struct kmod_list **output) __attribute__ ((deprecated));
diff --git a/libkmod/libkmod.sym b/libkmod/libkmod.sym
index 0c04fda..26c3eef 100644
--- a/libkmod/libkmod.sym
+++ b/libkmod/libkmod.sym
@@ -42,6 +42,7 @@ global:
 
 	kmod_module_get_dependencies;
 	kmod_module_get_softdeps;
+	kmod_module_get_user_softdeps;
 	kmod_module_get_filtered_blacklist;
 
 	kmod_module_get_name;
