diff --git a/fs/afs/main.c b/fs/afs/main.c
index 7a883c59976f..16ae947d371e 100644
--- a/fs/afs/main.c
+++ b/fs/afs/main.c
@@ -12,6 +12,7 @@
#include <linux/sched.h>
#include <linux/random.h>
#include <linux/proc_fs.h>
+#include <linux/dns_resolver.h>
#define CREATE_TRACE_POINTS
#include "internal.h"
@@ -183,6 +184,7 @@ static int __init afs_init(void)
if (ret < 0)
goto error_net;
+ dns_resolver_cache_get();
/* register the filesystems */
ret = afs_fs_init();
if (ret < 0)
@@ -199,6 +201,7 @@ static int __init afs_init(void)
error_proc:
afs_fs_exit();
error_fs:
+ dns_resolver_cache_put();
unregister_pernet_device(&afs_net_ops);
error_net:
destroy_workqueue(afs_lock_manager);
@@ -232,6 +235,7 @@ static void __exit afs_exit(void)
destroy_workqueue(afs_wq);
afs_clean_up_permit_cache();
rcu_barrier();
+ dns_resolver_cache_put();
}
module_exit(afs_exit);
diff --git a/fs/nfs/dns_resolve.h b/fs/nfs/dns_resolve.h
index fe3b172c4de1..4b9ecfb4f7fe 100644
--- a/fs/nfs/dns_resolve.h
+++ b/fs/nfs/dns_resolve.h
@@ -9,13 +9,18 @@
#ifdef CONFIG_NFS_USE_KERNEL_DNS
+#include <linux/dns_resolver.h>
+
static inline int nfs_dns_resolver_init(void)
{
+ dns_resolver_cache_get();
return 0;
}
static inline void nfs_dns_resolver_destroy(void)
-{}
+{
+ dns_resolver_cache_put();
+}
static inline int nfs_dns_resolver_cache_init(struct net *net)
{diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index bf199a5ca084..9788052599ce 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -31,6 +31,7 @@
#include <linux/xattr.h>
#include <linux/mm.h>
#include <linux/key-type.h>
+#include <linux/dns_resolver.h>
#include <linux/fileattr.h>
#include <uapi/linux/magic.h>
#include <net/ipv6.h>
@@ -2160,6 +2161,7 @@ init_cifs(void)
goto out_cifs_swn_init;
cifs_proc_init();
+ dns_resolver_cache_get();
rc = register_filesystem(&cifs_fs_type);
if (rc)
@@ -2174,6 +2176,7 @@ init_cifs(void)
return 0;
out_clean_proc:
+ dns_resolver_cache_put();
cifs_proc_clean();
exit_cifs_idmap();
out_cifs_swn_init:
@@ -2242,6 +2245,7 @@ exit_cifs(void)
destroy_workqueue(serverclose_wq);
destroy_workqueue(cfid_put_wq);
destroy_workqueue(cifsiod_wq);
+ dns_resolver_cache_put();
}
MODULE_AUTHOR("Steve French");diff --git a/include/linux/dns_resolver.h b/include/linux/dns_resolver.h
index 976cbbdb2832..cc11e09b0df3 100644
--- a/include/linux/dns_resolver.h
+++ b/include/linux/dns_resolver.h
@@ -27,8 +27,15 @@
#include <uapi/linux/dns_resolver.h>
struct net;
-extern int dns_query(struct net *net, const char *type, const char *name, size_t namelen,
- const char *options, char **_result, time64_t *_expiry,
- bool invalidate);
+#if IS_ENABLED(CONFIG_DNS_RESOLVER)
+int dns_query(struct net *net, const char *type, const char *name, size_t namelen,
+ const char *options, char **_result, time64_t *_expiry,
+ bool invalidate);
+void dns_resolver_cache_get(void);
+void dns_resolver_cache_put(void);
+#else
+static inline void dns_resolver_cache_get(void) { }
+static inline void dns_resolver_cache_put(void) { }
+#endif
#endif /* _LINUX_DNS_RESOLVER_H */diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c
index a797c7360e3c..df62a269cb73 100644
--- a/net/ceph/ceph_common.c
+++ b/net/ceph/ceph_common.c
@@ -8,6 +8,7 @@
#include <linux/in6.h>
#include <linux/key.h>
#include <keys/ceph-type.h>
+#include <linux/dns_resolver.h>
#include <linux/module.h>
#include <linux/mount.h>
#include <linux/nsproxy.h>
@@ -890,6 +891,9 @@ static int __init init_ceph_lib(void)
if (ret < 0)
goto out_msgr;
+#ifdef CONFIG_CEPH_LIB_USE_DNS_RESOLVER
+ dns_resolver_cache_get();
+#endif
pr_info("loaded (mon/osd proto %d/%d)\n",
CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL);
@@ -913,6 +917,9 @@ static void __exit exit_ceph_lib(void)
ceph_msgr_exit();
ceph_crypto_shutdown();
ceph_debugfs_cleanup();
+#ifdef CONFIG_CEPH_LIB_USE_DNS_RESOLVER
+ dns_resolver_cache_put();
+#endif
}
module_init(init_ceph_lib);
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index 451247864a63..63f4fac0dbc8 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/keyctl.h>
#include <linux/err.h>
+#include <linux/mutex.h>
#include <linux/seq_file.h>
#include <linux/dns_resolver.h>
#include <keys/dns_resolver-type.h>
@@ -31,6 +32,8 @@ module_param_named(debug, dns_resolver_debug, uint, 0644);
MODULE_PARM_DESC(debug, "DNS Resolver debugging mask");
const struct cred *dns_resolver_cache;
+static DEFINE_MUTEX(dns_resolver_cache_mutex);
+static unsigned int dns_resolver_cache_users;
#define DNS_ERRORNO_OPTION "dnserror"
@@ -306,6 +309,31 @@ static long dns_resolver_read(const struct key *key,
return user_read(key, buffer, buflen);
}
+void dns_resolver_cache_get(void)
+{
+ mutex_lock(&dns_resolver_cache_mutex);
+ dns_resolver_cache_users++;
+ mutex_unlock(&dns_resolver_cache_mutex);
+}
+EXPORT_SYMBOL_GPL(dns_resolver_cache_get);
+
+void dns_resolver_cache_put(void)
+{
+ int ret;
+
+ mutex_lock(&dns_resolver_cache_mutex);
+ if (--dns_resolver_cache_users == 0 && dns_resolver_cache) {
+ ret = keyring_clear(dns_resolver_cache->thread_keyring);
+ if (ret)
+ pr_warn_ratelimited("dns_resolver: Failed to clear cache: %d\n",
+ ret);
+ else
+ key_gc_flush();
+ }
+ mutex_unlock(&dns_resolver_cache_mutex);
+}
+EXPORT_SYMBOL_GPL(dns_resolver_cache_put);
+
struct key_type key_type_dns_resolver = {
.name = "dns_resolver",
.flags = KEY_TYPE_NET_DOMAIN | KEY_TYPE_INSTANT_REAP,--
2.47.3