summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2019-05-20 03:48:46 -0400
committerDavid Howells <dhowells@redhat.com>2019-09-02 06:43:54 -0400
commit8b6a666a97544bf307190a05947742b8357aa962 (patch)
tree16c344dabab751936bd81e720cc58620013976be
parent23a289137ab82daeea826eeb9556c6f89b1fcd67 (diff)
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: David Howells <dhowells@redhat.com>
-rw-r--r--fs/afs/internal.h1
-rw-r--r--fs/afs/security.c33
-rw-r--r--include/linux/key.h14
3 files changed, 45 insertions, 3 deletions
diff --git a/fs/afs/internal.h b/fs/afs/internal.h
index f66a3be12fd6..9cdfabaeaa0b 100644
--- a/fs/afs/internal.h
+++ b/fs/afs/internal.h
@@ -1217,6 +1217,7 @@ extern void afs_cache_permit(struct afs_vnode *, struct key *, unsigned int,
1217 struct afs_status_cb *); 1217 struct afs_status_cb *);
1218extern void afs_zap_permits(struct rcu_head *); 1218extern void afs_zap_permits(struct rcu_head *);
1219extern struct key *afs_request_key(struct afs_cell *); 1219extern struct key *afs_request_key(struct afs_cell *);
1220extern struct key *afs_request_key_rcu(struct afs_cell *);
1220extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *); 1221extern int afs_check_permit(struct afs_vnode *, struct key *, afs_access_t *);
1221extern int afs_permission(struct inode *, int); 1222extern int afs_permission(struct inode *, int);
1222extern void __exit afs_clean_up_permit_cache(void); 1223extern void __exit afs_clean_up_permit_cache(void);
diff --git a/fs/afs/security.c b/fs/afs/security.c
index 71e71c07568f..ef2fd34ba282 100644
--- a/fs/afs/security.c
+++ b/fs/afs/security.c
@@ -27,8 +27,37 @@ struct key *afs_request_key(struct afs_cell *cell)
27 _enter("{%x}", key_serial(cell->anonymous_key)); 27 _enter("{%x}", key_serial(cell->anonymous_key));
28 28
29 _debug("key %s", cell->anonymous_key->description); 29 _debug("key %s", cell->anonymous_key->description);
30 key = request_key(&key_type_rxrpc, cell->anonymous_key->description, 30 key = request_key_net(&key_type_rxrpc, cell->anonymous_key->description,
31 NULL); 31 cell->net->net, NULL);
32 if (IS_ERR(key)) {
33 if (PTR_ERR(key) != -ENOKEY) {
34 _leave(" = %ld", PTR_ERR(key));
35 return key;
36 }
37
38 /* act as anonymous user */
39 _leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
40 return key_get(cell->anonymous_key);
41 } else {
42 /* act as authorised user */
43 _leave(" = {%x} [auth]", key_serial(key));
44 return key;
45 }
46}
47
48/*
49 * Get a key when pathwalk is in rcuwalk mode.
50 */
51struct key *afs_request_key_rcu(struct afs_cell *cell)
52{
53 struct key *key;
54
55 _enter("{%x}", key_serial(cell->anonymous_key));
56
57 _debug("key %s", cell->anonymous_key->description);
58 key = request_key_net_rcu(&key_type_rxrpc,
59 cell->anonymous_key->description,
60 cell->net->net);
32 if (IS_ERR(key)) { 61 if (IS_ERR(key)) {
33 if (PTR_ERR(key) != -ENOKEY) { 62 if (PTR_ERR(key) != -ENOKEY) {
34 _leave(" = %ld", PTR_ERR(key)); 63 _leave(" = %ld", PTR_ERR(key));
diff --git a/include/linux/key.h b/include/linux/key.h
index 50028338a4cc..6cf8e71cf8b7 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -324,7 +324,7 @@ static inline struct key *request_key(struct key_type *type,
324} 324}
325 325
326#ifdef CONFIG_NET 326#ifdef CONFIG_NET
327/* 327/**
328 * request_key_net - Request a key for a net namespace and wait for construction 328 * request_key_net - Request a key for a net namespace and wait for construction
329 * @type: Type of key. 329 * @type: Type of key.
330 * @description: The searchable description of the key. 330 * @description: The searchable description of the key.
@@ -341,6 +341,18 @@ static inline struct key *request_key(struct key_type *type,
341 */ 341 */
342#define request_key_net(type, description, net, callout_info) \ 342#define request_key_net(type, description, net, callout_info) \
343 request_key_tag(type, description, net->key_domain, callout_info); 343 request_key_tag(type, description, net->key_domain, callout_info);
344
345/**
346 * request_key_net_rcu - Request a key for a net namespace under RCU conditions
347 * @type: Type of key.
348 * @description: The searchable description of the key.
349 * @net: The network namespace that is the key's domain of operation.
350 *
351 * As for request_key_rcu() except that only keys that operate the specified
352 * network namespace are used.
353 */
354#define request_key_net_rcu(type, description, net) \
355 request_key_rcu(type, description, net->key_domain);
344#endif /* CONFIG_NET */ 356#endif /* CONFIG_NET */
345 357
346extern int wait_for_key_construction(struct key *key, bool intr); 358extern int wait_for_key_construction(struct key *key, bool intr);