Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a58946c1 authored by David Howells's avatar David Howells
Browse files

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: default avatarDavid 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
parent 9b242610
Loading
Loading
Loading
Loading
+22 −6
Original line number Diff line number Diff line
@@ -1102,26 +1102,42 @@ payload contents" for more information.
    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.


+21 −8
Original line number Diff line number Diff line
@@ -13,10 +13,18 @@ The process starts by either the kernel requesting a service by calling
				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);
@@ -24,7 +32,8 @@ or::
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::

@@ -38,14 +47,18 @@ does not need to link the key to a keyring to prevent it from being immediately
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
+2 −2
Original line number Diff line number Diff line
@@ -250,8 +250,8 @@ struct afs_vlserver_list *afs_dns_query(struct afs_cell *cell, time64_t *_expiry

	_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);
+5 −3
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@ const struct file_operations afs_dynroot_file_operations = {
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;
@@ -40,13 +41,14 @@ static int afs_probe_cell_name(struct dentry *dentry)
		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;
+2 −1
Original line number Diff line number Diff line
@@ -77,7 +77,8 @@ dns_resolve_server_name_to_ip(const char *unc, char **ip_addr)
		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);
Loading