Commit ebed9203b68a4f333ce5d17e874b26c3afcfeff1
1 parent
9fcfe0c83c
Exists in
master
and in
7 other branches
NFS: Fix an allocation-under-spinlock bug
sunrpc_cache_update() will always call detail->update() from inside the detail->hash_lock, so it cannot allocate memory. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com> Cc: stable@kernel.org
Showing 1 changed file with 15 additions and 3 deletions Side-by-side Diff
fs/nfs/dns_resolve.c
... | ... | @@ -36,6 +36,19 @@ |
36 | 36 | }; |
37 | 37 | |
38 | 38 | |
39 | +static void nfs_dns_ent_update(struct cache_head *cnew, | |
40 | + struct cache_head *ckey) | |
41 | +{ | |
42 | + struct nfs_dns_ent *new; | |
43 | + struct nfs_dns_ent *key; | |
44 | + | |
45 | + new = container_of(cnew, struct nfs_dns_ent, h); | |
46 | + key = container_of(ckey, struct nfs_dns_ent, h); | |
47 | + | |
48 | + memcpy(&new->addr, &key->addr, key->addrlen); | |
49 | + new->addrlen = key->addrlen; | |
50 | +} | |
51 | + | |
39 | 52 | static void nfs_dns_ent_init(struct cache_head *cnew, |
40 | 53 | struct cache_head *ckey) |
41 | 54 | { |
... | ... | @@ -49,8 +62,7 @@ |
49 | 62 | new->hostname = kstrndup(key->hostname, key->namelen, GFP_KERNEL); |
50 | 63 | if (new->hostname) { |
51 | 64 | new->namelen = key->namelen; |
52 | - memcpy(&new->addr, &key->addr, key->addrlen); | |
53 | - new->addrlen = key->addrlen; | |
65 | + nfs_dns_ent_update(cnew, ckey); | |
54 | 66 | } else { |
55 | 67 | new->namelen = 0; |
56 | 68 | new->addrlen = 0; |
... | ... | @@ -234,7 +246,7 @@ |
234 | 246 | .cache_show = nfs_dns_show, |
235 | 247 | .match = nfs_dns_match, |
236 | 248 | .init = nfs_dns_ent_init, |
237 | - .update = nfs_dns_ent_init, | |
249 | + .update = nfs_dns_ent_update, | |
238 | 250 | .alloc = nfs_dns_ent_alloc, |
239 | 251 | }; |
240 | 252 |