See also Documentation/security/keys/request-key.rst.
 
 
+ *  To search for a key in a specific domain, call:
+
+       struct key *request_key_tag(const struct key_type *type,
+                                   const char *description,
+                                   struct key_tag *domain_tag,
+                                   const char *callout_info);
+
+    This is identical to request_key(), except that a domain tag may be
+    specifies that causes search algorithm to only match keys matching that
+    tag.  The domain_tag may be NULL, specifying a global domain that is
+    separate from any nominated domain.
+
+
  *  To search for a key, passing auxiliary data to the upcaller, call::
 
        struct key *request_key_with_auxdata(const struct key_type *type,
                                             const char *description,
+                                            struct key_tag *domain_tag,
                                             const void *callout_info,
                                             size_t callout_len,
                                             void *aux);
 
-    This is identical to request_key(), except that the auxiliary data is
-    passed to the key_type->request_key() op if it exists, and the callout_info
-    is a blob of length callout_len, if given (the length may be 0).
+    This is identical to request_key_tag(), except that the auxiliary data is
+    passed to the key_type->request_key() op if it exists, and the
+    callout_info is a blob of length callout_len, if given (the length may be
+    0).
 
 
  *  To search for a key under RCU conditions, call::
 
        struct key *request_key_rcu(const struct key_type *type,
-                                   const char *description);
+                                   const char *description,
+                                   struct key_tag *domain_tag);
 
-    which is similar to request_key() except that it does not check for keys
-    that are under construction and it will not call out to userspace to
+    which is similar to request_key_tag() except that it does not check for
+    keys that are under construction and it will not call out to userspace to
     construct a key if it can't find a match.
 
 
 
                                const char *description,
                                const char *callout_info);
 
+or::
+
+       struct key *request_key_tag(const struct key_type *type,
+                                   const char *description,
+                                   const struct key_tag *domain_tag,
+                                   const char *callout_info);
+
 or::
 
        struct key *request_key_with_auxdata(const struct key_type *type,
                                             const char *description,
+                                            const struct key_tag *domain_tag,
                                             const char *callout_info,
                                             size_t callout_len,
                                             void *aux);
 or::
 
        struct key *request_key_rcu(const struct key_type *type,
-                                   const char *description);
+                                   const char *description,
+                                   const struct key_tag *domain_tag);
 
 Or by userspace invoking the request_key system call::
 
 destroyed.  The kernel interface returns a pointer directly to the key, and
 it's up to the caller to destroy the key.
 
-The request_key_with_auxdata() calls is like the in-kernel request_key() call,
-except that they permit auxiliary data to be passed to the upcaller (the
-default is NULL).  This is only useful for those key types that define their
-own upcall mechanism rather than using /sbin/request-key.
+The request_key_tag() call is like the in-kernel request_key(), except that it
+also takes a domain tag that allows keys to be separated by namespace and
+killed off as a group.
+
+The request_key_with_auxdata() calls is like the request_key_tag() call, except
+that they permit auxiliary data to be passed to the upcaller (the default is
+NULL).  This is only useful for those key types that define their own upcall
+mechanism rather than using /sbin/request-key.
 
-The request_key_rcu() call is like the in-kernel request_key() call, except
-that it doesn't check for keys that are under construction and doesn't attempt
-to construct missing keys.
+The request_key_rcu() call is like the request_key_tag() call, except that it
+doesn't check for keys that are under construction and doesn't attempt to
+construct missing keys.
 
 The userspace interface links the key to a keyring associated with the process
 to prevent the key from going away, and returns the serial number of the key to
 
 
        _enter("%s", cell->name);
 
