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

Commit 8b6a666a authored by David Howells's avatar David Howells
Browse files

afs: Provide an RCU-capable key lookup



Provide an RCU-capable key lookup function.  We don't want to call
afs_request_key() in RCU-mode pathwalk as request_key() might sleep, even if
we don't ask it to construct anything as it might find a key that is currently
undergoing construction.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent 23a28913
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1217,6 +1217,7 @@ extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int,
			     struct afs_status_cb *);
extern void afs_zap_permits(struct rcu_head *);
extern struct key *afs_request_key(struct afs_cell *);
extern struct key *afs_request_key_rcu(struct afs_cell *);
extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *);
extern int afs_permission(struct inode *, int);
extern void __exit afs_clean_up_permit_cache(void);
+31 −2
Original line number Diff line number Diff line
@@ -27,8 +27,37 @@ struct key *afs_request_key(struct afs_cell *cell)
	_enter("{%x}", key_serial(cell->anonymous_key));

	_debug("key %s", cell->anonymous_key->description);
	key = request_key(&key_type_rxrpc, cell->anonymous_key->description,
			  NULL);
	key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description,
			      cell->net->net, NULL);
	if (IS_ERR(key)) {
		if (PTR_ERR(key) != -ENOKEY) {
			_leave(" = %ld", PTR_ERR(key));
			return key;
		}

		/* act as anonymous user */
		_leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
		return key_get(cell->anonymous_key);
	} else {
		/* act as authorised user */
		_leave(" = {%x} [auth]", key_serial(key));
		return key;
	}
}

/*
 * Get a key when pathwalk is in rcuwalk mode.
 */
struct key *afs_request_key_rcu(struct afs_cell *cell)
{
	struct key *key;

	_enter("{%x}", key_serial(cell->anonymous_key));

	_debug("key %s", cell->anonymous_key->description);
	key = request_key_net_rcu(&key_type_rxrpc,
				  cell->anonymous_key->description,
				  cell->net->net);
	if (IS_ERR(key)) {
		if (PTR_ERR(key) != -ENOKEY) {
			_leave(" = %ld", PTR_ERR(key));
+13 −1
Original line number Diff line number Diff line
@@ -324,7 +324,7 @@ static inline struct key *request_key(struct key_type *type,
}

#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.
@@ -341,6 +341,18 @@ static inline struct key *request_key(struct key_type *type,
 */
#define request_key_net(type, description, net, callout_info) \
	request_key_tag(type, description, net->key_domain, callout_info);

/**
 * request_key_net_rcu - Request a key for a net namespace under RCU conditions
 * @type: Type of key.
 * @description: The searchable description of the key.
 * @net: The network namespace that is the key's domain of operation.
 *
 * As for request_key_rcu() except that only keys that operate the specified
 * network namespace are used.
 */
#define request_key_net_rcu(type, description, net) \
	request_key_rcu(type, description, net->key_domain);
#endif /* CONFIG_NET */

extern int wait_for_key_construction(struct key *key, bool intr);