]>
Commit | Line | Data |
---|---|---|
4fa5b95e GKH |
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; |