-       ret = dns_query("afsdb", cell->name, cell->name_len, "srv=1",
-                       &result, _expiry, true);
+       ret = dns_query(cell->net->net, "afsdb", cell->name, cell->name_len,
+                       "srv=1", &result, _expiry, true);
        if (ret < 0) {
                _leave(" = %d [dns]", ret);
                return ERR_PTR(ret);
 
 static int afs_probe_cell_name(struct dentry *dentry)
 {
        struct afs_cell *cell;
+       struct afs_net *net = afs_d2net(dentry);
        const char *name = dentry->d_name.name;
        size_t len = dentry->d_name.len;
        int ret;
                len--;
        }
 
-       cell = afs_lookup_cell_rcu(afs_d2net(dentry), name, len);
+       cell = afs_lookup_cell_rcu(net, name, len);
        if (!IS_ERR(cell)) {
-               afs_put_cell(afs_d2net(dentry), cell);
+               afs_put_cell(net, cell);
                return 0;
        }
 
-       ret = dns_query("afsdb", name, len, "srv=1", NULL, NULL, false);
+       ret = dns_query(net->net, "afsdb", name, len, "srv=1",
+                       NULL, NULL, false);
        if (ret == -ENODATA)
                ret = -EDESTADDRREQ;
        return ret;
 
                goto name_is_IP_address;
 
        /* Perform the upcall */
-       rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL, false);
+       rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len,
+                      NULL, ip_addr, NULL, false);
        if (rc < 0)
                cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n",
                         __func__, len, len, hostname);
 
        char *ip_addr = NULL;
        int ip_len;
 
-       ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL, false);
+       ip_len = dns_query(net, NULL, name, namelen, NULL, &ip_addr, NULL,
+                          false);
        if (ip_len > 0)
                ret = rpc_pton(net, ip_addr, ip_len, sa, salen);
        else
 
        if (IS_ERR(rkey)) {
                mutex_lock(&idmap->idmap_mutex);
                rkey = request_key_with_auxdata(&key_type_id_resolver_legacy,
-                                               desc, "", 0, idmap);
+                                               desc, NULL, "", 0, idmap);
                mutex_unlock(&idmap->idmap_mutex);
        }
        if (!IS_ERR(rkey))
 
 
 #include <uapi/linux/dns_resolver.h>
 
-extern int dns_query(const char *type, const char *name, size_t namelen,
+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);
 
 
 typedef uint32_t key_perm_t;
 
 struct key;
+struct net;
 
 #ifdef CONFIG_KEYS
 
        key_put(key_ref_to_ptr(key_ref));
 }
 
-extern struct key *request_key(struct key_type *type,
-                              const char *description,
-                              const char *callout_info);
+extern struct key *request_key_tag(struct key_type *type,
+                                  const char *description,
+                                  struct key_tag *domain_tag,
+                                  const char *callout_info);
 
 extern struct key *request_key_rcu(struct key_type *type,
-                                  const char *description);
+                                  const char *description,
+                                  struct key_tag *domain_tag);
 
 extern struct key *request_key_with_auxdata(struct key_type *type,
                                            const char *description,
+                                           struct key_tag *domain_tag,
                                            const void *callout_info,
                                            size_t callout_len,
                                            void *aux);
 
+/**
+ * request_key - Request a key and wait for construction
+ * @type: Type of key.
+ * @description: The searchable description of the key.
+ * @callout_info: The data to pass to the instantiation upcall (or NULL).
+ *
+ * As for request_key_tag(), but with the default global domain tag.
+ */
+static inline struct key *request_key(struct key_type *type,
+                                     const char *description,
+                                     const char *callout_info)
+{
+       return request_key_tag(type, description, NULL, callout_info);
+}
+
+#ifdef CONFIG_NET
+/*
+ * request_key_net - Request a key for a net namespace and wait for construction
+ * @type: Type of key.
+ * @description: The searchable description of the key.
+ * @net: The network namespace that is the key's domain of operation.
+ * @callout_info: The data to pass to the instantiation upcall (or NULL).
+ *
+ * As for request_key() except that it does not add the returned key to a
+ * keyring if found, new keys are always allocated in the user's quota, the
+ * callout_info must be a NUL-terminated string and no auxiliary data can be
+ * passed.  Only keys that operate the specified network namespace are used.
+ *
+ * Furthermore, it then works as wait_for_key_construction() to wait for the
+ * completion of keys undergoing construction with a non-interruptible wait.
+ */
+#define request_key_net(type, description, net, callout_info) \
+       request_key_tag(type, description, net->key_domain, callout_info);
+#endif /* CONFIG_NET */
+
 extern int wait_for_key_construction(struct key *key, bool intr);
 
 extern int key_validate(const struct key *key);
 
                return -EINVAL;
 
        /* do dns_resolve upcall */
