Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

pnfs/blocklayout: serialize GETDEVICEINFO calls

The rpc_pipefs code isn't thread safe, leading to occasional use after
frees when running xfstests generic/241 (dbench).

Signed-off-by: Christoph Hellwig <hch@lst.de>
Link: http://lkml.kernel.org/r/1411740170-18611-2-git-send-email-hch@lst.de
Cc: stable@vger.kernel.org # 3.17.x
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>

authored by

Christoph Hellwig and committed by
Trond Myklebust
e0d4ed71 8c393f9a

+10 -5
+9 -5
fs/nfs/blocklayout/rpc_pipefs.c
··· 65 65 66 66 dprintk("%s CREATING PIPEFS MESSAGE\n", __func__); 67 67 68 + mutex_lock(&nn->bl_mutex); 68 69 bl_pipe_msg.bl_wq = &nn->bl_wq; 69 70 70 71 b->simple.len += 4; /* single volume */ 71 72 if (b->simple.len > PAGE_SIZE) 72 - return -EIO; 73 + goto out_unlock; 73 74 74 75 memset(msg, 0, sizeof(*msg)); 75 76 msg->len = sizeof(*bl_msg) + b->simple.len; 76 77 msg->data = kzalloc(msg->len, gfp_mask); 77 78 if (!msg->data) 78 - goto out; 79 + goto out_free_data; 79 80 80 81 bl_msg = msg->data; 81 82 bl_msg->type = BL_DEVICE_MOUNT, ··· 88 87 rc = rpc_queue_upcall(nn->bl_device_pipe, msg); 89 88 if (rc < 0) { 90 89 remove_wait_queue(&nn->bl_wq, &wq); 91 - goto out; 90 + goto out_free_data; 92 91 } 93 92 94 93 set_current_state(TASK_UNINTERRUPTIBLE); ··· 98 97 if (reply->status != BL_DEVICE_REQUEST_PROC) { 99 98 printk(KERN_WARNING "%s failed to decode device: %d\n", 100 99 __func__, reply->status); 101 - goto out; 100 + goto out_free_data; 102 101 } 103 102 104 103 dev = MKDEV(reply->major, reply->minor); 105 - out: 104 + out_free_data: 106 105 kfree(msg->data); 106 + out_unlock: 107 + mutex_unlock(&nn->bl_mutex); 107 108 return dev; 108 109 } 109 110 ··· 235 232 struct nfs_net *nn = net_generic(net, nfs_net_id); 236 233 struct dentry *dentry; 237 234 235 + mutex_init(&nn->bl_mutex); 238 236 init_waitqueue_head(&nn->bl_wq); 239 237 nn->bl_device_pipe = rpc_mkpipe_data(&bl_upcall_ops, 0); 240 238 if (IS_ERR(nn->bl_device_pipe))
+1
fs/nfs/netns.h
··· 19 19 struct rpc_pipe *bl_device_pipe; 20 20 struct bl_dev_msg bl_mount_reply; 21 21 wait_queue_head_t bl_wq; 22 + struct mutex bl_mutex; 22 23 struct list_head nfs_client_list; 23 24 struct list_head nfs_volume_list; 24 25 #if IS_ENABLED(CONFIG_NFS_V4)