History

KEYS: Differentiate uses of rcu_dereference_key() and user_key_payload()

rcu_dereference_key() and user_key_payload() are currently being used in two different, incompatible ways: (1) As a wrapper to rcu_dereference() - when only the RCU read lock used to protect the key. (2) As a wrapper to rcu_dereference_protected() - when the key semaphor is used to protect the key and the may be being modified. Fix this by splitting both of the key wrappers to produce: (1) RCU accessors for keys when caller has the key semaphore locked: dereference_key_locked() user_key_payload_locked() (2) RCU accessors for keys when caller holds the RCU read lock: dereference_key_rcu() user_key_payload_rcu() This should fix following warning in the NFS idmapper =============================== [ INFO: suspicious RCU usage. ] 4.10.0 #1 Tainted: G W ------------------------------- ./include/keys/user-type.h:53 suspicious rcu_dereference_protected() usage! other info that might help us debug this: rcu_scheduler_active = 2, debug_locks = 0 1 lock held by mount.nfs/5987: #0: (rcu_read_lock){......}, at: [<d000000002527abc>] nfs_idmap_get_key+0x15c/0x420 [nfsv4] stack backtrace: CPU: 1 PID: 5987 Comm: mount.nfs Tainted: G W 4.10.0 #1 Call Trace: dump_stack+0xe8/0x154 (unreliable) lockdep_rcu_suspicious+0x140/0x190 nfs_idmap_get_key+0x380/0x420 [nfsv4] nfs_map_name_to_uid+0x2a0/0x3b0 [nfsv4] decode_getfattr_attrs+0xfac/0x16b0 [nfsv4] decode_getfattr_generic.constprop.106+0xbc/0x150 [nfsv4] nfs4_xdr_dec_lookup_root+0xac/0xb0 [nfsv4] rpcauth_unwrap_resp+0xe8/0x140 [sunrpc] call_decode+0x29c/0x910 [sunrpc] __rpc_execute+0x140/0x8f0 [sunrpc] rpc_run_task+0x170/0x200 [sunrpc] nfs4_call_sync_sequence+0x68/0xa0 [nfsv4] _nfs4_lookup_root.isra.44+0xd0/0xf0 [nfsv4] nfs4_lookup_root+0xe0/0x350 [nfsv4] nfs4_lookup_root_sec+0x70/0xa0 [nfsv4] nfs4_find_root_sec+0xc4/0x100 [nfsv4] nfs4_proc_get_rootfh+0x5c/0xf0 [nfsv4] nfs4_get_rootfh+0x6c/0x190 [nfsv4] nfs4_server_common_setup+0xc4/0x260 [nfsv4] nfs4_create_server+0x278/0x3c0 [nfsv4] nfs4_remote_mount+0x50/0xb0 [nfsv4] mount_fs+0x74/0x210 vfs_kern_mount+0x78/0x220 nfs_do_root_mount+0xb0/0x140 [nfsv4] nfs4_try_mount+0x60/0x100 [nfsv4] nfs_fs_mount+0x5ec/0xda0 [nfs] mount_fs+0x74/0x210 vfs_kern_mount+0x78/0x220 do_mount+0x254/0xf70 SyS_mount+0x94/0x100 system_call+0x38/0xe0

David Howells committed 9 years ago

Commit 0837e491 parent 6053dc915 files · +43 −22Browse files

Unified · Split

15 files
  1. Documentation/security/keys.txt +15 −2
  2. drivers/md/dm-crypt.c +1 −1
  3. fs/cifs/connect.c +1 −1
  4. fs/crypto/keyinfo.c +1 −1
  5. fs/ecryptfs/ecryptfs_kernel.h +1 −1
  6. fs/fscache/object-list.c +1 −1
  7. fs/nfs/nfs4idmap.c +1 −1
  8. include/keys/user-type.h +7 −2
  9. include/linux/key.h +4 −1
  10. lib/digsig.c +1 −1
  11. net/dns_resolver/dns_query.c +2 −2
  12. security/keys/dh.c +1 −1
  13. security/keys/encrypted-keys/encrypted.c +2 −2
  14. security/keys/trusted.c +2 −2
  15. security/keys/user_defined.c +3 −3
