]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
afs: Provide an RCU-capable key lookup
authorDavid Howells <dhowells@redhat.com>
Mon, 20 May 2019 07:48:46 +0000 (08:48 +0100)
committerDavid Howells <dhowells@redhat.com>
Mon, 2 Sep 2019 10:43:54 +0000 (11:43 +0100)
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>
fs/afs/internal.h
fs/afs/security.c
include/linux/key.h

index f66a3be12fd6360bb2c6d9cedc6960f529841ac8..9cdfabaeaa0b5a113b07805528333be28e65f976 100644 (file)
@@ -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);
index 71e71c07568f6f0675662ae976a0061c7132b8c7..ef2fd34ba28283eda43dc6ea9540ec15a4f0ce2a 100644 (file)
@@ -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));
index 50028338a4cc081dc0f9dfcda8394804962dc1de..6cf8e71cf8b7c8de3903a29e8195129423de0c02 100644 (file)
@@ -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);