]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-4.4/sunrpc-don-t-mark-uninitialised-items-as-valid.patch
4.4-stable patches
[thirdparty/kernel/stable-queue.git] / queue-4.4 / sunrpc-don-t-mark-uninitialised-items-as-valid.patch
CommitLineData
4fa5b95e
GKH
1From d58431eacb226222430940134d97bfd72f292fcd Mon Sep 17 00:00:00 2001
2From: NeilBrown <neilb@suse.com>
3Date: Fri, 5 Apr 2019 11:34:40 +1100
4Subject: sunrpc: don't mark uninitialised items as VALID.
5
6From: NeilBrown <neilb@suse.com>
7
8commit d58431eacb226222430940134d97bfd72f292fcd upstream.
9
10A recent commit added a call to cache_fresh_locked()
11when an expired item was found.
12The call sets the CACHE_VALID flag, so it is important
13that the item actually is valid.
14There are two ways it could be valid:
151/ If ->update has been called to fill in relevant content
162/ if CACHE_NEGATIVE is set, to say that content doesn't exist.
17
18An expired item that is waiting for an update will be neither.
19Setting CACHE_VALID will mean that a subsequent call to cache_put()
20will be likely to dereference uninitialised pointers.
21
22So we must make sure the item is valid, and we already have code to do
23that in try_to_negate_entry(). This takes the hash lock and so cannot
24be used directly, so take out the two lines that we need and use them.
25
26Now cache_fresh_locked() is certain to be called only on
27a valid item.
28
29Cc: stable@kernel.org # 2.6.35
30Fixes: 4ecd55ea0742 ("sunrpc: fix cache_head leak due to queued request")
31Signed-off-by: NeilBrown <neilb@suse.com>
32Signed-off-by: J. Bruce Fields <bfields@redhat.com>
33Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34
35---
36 net/sunrpc/cache.c | 3 +++
37 1 file changed, 3 insertions(+)
38
39--- a/net/sunrpc/cache.c
40+++ b/net/sunrpc/cache.c
41@@ -54,6 +54,7 @@ static void cache_init(struct cache_head
42 h->last_refresh = now;
43 }
44
45+static inline int cache_is_valid(struct cache_head *h);
46 static void cache_fresh_locked(struct cache_head *head, time_t expiry,
47 struct cache_detail *detail);
48 static void cache_fresh_unlocked(struct cache_head *head,
49@@ -100,6 +101,8 @@ struct cache_head *sunrpc_cache_lookup(s
50 if (cache_is_expired(detail, tmp)) {
51 hlist_del_init(&tmp->cache_list);
52 detail->entries --;
53+ if (cache_is_valid(tmp) == -EAGAIN)
54+ set_bit(CACHE_NEGATIVE, &tmp->flags);
55 cache_fresh_locked(tmp, 0, detail);
56 freeme = tmp;
57 break;