[PATCH v5 02/12] dns_resolver: Move the key type into a separate module
Jarkko Sakkinen
jarkko at kernel.org
Sun Nov 8 14:27:08 PST 2026
Once keys pin to the kernel module of their key type, having the DNS key
type in the same modules as the resolver will introduce a circular
dependency preventing module_exit() from ever running.
Introduce dns_resolver_key.ko containing key_type_dns_resolver. On a module
exit, drop the credentials and call key_gc_flush() in order the drain the
remaining RCU callbacks.
Signed-off-by: Jarkko Sakkinen <jarkko at kernel.org>
---
net/Makefile | 2 +-
net/dns_resolver/Kconfig | 15 +++++++++
net/dns_resolver/Makefile | 4 ++-
net/dns_resolver/dns_key.c | 65 +++++-------------------------------
net/dns_resolver/dns_query.c | 64 +++++++++++++++++++++++++++++++++++
net/dns_resolver/internal.h | 5 ---
6 files changed, 92 insertions(+), 63 deletions(-)
diff --git a/net/Makefile b/net/Makefile
index 5b2dd7f07a85..69c16a7851b4 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -55,7 +55,7 @@ obj-$(CONFIG_IEEE802154) += ieee802154/
obj-$(CONFIG_MAC802154) += mac802154/
obj-$(CONFIG_SYSCTL) += sysctl_net.o
-obj-$(CONFIG_DNS_RESOLVER) += dns_resolver/
+obj-$(CONFIG_DNS_KEY) += dns_resolver/
obj-$(CONFIG_CEPH_LIB) += ceph/
obj-$(CONFIG_BATMAN_ADV) += batman-adv/
obj-$(CONFIG_NFC) += nfc/
diff --git a/net/dns_resolver/Kconfig b/net/dns_resolver/Kconfig
index 7c2dba273e35..2618bad2e771 100644
--- a/net/dns_resolver/Kconfig
+++ b/net/dns_resolver/Kconfig
@@ -1,10 +1,25 @@
# SPDX-License-Identifier: GPL-2.0-only
+
+#
+# Configuration for DNS Resolver key type
+#
+config DNS_KEY
+ tristate "DNS Resolver key type"
+ depends on KEYS
+ help
+ Support the key type used to cache DNS lookups independently of
+ the in-kernel DNS query service.
+
+ To compile this as a module, choose M here: the module is called
+ dns_resolver_key.
+
#
# Configuration for DNS Resolver
#
config DNS_RESOLVER
tristate "DNS Resolver support"
depends on KEYS
+ select DNS_KEY
help
Saying Y here will include support for the DNS Resolver key type
which can be used to make upcalls to perform DNS lookups in
diff --git a/net/dns_resolver/Makefile b/net/dns_resolver/Makefile
index 877532d662d0..586e4c6514de 100644
--- a/net/dns_resolver/Makefile
+++ b/net/dns_resolver/Makefile
@@ -3,6 +3,8 @@
# Makefile for the Linux DNS Resolver.
#
+obj-$(CONFIG_DNS_KEY) += dns_resolver_key.o
obj-$(CONFIG_DNS_RESOLVER) += dns_resolver.o
-dns_resolver-y := dns_key.o dns_query.o
+dns_resolver-y := dns_query.o
+dns_resolver_key-y := dns_key.o
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index 451247864a63..fecbdc1d6beb 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -9,8 +9,8 @@
* Wang Lei (wang840925 at gmail.com)
* David Howells (dhowells at redhat.com)
*/
+
#include <linux/module.h>
-#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/kernel.h>
@@ -22,15 +22,12 @@
#include <keys/user-type.h>
#include "internal.h"
-MODULE_DESCRIPTION("DNS Resolver");
+MODULE_DESCRIPTION("DNS Resolver key type");
MODULE_AUTHOR("Wang Lei");
MODULE_LICENSE("GPL");
unsigned int dns_resolver_debug;
-module_param_named(debug, dns_resolver_debug, uint, 0644);
-MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");
-
-const struct cred *dns_resolver_cache;
+EXPORT_SYMBOL_GPL(dns_resolver_debug);
#define DNS_ERRORNO_OPTION "dnserror"
@@ -318,61 +315,17 @@ struct key_type key_type_dns_resolver = {
.describe = dns_resolver_describe,
.read = dns_resolver_read,
};
+EXPORT_SYMBOL_GPL(key_type_dns_resolver);
-static int __init init_dns_resolver(void)
+static int __init init_dns_key(void)
{
- struct cred *cred;
- struct key *keyring;
- int ret;
-
- /* create an override credential set with a special thread keyring in
- * which DNS requests are cached
- *
- * this is used to prevent malicious redirections from being installed
- * with add_key().
- */
- cred = prepare_kernel_cred(&init_task);
- if (!cred)
- return -ENOMEM;
-
- keyring = keyring_alloc(".dns_resolver",
- GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
- (KEY_POS_ALL & ~KEY_POS_SETATTR) |
- KEY_USR_VIEW | KEY_USR_READ,
- KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
- if (IS_ERR(keyring)) {
- ret = PTR_ERR(keyring);
- goto failed_put_cred;
- }
-
- ret = register_key_type(&key_type_dns_resolver);
- if (ret < 0)
- goto failed_put_key;
-
- /* instruct request_key() to use this special keyring as a cache for
- * the results it looks up */
- set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
- cred->thread_keyring = keyring;
- cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
- dns_resolver_cache = cred;
-
- kdebug("DNS resolver keyring: %d\n", key_serial(keyring));
- return 0;
-
-failed_put_key:
- key_put(keyring);
-failed_put_cred:
- put_cred(cred);
- return ret;
+ return register_key_type(&key_type_dns_resolver);
}
-static void __exit exit_dns_resolver(void)
+static void __exit exit_dns_key(void)
{
- key_revoke(dns_resolver_cache->thread_keyring);
unregister_key_type(&key_type_dns_resolver);
- put_cred(dns_resolver_cache);
}
-module_init(init_dns_resolver)
-module_exit(exit_dns_resolver)
-MODULE_LICENSE("GPL");
+module_init(init_dns_key);
+module_exit(exit_dns_key);
diff --git a/net/dns_resolver/dns_query.c b/net/dns_resolver/dns_query.c
index b8fb9a1245bf..ae4dde190101 100644
--- a/net/dns_resolver/dns_query.c
+++ b/net/dns_resolver/dns_query.c
@@ -24,8 +24,10 @@
*/
#include <linux/module.h>
+#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/cred.h>
+#include <linux/keyctl.h>
#include <linux/dns_resolver.h>
#include <linux/err.h>
#include <net/net_namespace.h>
@@ -35,6 +37,8 @@
#include "internal.h"
+static const struct cred *dns_resolver_cache;
+
/**
* dns_query - Query the DNS
* @net: The network namespace to operate in.
@@ -137,3 +141,63 @@ int dns_query(struct net *net,
return ret;
}
EXPORT_SYMBOL(dns_query);
+
+static int __init init_dns_resolver(void)
+{
+ struct cred *cred;
+ struct key *keyring;
+ int ret;
+
+ /*
+ * Create an override credential set with a special thread keyring in
+ * which DNS requests are cached. This prevents malicious redirections
+ * from being installed with add_key().
+ */
+ cred = prepare_kernel_cred(&init_task);
+ if (!cred)
+ return -ENOMEM;
+
+ keyring = keyring_alloc(".dns_resolver",
+ GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
+ (KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ,
+ KEY_ALLOC_NOT_IN_QUOTA, NULL, NULL);
+ if (IS_ERR(keyring)) {
+ ret = PTR_ERR(keyring);
+ goto failed_put_cred;
+ }
+
+ /*
+ * Instruct request_key() to use this special keyring as a cache for
+ * the results it looks up.
+ */
+ set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
+ cred->thread_keyring = keyring;
+ cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
+ dns_resolver_cache = cred;
+
+ kdebug("DNS resolver keyring: %d\n", key_serial(keyring));
+ return 0;
+
+failed_put_cred:
+ put_cred(cred);
+ return ret;
+}
+
+static void __exit exit_dns_resolver(void)
+{
+ key_revoke(dns_resolver_cache->thread_keyring);
+ put_cred(dns_resolver_cache);
+ /* Drain deferred credential and keyring destruction. */
+ key_gc_flush();
+}
+
+module_init(init_dns_resolver);
+module_exit(exit_dns_resolver);
+
+MODULE_DESCRIPTION("DNS Resolver");
+MODULE_AUTHOR("Wang Lei");
+MODULE_LICENSE("GPL");
+
+module_param_named(debug, dns_resolver_debug, uint, 0644);
+MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");
diff --git a/net/dns_resolver/internal.h b/net/dns_resolver/internal.h
index d0d8edcea092..3478bad78a9a 100644
--- a/net/dns_resolver/internal.h
+++ b/net/dns_resolver/internal.h
@@ -18,11 +18,6 @@ enum {
dns_key_error,
};
-/*
- * dns_key.c
- */
-extern const struct cred *dns_resolver_cache;
-
/*
* debug tracing
*/
--
2.47.3
More information about the linux-afs
mailing list