-       ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL, false);
+       ip_len = dns_query(current->nsproxy->net_ns,
+                          NULL, name, end - name, NULL, &ip_addr, NULL, false);
        if (ip_len > 0)
                ret = ceph_pton(ip_addr, ip_len, addr, -1, NULL);
        else
 
 #include <linux/cred.h>
 #include <linux/dns_resolver.h>
 #include <linux/err.h>
+#include <net/net_namespace.h>
 
 #include <keys/dns_resolver-type.h>
 #include <keys/user-type.h>
 
 /**
  * dns_query - Query the DNS
+ * @net: The network namespace to operate in.
  * @type: Query type (or NULL for straight host->IP lookup)
  * @name: Name to look up
  * @namelen: Length of name
  *
  * Returns the size of the result on success, -ve error code otherwise.
  */
-int dns_query(const char *type, const char *name, size_t namelen,
+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)
 {
         * add_key() to preinstall malicious redirections
         */
        saved_cred = override_creds(dns_resolver_cache);
-       rkey = request_key(&key_type_dns_resolver, desc, options);
+       rkey = request_key_net(&key_type_dns_resolver, desc, net, options);
        revert_creds(saved_cred);
        kfree(desc);
        if (IS_ERR(rkey)) {
 
        if (IS_ERR(description))
                return PTR_ERR(description);
 
-       key = request_key(&key_type_rxrpc, description, NULL);
+       key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL);
        if (IS_ERR(key)) {
                kfree(description);
                _leave(" = %ld", PTR_ERR(key));
        if (IS_ERR(description))
                return PTR_ERR(description);
 
-       key = request_key(&key_type_keyring, description, NULL);
+       key = request_key_net(&key_type_keyring, description, sock_net(&rx->sk), NULL);
        if (IS_ERR(key)) {
                kfree(description);
                _leave(" = %ld", PTR_ERR(key));
 
 
 extern struct key *request_key_and_link(struct key_type *type,
                                        const char *description,
+                                       struct key_tag *domain_tag,
                                        const void *callout_info,
                                        size_t callout_len,
                                        void *aux,
 
        }
 
        /* do the search */
-       key = request_key_and_link(ktype, description, callout_info,
+       key = request_key_and_link(ktype, description, NULL, callout_info,
                                   callout_len, NULL, key_ref_to_ptr(dest_ref),
                                   KEY_ALLOC_IN_QUOTA);
        if (IS_ERR(key)) {
 
 
        memcpy(index_key->desc, index_key->description, n);
 
-       if (index_key->type->flags & KEY_TYPE_NET_DOMAIN)
-               index_key->domain_tag = current->nsproxy->net_ns->key_domain;
-       else
-               index_key->domain_tag = &default_domain_tag;
+       if (!index_key->domain_tag) {
+               if (index_key->type->flags & KEY_TYPE_NET_DOMAIN)
+                       index_key->domain_tag = current->nsproxy->net_ns->key_domain;
+               else
+                       index_key->domain_tag = &default_domain_tag;
+       }
+
        hash_key_type_and_desc(index_key);
 }
 
 
 #include <linux/err.h>
 #include <linux/keyctl.h>
 #include <linux/slab.h>
+#include <net/net_namespace.h>
 #include "internal.h"
 #include <keys/request_key_auth-type.h>
 
  * request_key_and_link - Request a key and cache it in a keyring.
  * @type: The type of key we want.
  * @description: The searchable description of the key.
+ * @domain_tag: The domain in which the key operates.
  * @callout_info: The data to pass to the instantiation upcall (or NULL).
  * @callout_len: The length of callout_info.
  * @aux: Auxiliary data for the upcall.
  * @dest_keyring: Where to cache the key.
  * @flags: Flags to key_alloc().
  *
- * A key matching the specified criteria is searched for in the process's
- * keyrings and returned with its usage count incremented if found.  Otherwise,
- * if callout_info is not NULL, a key will be allocated and some service
- * (probably in userspace) will be asked to instantiate it.
+ * A key matching the specified criteria (type, description, domain_tag) is
+ * searched for in the process's keyrings and returned with its usage count
+ * incremented if found.  Otherwise, if callout_info is not NULL, a key will be
+ * allocated and some service (probably in userspace) will be asked to
+ * instantiate it.
  *
  * If successfully found or created, the key will be linked to the destination
  * keyring if one is provided.
  */
 struct key *request_key_and_link(struct key_type *type,
                                 const char *description,
+                                struct key_tag *domain_tag,
                                 const void *callout_info,
                                 size_t callout_len,
                                 void *aux,
 {
        struct keyring_search_context ctx = {
                .index_key.type         = type,
+               .index_key.domain_tag   = domain_tag,
                .index_key.description  = description,
                .index_key.desc_len     = strlen(description),
                .cred                   = current_cred(),
 EXPORT_SYMBOL(wait_for_key_construction);
 
 /**
- * request_key - Request a key and wait for construction
+ * request_key_tag - Request a key and wait for construction
  * @type: Type of key.
  * @description: The searchable description of the key.
+ * @domain_tag: The domain in which the key operates.
  * @callout_info: The data to pass to the instantiation upcall (or NULL).
  *
  * As for request_key_and_link() except that it does not add the returned key
  * Furthermore, it then works as wait_for_key_construction() to wait for the
  * completion of keys undergoing construction with a non-interruptible wait.
  */
-struct key *request_key(struct key_type *type,
-                       const char *description,
-                       const char *callout_info)
+struct key *request_key_tag(struct key_type *type,
+                           const char *description,
+                           struct key_tag *domain_tag,
+                           const char *callout_info)
 {
        struct key *key;
        size_t callout_len = 0;
 
        if (callout_info)
                callout_len = strlen(callout_info);
-       key = request_key_and_link(type, description, callout_info, callout_len,
+       key = request_key_and_link(type, description, domain_tag,
+                                  callout_info, callout_len,
                                   NULL, NULL, KEY_ALLOC_IN_QUOTA);
        if (!IS_ERR(key)) {
                ret = wait_for_key_construction(key, false);
        }
        return key;
 }
-EXPORT_SYMBOL(request_key);
+EXPORT_SYMBOL(request_key_tag);
 
 /**
  * request_key_with_auxdata - Request a key with auxiliary data for the upcaller
  * @type: The type of key we want.
  * @description: The searchable description of the key.
+ * @domain_tag: The domain in which the key operates.
  * @callout_info: The data to pass to the instantiation upcall (or NULL).
  * @callout_len: The length of callout_info.
  * @aux: Auxiliary data for the upcall.
  */
 struct key *request_key_with_auxdata(struct key_type *type,
                                     const char *description,
+                                    struct key_tag *domain_tag,
                                     const void *callout_info,
                                     size_t callout_len,
                                     void *aux)
        struct key *key;
        int ret;
 
-       key = request_key_and_link(type, description, callout_info, callout_len,
+       key = request_key_and_link(type, description, domain_tag,
+                                  callout_info, callout_len,
                                   aux, NULL, KEY_ALLOC_IN_QUOTA);
        if (!IS_ERR(key)) {
                ret = wait_for_key_construction(key, false);
  * request_key_rcu - Request key from RCU-read-locked context
  * @type: The type of key we want.
  * @description: The name of the key we want.
+ * @domain_tag: The domain in which the key operates.
  *
  * Request a key from a context that we may not sleep in (such as RCU-mode
  * pathwalk).  Keys under construction are ignored.
  * Return a pointer to the found key if successful, -ENOKEY if we couldn't find
  * a key or some other error if the key found was unsuitable or inaccessible.
  */
-struct key *request_key_rcu(struct key_type *type, const char *description)
+struct key *request_key_rcu(struct key_type *type,
+                           const char *description,
+                           struct key_tag *domain_tag)
 {
        struct keyring_search_context ctx = {
                .index_key.type         = type,
+               .index_key.domain_tag   = domain_tag,
                .index_key.description  = description,
                .index_key.desc_len     = strlen(description),
                .cred                   = current_cred(),