Commit ebed9203b68a4f333ce5d17e874b26c3afcfeff1

Authored by Trond Myklebust
1 parent 9fcfe0c83c

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