Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

keys: Pass the network namespace into request_key mechanism

Create a request_key_net() function and use it to pass the network
namespace domain tag into DNS revolver keys and rxrpc/AFS keys so that keys
for different domains can coexist in the same keyring.

Signed-off-by: David Howells <dhowells@redhat.com>
cc: netdev@vger.kernel.org
cc: linux-nfs@vger.kernel.org
cc: linux-cifs@vger.kernel.org
cc: linux-afs@lists.infradead.org

+145 -49
+22 -6
Documentation/security/keys/core.rst
··· 1102 1102 See also Documentation/security/keys/request-key.rst. 1103 1103 1104 1104 1105 + * To search for a key in a specific domain, call: 1106 + 1107 + struct key *request_key_tag(const struct key_type *type, 1108 + const char *description, 1109 + struct key_tag *domain_tag, 1110 + const char *callout_info); 1111 + 1112 + This is identical to request_key(), except that a domain tag may be 1113 + specifies that causes search algorithm to only match keys matching that 1114 + tag. The domain_tag may be NULL, specifying a global domain that is 1115 + separate from any nominated domain. 1116 + 1117 + 1105 1118 * To search for a key, passing auxiliary data to the upcaller, call:: 1106 1119 1107 1120 struct key *request_key_with_auxdata(const struct key_type *type, 1108 1121 const char *description, 1122 + struct key_tag *domain_tag, 1109 1123 const void *callout_info, 1110 1124 size_t callout_len, 1111 1125 void *aux); 1112 1126 1113 - This is identical to request_key(), except that the auxiliary data is 1114 - passed to the key_type->request_key() op if it exists, and the callout_info 1115 - is a blob of length callout_len, if given (the length may be 0). 1127 + This is identical to request_key_tag(), except that the auxiliary data is 1128 + passed to the key_type->request_key() op if it exists, and the 1129 + callout_info is a blob of length callout_len, if given (the length may be 1130 + 0). 1116 1131 1117 1132 1118 1133 * To search for a key under RCU conditions, call:: 1119 1134 1120 1135 struct key *request_key_rcu(const struct key_type *type, 1121 - const char *description); 1136 + const char *description, 1137 + struct key_tag *domain_tag); 1122 1138 1123 - which is similar to request_key() except that it does not check for keys 1124 - that are under construction and it will not call out to userspace to 1139 + which is similar to request_key_tag() except that it does not check for 1140 + keys that are under construction and it will not call out to userspace to 1125 1141 construct a key if it can't find a match. 1126 1142 1127 1143
+21 -8
Documentation/security/keys/request-key.rst
··· 15 15 16 16 or:: 17 17 18 + struct key *request_key_tag(const struct key_type *type, 19 + const char *description, 20 + const struct key_tag *domain_tag, 21 + const char *callout_info); 22 + 23 + or:: 24 + 18 25 struct key *request_key_with_auxdata(const struct key_type *type, 19 26 const char *description, 27 + const struct key_tag *domain_tag, 20 28 const char *callout_info, 21 29 size_t callout_len, 22 30 void *aux); ··· 32 24 or:: 33 25 34 26 struct key *request_key_rcu(const struct key_type *type, 35 - const char *description); 27 + const char *description, 28 + const struct key_tag *domain_tag); 36 29 37 30 Or by userspace invoking the request_key system call:: 38 31 ··· 47 38 destroyed. The kernel interface returns a pointer directly to the key, and 48 39 it's up to the caller to destroy the key. 49 40 50 - The request_key_with_auxdata() calls is like the in-kernel request_key() call, 51 - except that they permit auxiliary data to be passed to the upcaller (the 52 - default is NULL). This is only useful for those key types that define their 53 - own upcall mechanism rather than using /sbin/request-key. 41 + The request_key_tag() call is like the in-kernel request_key(), except that it 42 + also takes a domain tag that allows keys to be separated by namespace and 43 + killed off as a group. 54 44 55 - The request_key_rcu() call is like the in-kernel request_key() call, except 56 - that it doesn't check for keys that are under construction and doesn't attempt 57 - to construct missing keys. 45 + The request_key_with_auxdata() calls is like the request_key_tag() call, except 46 + that they permit auxiliary data to be passed to the upcaller (the default is 47 + NULL). This is only useful for those key types that define their own upcall 48 + mechanism rather than using /sbin/request-key. 49 + 50 + The request_key_rcu() call is like the request_key_tag() call, except that it 51 + doesn't check for keys that are under construction and doesn't attempt to 52 + construct missing keys. 58 53 59 54 The userspace interface links the key to a keyring associated with the process 60 55 to prevent the key from going away, and returns the serial number of the key to
+2 -2
fs/afs/addr_list.c
··· 250 250 251 251 _enter("%s", cell->name); 252 252 253 - ret = dns_query("afsdb", cell->name, cell->name_len, "srv=1", 254 - &result, _expiry, true); 253 + ret = dns_query(cell->net->net, "afsdb", cell->name, cell->name_len, 254 + "srv=1", &result, _expiry, true); 255 255 if (ret < 0) { 256 256 _leave(" = %d [dns]", ret); 257 257 return ERR_PTR(ret);
+5 -3
fs/afs/dynroot.c
··· 28 28 static int afs_probe_cell_name(struct dentry *dentry) 29 29 { 30 30 struct afs_cell *cell; 31 + struct afs_net *net = afs_d2net(dentry); 31 32 const char *name = dentry->d_name.name; 32 33 size_t len = dentry->d_name.len; 33 34 int ret; ··· 41 40 len--; 42 41 } 43 42 44 - cell = afs_lookup_cell_rcu(afs_d2net(dentry), name, len); 43 + cell = afs_lookup_cell_rcu(net, name, len); 45 44 if (!IS_ERR(cell)) { 46 - afs_put_cell(afs_d2net(dentry), cell); 45 + afs_put_cell(net, cell); 47 46 return 0; 48 47 } 49 48 50 - ret = dns_query("afsdb", name, len, "srv=1", NULL, NULL, false); 49 + ret = dns_query(net->net, "afsdb", name, len, "srv=1", 50 + NULL, NULL, false); 51 51 if (ret == -ENODATA) 52 52 ret = -EDESTADDRREQ; 53 53 return ret;
+2 -1
fs/cifs/dns_resolve.c
··· 77 77 goto name_is_IP_address; 78 78 79 79 /* Perform the upcall */ 80 - rc = dns_query(NULL, hostname, len, NULL, ip_addr, NULL, false); 80 + rc = dns_query(current->nsproxy->net_ns, NULL, hostname, len, 81 + NULL, ip_addr, NULL, false); 81 82 if (rc < 0) 82 83 cifs_dbg(FYI, "%s: unable to resolve: %*.*s\n", 83 84 __func__, len, len, hostname);
+2 -1
fs/nfs/dns_resolve.c
··· 22 22 char *ip_addr = NULL; 23 23 int ip_len; 24 24 25 - ip_len = dns_query(NULL, name, namelen, NULL, &ip_addr, NULL, false); 25 + ip_len = dns_query(net, NULL, name, namelen, NULL, &ip_addr, NULL, 26 + false); 26 27 if (ip_len > 0) 27 28 ret = rpc_pton(net, ip_addr, ip_len, sa, salen); 28 29 else
+1 -1
fs/nfs/nfs4idmap.c
··· 291 291 if (IS_ERR(rkey)) { 292 292 mutex_lock(&idmap->idmap_mutex); 293 293 rkey = request_key_with_auxdata(&key_type_id_resolver_legacy, 294 - desc, "", 0, idmap); 294 + desc, NULL, "", 0, idmap); 295 295 mutex_unlock(&idmap->idmap_mutex); 296 296 } 297 297 if (!IS_ERR(rkey))
+2 -1
include/linux/dns_resolver.h
··· 26 26 27 27 #include <uapi/linux/dns_resolver.h> 28 28 29 - extern int dns_query(const char *type, const char *name, size_t namelen, 29 + struct net; 30 + extern int dns_query(struct net *net, const char *type, const char *name, size_t namelen, 30 31 const char *options, char **_result, time64_t *_expiry, 31 32 bool invalidate); 32 33
+43 -4
include/linux/key.h
··· 36 36 typedef uint32_t key_perm_t; 37 37 38 38 struct key; 39 + struct net; 39 40 40 41 #ifdef CONFIG_KEYS 41 42 ··· 297 296 key_put(key_ref_to_ptr(key_ref)); 298 297 } 299 298 300 - extern struct key *request_key(struct key_type *type, 301 - const char *description, 302 - const char *callout_info); 299 + extern struct key *request_key_tag(struct key_type *type, 300 + const char *description, 301 + struct key_tag *domain_tag, 302 + const char *callout_info); 303 303 304 304 extern struct key *request_key_rcu(struct key_type *type, 305 - const char *description); 305 + const char *description, 306 + struct key_tag *domain_tag); 306 307 307 308 extern struct key *request_key_with_auxdata(struct key_type *type, 308 309 const char *description, 310 + struct key_tag *domain_tag, 309 311 const void *callout_info, 310 312 size_t callout_len, 311 313 void *aux); 314 + 315 + /** 316 + * request_key - Request a key and wait for construction 317 + * @type: Type of key. 318 + * @description: The searchable description of the key. 319 + * @callout_info: The data to pass to the instantiation upcall (or NULL). 320 + * 321 + * As for request_key_tag(), but with the default global domain tag. 322 + */ 323 + static inline struct key *request_key(struct key_type *type, 324 + const char *description, 325 + const char *callout_info) 326 + { 327 + return request_key_tag(type, description, NULL, callout_info); 328 + } 329 + 330 + #ifdef CONFIG_NET 331 + /* 332 + * request_key_net - Request a key for a net namespace and wait for construction 333 + * @type: Type of key. 334 + * @description: The searchable description of the key. 335 + * @net: The network namespace that is the key's domain of operation. 336 + * @callout_info: The data to pass to the instantiation upcall (or NULL). 337 + * 338 + * As for request_key() except that it does not add the returned key to a 339 + * keyring if found, new keys are always allocated in the user's quota, the 340 + * callout_info must be a NUL-terminated string and no auxiliary data can be 341 + * passed. Only keys that operate the specified network namespace are used. 342 + * 343 + * Furthermore, it then works as wait_for_key_construction() to wait for the 344 + * completion of keys undergoing construction with a non-interruptible wait. 345 + */ 346 + #define request_key_net(type, description, net, callout_info) \ 347 + request_key_tag(type, description, net->key_domain, callout_info); 348 + #endif /* CONFIG_NET */ 312 349 313 350 extern int wait_for_key_construction(struct key *key, bool intr); 314 351
+2 -1
net/ceph/messenger.c
··· 1887 1887 return -EINVAL; 1888 1888 1889 1889 /* do dns_resolve upcall */ 1890 - ip_len = dns_query(NULL, name, end - name, NULL, &ip_addr, NULL, false); 1890 + ip_len = dns_query(current->nsproxy->net_ns, 1891 + NULL, name, end - name, NULL, &ip_addr, NULL, false); 1891 1892 if (ip_len > 0) 1892 1893 ret = ceph_pton(ip_addr, ip_len, addr, -1, NULL); 1893 1894 else
+5 -2
net/dns_resolver/dns_query.c
··· 40 40 #include <linux/cred.h> 41 41 #include <linux/dns_resolver.h> 42 42 #include <linux/err.h> 43 + #include <net/net_namespace.h> 43 44 44 45 #include <keys/dns_resolver-type.h> 45 46 #include <keys/user-type.h> ··· 49 48 50 49 /** 51 50 * dns_query - Query the DNS 51 + * @net: The network namespace to operate in. 52 52 * @type: Query type (or NULL for straight host->IP lookup) 53 53 * @name: Name to look up 54 54 * @namelen: Length of name ··· 71 69 * 72 70 * Returns the size of the result on success, -ve error code otherwise. 73 71 */ 74 - int dns_query(const char *type, const char *name, size_t namelen, 72 + int dns_query(struct net *net, 73 + const char *type, const char *name, size_t namelen, 75 74 const char *options, char **_result, time64_t *_expiry, 76 75 bool invalidate) 77 76 { ··· 125 122 * add_key() to preinstall malicious redirections 126 123 */ 127 124 saved_cred = override_creds(dns_resolver_cache); 128 - rkey = request_key(&key_type_dns_resolver, desc, options); 125 + rkey = request_key_net(&key_type_dns_resolver, desc, net, options); 129 126 revert_creds(saved_cred); 130 127 kfree(desc); 131 128 if (IS_ERR(rkey)) {
+2 -2
net/rxrpc/key.c
··· 914 914 if (IS_ERR(description)) 915 915 return PTR_ERR(description); 916 916 917 - key = request_key(&key_type_rxrpc, description, NULL); 917 + key = request_key_net(&key_type_rxrpc, description, sock_net(&rx->sk), NULL); 918 918 if (IS_ERR(key)) { 919 919 kfree(description); 920 920 _leave(" = %ld", PTR_ERR(key)); ··· 945 945 if (IS_ERR(description)) 946 946 return PTR_ERR(description); 947 947 948 - key = request_key(&key_type_keyring, description, NULL); 948 + key = request_key_net(&key_type_keyring, description, sock_net(&rx->sk), NULL); 949 949 if (IS_ERR(key)) { 950 950 kfree(description); 951 951 _leave(" = %ld", PTR_ERR(key));
+1
security/keys/internal.h
··· 156 156 157 157 extern struct key *request_key_and_link(struct key_type *type, 158 158 const char *description, 159 + struct key_tag *domain_tag, 159 160 const void *callout_info, 160 161 size_t callout_len, 161 162 void *aux,
+1 -1
security/keys/keyctl.c
··· 224 224 } 225 225 226 226 /* do the search */ 227 - key = request_key_and_link(ktype, description, callout_info, 227 + key = request_key_and_link(ktype, description, NULL, callout_info, 228 228 callout_len, NULL, key_ref_to_ptr(dest_ref), 229 229 KEY_ALLOC_IN_QUOTA); 230 230 if (IS_ERR(key)) {
+7 -4
security/keys/keyring.c
··· 222 222 223 223 memcpy(index_key->desc, index_key->description, n); 224 224 225 - if (index_key->type->flags & KEY_TYPE_NET_DOMAIN) 226 - index_key->domain_tag = current->nsproxy->net_ns->key_domain; 227 - else 228 - index_key->domain_tag = &default_domain_tag; 225 + if (!index_key->domain_tag) { 226 + if (index_key->type->flags & KEY_TYPE_NET_DOMAIN) 227 + index_key->domain_tag = current->nsproxy->net_ns->key_domain; 228 + else 229 + index_key->domain_tag = &default_domain_tag; 230 + } 231 + 229 232 hash_key_type_and_desc(index_key); 230 233 } 231 234
+27 -12
security/keys/request_key.c
··· 17 17 #include <linux/err.h> 18 18 #include <linux/keyctl.h> 19 19 #include <linux/slab.h> 20 + #include <net/net_namespace.h> 20 21 #include "internal.h" 21 22 #include <keys/request_key_auth-type.h> 22 23 ··· 534 533 * request_key_and_link - Request a key and cache it in a keyring. 535 534 * @type: The type of key we want. 536 535 * @description: The searchable description of the key. 536 + * @domain_tag: The domain in which the key operates. 537 537 * @callout_info: The data to pass to the instantiation upcall (or NULL). 538 538 * @callout_len: The length of callout_info. 539 539 * @aux: Auxiliary data for the upcall. 540 540 * @dest_keyring: Where to cache the key. 541 541 * @flags: Flags to key_alloc(). 542 542 * 543 - * A key matching the specified criteria is searched for in the process's 544 - * keyrings and returned with its usage count incremented if found. Otherwise, 545 - * if callout_info is not NULL, a key will be allocated and some service 546 - * (probably in userspace) will be asked to instantiate it. 543 + * A key matching the specified criteria (type, description, domain_tag) is 544 + * searched for in the process's keyrings and returned with its usage count 545 + * incremented if found. Otherwise, if callout_info is not NULL, a key will be 546 + * allocated and some service (probably in userspace) will be asked to 547 + * instantiate it. 547 548 * 548 549 * If successfully found or created, the key will be linked to the destination 549 550 * keyring if one is provided. ··· 561 558 */ 562 559 struct key *request_key_and_link(struct key_type *type, 563 560 const char *description, 561 + struct key_tag *domain_tag, 564 562 const void *callout_info, 565 563 size_t callout_len, 566 564 void *aux, ··· 570 566 { 571 567 struct keyring_search_context ctx = { 572 568 .index_key.type = type, 569 + .index_key.domain_tag = domain_tag, 573 570 .index_key.description = description, 574 571 .index_key.desc_len = strlen(description), 575 572 .cred = current_cred(), ··· 677 672 EXPORT_SYMBOL(wait_for_key_construction); 678 673 679 674 /** 680 - * request_key - Request a key and wait for construction 675 + * request_key_tag - Request a key and wait for construction 681 676 * @type: Type of key. 682 677 * @description: The searchable description of the key. 678 + * @domain_tag: The domain in which the key operates. 683 679 * @callout_info: The data to pass to the instantiation upcall (or NULL). 684 680 * 685 681 * As for request_key_and_link() except that it does not add the returned key ··· 691 685 * Furthermore, it then works as wait_for_key_construction() to wait for the 692 686 * completion of keys undergoing construction with a non-interruptible wait. 693 687 */ 694 - struct key *request_key(struct key_type *type, 695 - const char *description, 696 - const char *callout_info) 688 + struct key *request_key_tag(struct key_type *type, 689 + const char *description, 690 + struct key_tag *domain_tag, 691 + const char *callout_info) 697 692 { 698 693 struct key *key; 699 694 size_t callout_len = 0; ··· 702 695 703 696 if (callout_info) 704 697 callout_len = strlen(callout_info); 705 - key = request_key_and_link(type, description, callout_info, callout_len, 698 + key = request_key_and_link(type, description, domain_tag, 699 + callout_info, callout_len, 706 700 NULL, NULL, KEY_ALLOC_IN_QUOTA); 707 701 if (!IS_ERR(key)) { 708 702 ret = wait_for_key_construction(key, false); ··· 714 706 } 715 707 return key; 716 708 } 717 - EXPORT_SYMBOL(request_key); 709 + EXPORT_SYMBOL(request_key_tag); 718 710 719 711 /** 720 712 * request_key_with_auxdata - Request a key with auxiliary data for the upcaller 721 713 * @type: The type of key we want. 722 714 * @description: The searchable description of the key. 715 + * @domain_tag: The domain in which the key operates. 723 716 * @callout_info: The data to pass to the instantiation upcall (or NULL). 724 717 * @callout_len: The length of callout_info. 725 718 * @aux: Auxiliary data for the upcall. ··· 733 724 */ 734 725 struct key *request_key_with_auxdata(struct key_type *type, 735 726 const char *description, 727 + struct key_tag *domain_tag, 736 728 const void *callout_info, 737 729 size_t callout_len, 738 730 void *aux) ··· 741 731 struct key *key; 742 732 int ret; 743 733 744 - key = request_key_and_link(type, description, callout_info, callout_len, 734 + key = request_key_and_link(type, description, domain_tag, 735 + callout_info, callout_len, 745 736 aux, NULL, KEY_ALLOC_IN_QUOTA); 746 737 if (!IS_ERR(key)) { 747 738 ret = wait_for_key_construction(key, false); ··· 759 748 * request_key_rcu - Request key from RCU-read-locked context 760 749 * @type: The type of key we want. 761 750 * @description: The name of the key we want. 751 + * @domain_tag: The domain in which the key operates. 762 752 * 763 753 * Request a key from a context that we may not sleep in (such as RCU-mode 764 754 * pathwalk). Keys under construction are ignored. ··· 767 755 * Return a pointer to the found key if successful, -ENOKEY if we couldn't find 768 756 * a key or some other error if the key found was unsuitable or inaccessible. 769 757 */ 770 - struct key *request_key_rcu(struct key_type *type, const char *description) 758 + struct key *request_key_rcu(struct key_type *type, 759 + const char *description, 760 + struct key_tag *domain_tag) 771 761 { 772 762 struct keyring_search_context ctx = { 773 763 .index_key.type = type, 764 + .index_key.domain_tag = domain_tag, 774 765 .index_key.description = description, 775 766 .index_key.desc_len = strlen(description), 776 767 .cred = current_cred(),