Documentation/security/keys.txt+15−2
@@ -1151,8 +1151,21 @@ access the data: · 1150 unmodified lines
1151 usage. This is called key->payload.rcu_data0. The following accessors1151 usage. This is called key->payload.rcu_data0. The following accessors
1152 wrap the RCU calls to this element:1152 wrap the RCU calls to this element:
1153 1153
1154 rcu_assign_keypointer(struct key *key, void *data);1154 (a) Set or change the first payload pointer:
1155 void *rcu_dereference_key(struct key *key);1155
1156 rcu_assign_keypointer(struct key *key, void *data);
1157
1158 (b) Read the first payload pointer with the key semaphore held:
1159
1160 [const] void *dereference_key_locked([const] struct key *key);
1161
1162 Note that the return value will inherit its constness from the key
1163 parameter. Static analysis will give an error if it things the lock
1164 isn't held.
1165
1166 (c) Read the first payload pointer with the RCU read lock held:
1167
1168 const void *dereference_key_rcu(const struct key *key);
1156 1169
1157 1170
1158===================1171===================
drivers/md/dm-crypt.c+1−1
@@ -1536,7 +1536,7 @@ static int crypt_set_keyring_key(struct crypt_config *cc, const char *key_string · 1535 unmodified lines
1536 1536
1537 down_read(&key->sem);1537 down_read(&key->sem);
1538 1538
1539 ukp = user_key_payload(key);1539 ukp = user_key_payload_locked(key);
1540 if (!ukp) {1540 if (!ukp) {
1541 up_read(&key->sem);1541 up_read(&key->sem);
1542 key_put(key);1542 key_put(key);
fs/cifs/connect.c+1−1
@@ -2455,7 +2455,7 @@ cifs_set_cifscreds(struct smb_vol *vol, struct cifs_ses *ses) · 2454 unmodified lines
2455 }2455 }
2456 2456
2457 down_read(&key->sem);2457 down_read(&key->sem);
2458 upayload = user_key_payload(key);2458 upayload = user_key_payload_locked(key);
2459 if (IS_ERR_OR_NULL(upayload)) {2459 if (IS_ERR_OR_NULL(upayload)) {
2460 rc = upayload ? PTR_ERR(upayload) : -EINVAL;2460 rc = upayload ? PTR_ERR(upayload) : -EINVAL;
2461 goto out_key_put;2461 goto out_key_put;
fs/crypto/keyinfo.c+1−1
@@ -103,7 +103,7 @@ static int validate_user_key(struct fscrypt_info *crypt_info, · 102 unmodified lines
103 goto out;103 goto out;
104 }104 }
105 down_read(&keyring_key->sem);105 down_read(&keyring_key->sem);
106 ukp = user_key_payload(keyring_key);106 ukp = user_key_payload_locked(keyring_key);
107 if (ukp->datalen != sizeof(struct fscrypt_key)) {107 if (ukp->datalen != sizeof(struct fscrypt_key)) {
108 res = -EINVAL;108 res = -EINVAL;
109 up_read(&keyring_key->sem);109 up_read(&keyring_key->sem);
fs/ecryptfs/ecryptfs_kernel.h+1−1
@@ -117,7 +117,7 @@ ecryptfs_get_key_payload_data(struct key *key) · 116 unmodified lines
117 117
118 auth_tok = ecryptfs_get_encrypted_key_payload_data(key);118 auth_tok = ecryptfs_get_encrypted_key_payload_data(key);
119 if (!auth_tok)119 if (!auth_tok)
120 return (struct ecryptfs_auth_tok *)user_key_payload(key)->data;120 return (struct ecryptfs_auth_tok *)user_key_payload_locked(key)->data;
121 else121 else
122 return auth_tok;122 return auth_tok;
123}123}
fs/fscache/object-list.c+1−1
@@ -329,7 +329,7 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) · 328 unmodified lines
329 config = 0;329 config = 0;
330 rcu_read_lock();330 rcu_read_lock();
331 331
332 confkey = user_key_payload(key);332 confkey = user_key_payload_rcu(key);
333 buf = confkey->data;333 buf = confkey->data;
334 334
335 for (len = confkey->datalen - 1; len >= 0; len--) {335 for (len = confkey->datalen - 1; len >= 0; len--) {
fs/nfs/nfs4idmap.c+1−1
@@ -316,7 +316,7 @@ static ssize_t nfs_idmap_get_key(const char *name, size_t namelen, · 315 unmodified lines
316 if (ret < 0)316 if (ret < 0)
317 goto out_up;317 goto out_up;
318 318
319 payload = user_key_payload(rkey);319 payload = user_key_payload_rcu(rkey);
320 if (IS_ERR_OR_NULL(payload)) {320 if (IS_ERR_OR_NULL(payload)) {
321 ret = PTR_ERR(payload);321 ret = PTR_ERR(payload);
322 goto out_up;322 goto out_up;
include/keys/user-type.h+7−2
@@ -48,9 +48,14 @@ extern void user_describe(const struct key *user, struct seq_file *m); · 47 unmodified lines
48extern long user_read(const struct key *key,48extern long user_read(const struct key *key,
49 char __user *buffer, size_t buflen);49 char __user *buffer, size_t buflen);
50 50
51static inline const struct user_key_payload *user_key_payload(const struct key *key)51static inline const struct user_key_payload *user_key_payload_rcu(const struct key *key)
52{52{
53 return (struct user_key_payload *)rcu_dereference_key(key);53 return (struct user_key_payload *)dereference_key_rcu(key);
54}
55
56static inline struct user_key_payload *user_key_payload_locked(const struct key *key)
57{
58 return (struct user_key_payload *)dereference_key_locked((struct key *)key);
54}59}
55 60
56#endif /* CONFIG_KEYS */61#endif /* CONFIG_KEYS */
include/linux/key.h+4−1
@@ -354,7 +354,10 @@ static inline bool key_is_instantiated(const struct key *key) · 353 unmodified lines
354 !test_bit(KEY_FLAG_NEGATIVE, &key->flags);354 !test_bit(KEY_FLAG_NEGATIVE, &key->flags);
355}355}
356 356
357#define rcu_dereference_key(KEY) \357#define dereference_key_rcu(KEY) \
358 (rcu_dereference((KEY)->payload.rcu_data0))
359
360#define dereference_key_locked(KEY) \
358 (rcu_dereference_protected((KEY)->payload.rcu_data0, \361 (rcu_dereference_protected((KEY)->payload.rcu_data0, \
359 rwsem_is_locked(&((struct key *)(KEY))->sem)))362 rwsem_is_locked(&((struct key *)(KEY))->sem)))
360 363
lib/digsig.c+1−1
@@ -85,7 +85,7 @@ static int digsig_verify_rsa(struct key *key, · 84 unmodified lines
85 struct pubkey_hdr *pkh;85 struct pubkey_hdr *pkh;
86 86
87 down_read(&key->sem);87 down_read(&key->sem);
88 ukp = user_key_payload(key);88 ukp = user_key_payload_locked(key);
89 89
90 if (ukp->datalen < sizeof(*pkh))90 if (ukp->datalen < sizeof(*pkh))
91 goto err1;91 goto err1;
net/dns_resolver/dns_query.c+2−2
@@ -70,7 +70,7 @@ int dns_query(const char *type, const char *name, size_t namelen, · 69 unmodified lines
70 const char *options, char **_result, time64_t *_expiry)70 const char *options, char **_result, time64_t *_expiry)
71{71{
72 struct key *rkey;72 struct key *rkey;
73 const struct user_key_payload *upayload;73 struct user_key_payload *upayload;
74 const struct cred *saved_cred;74 const struct cred *saved_cred;
75 size_t typelen, desclen;75 size_t typelen, desclen;
76 char *desc, *cp;76 char *desc, *cp;
@@ -141,7 +141,7 @@ int dns_query(const char *type, const char *name, size_t namelen, · 64 unmodified lines
141 if (ret)141 if (ret)
142 goto put;142 goto put;
143 143
144 upayload = user_key_payload(rkey);144 upayload = user_key_payload_locked(rkey);
145 len = upayload->datalen;145 len = upayload->datalen;
146 146
147 ret = -ENOMEM;147 ret = -ENOMEM;
security/keys/dh.c+1−1
@@ -55,7 +55,7 @@ static ssize_t mpi_from_key(key_serial_t keyid, size_t maxlen, MPI *mpi) · 54 unmodified lines
55 if (status == 0) {55 if (status == 0) {
56 const struct user_key_payload *payload;56 const struct user_key_payload *payload;
57 57
58 payload = user_key_payload(key);58 payload = user_key_payload_locked(key);
59 59
60 if (maxlen == 0) {60 if (maxlen == 0) {
61 *mpi = NULL;61 *mpi = NULL;
security/keys/encrypted-keys/encrypted.c+2−2
@@ -314,7 +314,7 @@ static struct key *request_user_key(const char *master_desc, const u8 **master_k · 313 unmodified lines
314 goto error;314 goto error;
315 315
316 down_read(&ukey->sem);316 down_read(&ukey->sem);
317 upayload = user_key_payload(ukey);317 upayload = user_key_payload_locked(ukey);
318 *master_key = upayload->data;318 *master_key = upayload->data;
319 *master_keylen = upayload->datalen;319 *master_keylen = upayload->datalen;
320error:320error:
@@ -926,7 +926,7 @@ static long encrypted_read(const struct key *key, char __user *buffer, · 605 unmodified lines
926 size_t asciiblob_len;926 size_t asciiblob_len;
927 int ret;927 int ret;
928 928
929 epayload = rcu_dereference_key(key);929 epayload = dereference_key_locked(key);
930 930
931 /* returns the hex encoded iv, encrypted-data, and hmac as ascii */931 /* returns the hex encoded iv, encrypted-data, and hmac as ascii */
932 asciiblob_len = epayload->datablob_len + ivsize + 1932 asciiblob_len = epayload->datablob_len + ivsize + 1
security/keys/trusted.c+2−2
@@ -1140,12 +1140,12 @@ out: · 1139 unmodified lines
1140static long trusted_read(const struct key *key, char __user *buffer,1140static long trusted_read(const struct key *key, char __user *buffer,
1141 size_t buflen)1141 size_t buflen)
1142{1142{
1143 struct trusted_key_payload *p;1143 const struct trusted_key_payload *p;
1144 char *ascii_buf;1144 char *ascii_buf;
1145 char *bufp;1145 char *bufp;
1146 int i;1146 int i;
1147 1147
1148 p = rcu_dereference_key(key);1148 p = dereference_key_locked(key);
1149 if (!p)1149 if (!p)
1150 return -EINVAL;1150 return -EINVAL;
1151 if (!buffer || buflen <= 0)1151 if (!buffer || buflen <= 0)
security/keys/user_defined.c+3−3
@@ -107,7 +107,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) · 106 unmodified lines
107 /* attach the new data, displacing the old */107 /* attach the new data, displacing the old */
108 key->expiry = prep->expiry;108 key->expiry = prep->expiry;
109 if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))109 if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags))
110 zap = rcu_dereference_key(key);110 zap = dereference_key_locked(key);
111 rcu_assign_keypointer(key, prep->payload.data[0]);111 rcu_assign_keypointer(key, prep->payload.data[0]);
112 prep->payload.data[0] = NULL;112 prep->payload.data[0] = NULL;
113 113
@@ -123,7 +123,7 @@ EXPORT_SYMBOL_GPL(user_update); · 9 unmodified lines
123 */123 */
124void user_revoke(struct key *key)124void user_revoke(struct key *key)
125{125{
126 struct user_key_payload *upayload = key->payload.data[0];126 struct user_key_payload *upayload = user_key_payload_locked(key);
127 127
128 /* clear the quota */128 /* clear the quota */
129 key_payload_reserve(key, 0);129 key_payload_reserve(key, 0);
@@ -169,7 +169,7 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) · 39 unmodified lines
169 const struct user_key_payload *upayload;169 const struct user_key_payload *upayload;
170 long ret;170 long ret;
171 171
172 upayload = user_key_payload(key);172 upayload = user_key_payload_locked(key);
173 ret = upayload->datalen;173 ret = upayload->datalen;
174 174
175 /* we can return the data as is */175 /* we can return the data as is */