]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - 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
1 From d58431eacb226222430940134d97bfd72f292fcd Mon Sep 17 00:00:00 2001
2 From: NeilBrown <neilb@suse.com>
3 Date: Fri, 5 Apr 2019 11:34:40 +1100
4 Subject: sunrpc: don't mark uninitialised items as VALID.
5
6 From: NeilBrown <neilb@suse.com>
7
8 commit d58431eacb226222430940134d97bfd72f292fcd upstream.
9
10 A recent commit added a call to cache_fresh_locked()
11 when an expired item was found.
12 The call sets the CACHE_VALID flag, so it is important
13 that the item actually is valid.
14 There are two ways it could be valid:
15 1/ If ->update has been called to fill in relevant content
16 2/ if CACHE_NEGATIVE is set, to say that content doesn't exist.
17
18 An expired item that is waiting for an update will be neither.
19 Setting CACHE_VALID will mean that a subsequent call to cache_put()
20 will be likely to dereference uninitialised pointers.
21
22 So we must make sure the item is valid, and we already have code to do
23 that in try_to_negate_entry(). This takes the hash lock and so cannot
24 be used directly, so take out the two lines that we need and use them.
25
26 Now cache_fresh_locked() is certain to be called only on
27 a valid item.
28
29 Cc: stable@kernel.org # 2.6.35
30 Fixes: 4ecd55ea0742 ("sunrpc: fix cache_head leak due to queued request")
31 Signed-off-by: NeilBrown <neilb@suse.com>
32 Signed-off-by: J. Bruce Fields <bfields@redhat.com>
33 Signed-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;