Skip to content

Commit b503de2

Browse files
vwaxwsakernel
authored andcommitted
i2c: virtio: fix completion handling
The driver currently assumes that the notify callback is only received when the device is done with all the queued buffers. However, this is not true, since the notify callback could be called without any of the queued buffers being completed (for example, with virtio-pci and shared interrupts) or with only some of the buffers being completed (since the driver makes them available to the device in multiple separate virtqueue_add_sgs() calls). This can lead to incorrect data on the I2C bus or memory corruption in the guest if the device operates on buffers which are have been freed by the driver. (The WARN_ON in the driver is also triggered.) BUG kmalloc-128 (Tainted: G W ): Poison overwritten First byte 0x0 instead of 0x6b Allocated in i2cdev_ioctl_rdwr+0x9d/0x1de age=243 cpu=0 pid=28 memdup_user+0x2e/0xbd i2cdev_ioctl_rdwr+0x9d/0x1de i2cdev_ioctl+0x247/0x2ed vfs_ioctl+0x21/0x30 sys_ioctl+0xb18/0xb41 Freed in i2cdev_ioctl_rdwr+0x1bb/0x1de age=68 cpu=0 pid=28 kfree+0x1bd/0x1cc i2cdev_ioctl_rdwr+0x1bb/0x1de i2cdev_ioctl+0x247/0x2ed vfs_ioctl+0x21/0x30 sys_ioctl+0xb18/0xb41 Fix this by calling virtio_get_buf() from the notify handler like other virtio drivers and by actually waiting for all the buffers to be completed. Fixes: 3cfc883 ("i2c: virtio: add a virtio i2c frontend driver") Acked-by: Viresh Kumar <[email protected]> Signed-off-by: Vincent Whitchurch <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 0fcfb00 commit b503de2

File tree

1 file changed

+12
-20
lines changed

1 file changed

+12
-20
lines changed

drivers/i2c/busses/i2c-virtio.c

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,34 +22,36 @@
2222
/**
2323
* struct virtio_i2c - virtio I2C data
2424
* @vdev: virtio device for this controller
25-
* @completion: completion of virtio I2C message
2625
* @adap: I2C adapter for this controller
2726
* @vq: the virtio virtqueue for communication
2827
*/
2928
struct virtio_i2c {
3029
struct virtio_device *vdev;
31-
struct completion completion;
3230
struct i2c_adapter adap;
3331
struct virtqueue *vq;
3432
};
3533

3634
/**
3735
* struct virtio_i2c_req - the virtio I2C request structure
36+
* @completion: completion of virtio I2C message
3837
* @out_hdr: the OUT header of the virtio I2C message
3938
* @buf: the buffer into which data is read, or from which it's written
4039
* @in_hdr: the IN header of the virtio I2C message
4140
*/
4241
struct virtio_i2c_req {
42+
struct completion completion;
4343
struct virtio_i2c_out_hdr out_hdr ____cacheline_aligned;
4444
uint8_t *buf ____cacheline_aligned;
4545
struct virtio_i2c_in_hdr in_hdr ____cacheline_aligned;
4646
};
4747

4848
static void virtio_i2c_msg_done(struct virtqueue *vq)
4949
{
50-
struct virtio_i2c *vi = vq->vdev->priv;
50+
struct virtio_i2c_req *req;
51+
unsigned int len;
5152

52-
complete(&vi->completion);
53+
while ((req = virtqueue_get_buf(vq, &len)))
54+
complete(&req->completion);
5355
}
5456

5557
static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
@@ -62,6 +64,8 @@ static int virtio_i2c_prepare_reqs(struct virtqueue *vq,
6264
for (i = 0; i < num; i++) {
6365
int outcnt = 0, incnt = 0;
6466

67+
init_completion(&reqs[i].completion);
68+
6569
/*
6670
* Only 7-bit mode supported for this moment. For the address
6771
* format, Please check the Virtio I2C Specification.
@@ -106,21 +110,15 @@ static int virtio_i2c_complete_reqs(struct virtqueue *vq,
106110
struct virtio_i2c_req *reqs,
107111
struct i2c_msg *msgs, int num)
108112
{
109-
struct virtio_i2c_req *req;
110113
bool failed = false;
111-
unsigned int len;
112114
int i, j = 0;
113115

114116
for (i = 0; i < num; i++) {
115-
/* Detach the ith request from the vq */
116-
req = virtqueue_get_buf(vq, &len);
117+
struct virtio_i2c_req *req = &reqs[i];
117118

118-
/*
119-
* Condition req == &reqs[i] should always meet since we have
120-
* total num requests in the vq. reqs[i] can never be NULL here.
121-
*/
122-
if (!failed && (WARN_ON(req != &reqs[i]) ||
123-
req->in_hdr.status != VIRTIO_I2C_MSG_OK))
119+
wait_for_completion(&req->completion);
120+
121+
if (!failed && req->in_hdr.status != VIRTIO_I2C_MSG_OK)
124122
failed = true;
125123

126124
i2c_put_dma_safe_msg_buf(reqs[i].buf, &msgs[i], !failed);
@@ -156,12 +154,8 @@ static int virtio_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
156154
* remote here to clear the virtqueue, so we can try another set of
157155
* messages later on.
158156
*/
159-
160-
reinit_completion(&vi->completion);
161157
virtqueue_kick(vq);
162158

163-
wait_for_completion(&vi->completion);
164-
165159
count = virtio_i2c_complete_reqs(vq, reqs, msgs, count);
166160

167161
err_free:
@@ -210,8 +204,6 @@ static int virtio_i2c_probe(struct virtio_device *vdev)
210204
vdev->priv = vi;
211205
vi->vdev = vdev;
212206

213-
init_completion(&vi->completion);
214-
215207
ret = virtio_i2c_setup_vqs(vi);
216208
if (ret)
217209
return ret;

0 commit comments

Comments
 (0)