summaryrefslogtreecommitdiffstats
path: root/net/dns_resolver
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2017-10-04 16:43:25 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-10-27 10:23:18 +0200
commit8a004caec12bf241e567e3640401256cc9bc2e45 (patch)
treeadd474bceb7e5d7c0add66d2eec7d56398dc47e0 /net/dns_resolver
parent1dda04c761abf006402f7f5e9adb11f9044731c8 (diff)
downloadlinux-stable-8a004caec12bf241e567e3640401256cc9bc2e45.tar.gz
linux-stable-8a004caec12bf241e567e3640401256cc9bc2e45.tar.bz2
linux-stable-8a004caec12bf241e567e3640401256cc9bc2e45.zip
KEYS: Fix race between updating and finding a negative key
commit 363b02dab09b3226f3bd1420dad9c72b79a42a76 upstream. Consolidate KEY_FLAG_INSTANTIATED, KEY_FLAG_NEGATIVE and the rejection error into one field such that: (1) The instantiation state can be modified/read atomically. (2) The error can be accessed atomically with the state. (3) The error isn't stored unioned with the payload pointers. This deals with the problem that the state is spread over three different objects (two bits and a separate variable) and reading or updating them atomically isn't practical, given that not only can uninstantiated keys change into instantiated or rejected keys, but rejected keys can also turn into instantiated keys - and someone accessing the key might not be using any locking. The main side effect of this problem is that what was held in the payload may change, depending on the state. For instance, you might observe the key to be in the rejected state. You then read the cached error, but if the key semaphore wasn't locked, the key might've become instantiated between the two reads - and you might now have something in hand that isn't actually an error code. The state is now KEY_IS_UNINSTANTIATED, KEY_IS_POSITIVE or a negative error code if the key is negatively instantiated. The key_is_instantiated() function is replaced with key_is_positive() to avoid confusion as negative keys are also 'instantiated'. Additionally, barriering is included: (1) Order payload-set before state-set during instantiation. (2) Order state-read before payload-read when using the key. Further separate barriering is necessary if RCU is being used to access the payload content after reading the payload pointers. Fixes: 146aa8b1453b ("KEYS: Merge the type-specific data with the payload data") Reported-by: Eric Biggers <ebiggers@google.com> Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net/dns_resolver')
-rw-r--r--net/dns_resolver/dns_key.c2
1 files changed, 1 insertions, 1 deletions
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c
index c79b85eb4d4c..6abc5012200b 100644
--- a/net/dns_resolver/dns_key.c
+++ b/net/dns_resolver/dns_key.c
@@ -224,7 +224,7 @@ static int dns_resolver_match_preparse(struct key_match_data *match_data)
static void dns_resolver_describe(const struct key *key, struct seq_file *m)
{
seq_puts(m, key->description);
- if (key_is_instantiated(key)) {
+ if (key_is_positive(key)) {
int err = PTR_ERR(key->payload.data[dns_key_error]);
if (err)