lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Fri, 11 Dec 2015 11:00:28 +0800
From:	Stefan Hajnoczi <stefanha@...hat.com>
To:	Alex Bennée <alex.bennee@...aro.org>
Cc:	kvm@...r.kernel.org, "Michael S. Tsirkin" <mst@...hat.com>,
	netdev@...r.kernel.org, virtualization@...ts.linux-foundation.org,
	Matt Benjamin <mbenjamin@...hat.com>,
	Asias He <asias@...hat.com>,
	Christoffer Dall <christoffer.dall@...aro.org>,
	matt.ma@...aro.org
Subject: Re: [PATCH v3 2/4] VSOCK: Introduce virtio-vsock.ko

On Thu, Dec 10, 2015 at 09:23:25PM +0000, Alex Bennée wrote:
> Stefan Hajnoczi <stefanha@...hat.com> writes:
> 
> > From: Asias He <asias@...hat.com>
> >
> > VM sockets virtio transport implementation. This module runs in guest
> > kernel.
> 
> checkpatch warns on a bunch of whitespace/tab issues.

Will fix in the next version.

> > +struct virtio_vsock {
> > +	/* Virtio device */
> > +	struct virtio_device *vdev;
> > +	/* Virtio virtqueue */
> > +	struct virtqueue *vqs[VSOCK_VQ_MAX];
> > +	/* Wait queue for send pkt */
> > +	wait_queue_head_t queue_wait;
> > +	/* Work item to send pkt */
> > +	struct work_struct tx_work;
> > +	/* Work item to recv pkt */
> > +	struct work_struct rx_work;
> > +	/* Mutex to protect send pkt*/
> > +	struct mutex tx_lock;
> > +	/* Mutex to protect recv pkt*/
> > +	struct mutex rx_lock;
> 
> Further down I got confused by what lock was what and exactly what was
> being protected. If the receive and transmit paths touch separate things
> it might be worth re-arranging the structure to make it clearer, eg:
> 
>    /* The transmit path is protected by tx_lock */
>    struct mutex tx_lock;
>    struct work_struct tx_work;
>    ..
>    ..
> 
>    /* The receive path is protected by rx_lock */
>    wait_queue_head_t queue_wait;
>    ..
>    ..
> 
>  Which might make things a little clearer. Then all the redundant
>  information in the comments can be removed. I don't need to know what
>  is a Virtio device, virtqueue or wait_queue etc as they are implicit in
>  the structure name.

Thanks, that is a nice idea.

> > +	mutex_lock(&vsock->tx_lock);
> > +	while ((ret = virtqueue_add_sgs(vq, sgs, out_sg, in_sg, pkt,
> > +					GFP_KERNEL)) < 0) {
> > +		prepare_to_wait_exclusive(&vsock->queue_wait, &wait,
> > +					  TASK_UNINTERRUPTIBLE);
> > +		mutex_unlock(&vsock->tx_lock);
> > +		schedule();
> > +		mutex_lock(&vsock->tx_lock);
> > +		finish_wait(&vsock->queue_wait, &wait);
> > +	}
> > +	virtqueue_kick(vq);
> > +	mutex_unlock(&vsock->tx_lock);
> 
> What are we protecting with tx_lock here? See comments above about
> making the lock usage semantics clearer.

vq (vsock->vqs[VSOCK_VQ_TX]) is being protected.  Concurrent calls to
virtqueue_add_sgs() are not allowed.

> > +
> > +	return pkt_len;
> > +}
> > +
> > +static struct virtio_transport_pkt_ops virtio_ops = {
> > +	.send_pkt = virtio_transport_send_pkt,
> > +};
> > +
> > +static void virtio_vsock_rx_fill(struct virtio_vsock *vsock)
> > +{
> > +	int buf_len = VIRTIO_VSOCK_DEFAULT_RX_BUF_SIZE;
> > +	struct virtio_vsock_pkt *pkt;
> > +	struct scatterlist hdr, buf, *sgs[2];
> > +	struct virtqueue *vq;
> > +	int ret;
> > +
> > +	vq = vsock->vqs[VSOCK_VQ_RX];
> > +
> > +	do {
> > +		pkt = kzalloc(sizeof(*pkt), GFP_KERNEL);
> > +		if (!pkt) {
> > +			pr_debug("%s: fail to allocate pkt\n", __func__);
> > +			goto out;
> > +		}
> > +
> > +		/* TODO: use mergeable rx buffer */
> 
> TODO's should end up in merged code.

Will fix in next revision.

> > +		pkt->buf = kmalloc(buf_len, GFP_KERNEL);
> > +		if (!pkt->buf) {
> > +			pr_debug("%s: fail to allocate pkt->buf\n", __func__);
> > +			goto err;
> > +		}
> > +
> > +		sg_init_one(&hdr, &pkt->hdr, sizeof(pkt->hdr));
> > +		sgs[0] = &hdr;
> > +
> > +		sg_init_one(&buf, pkt->buf, buf_len);
> > +	        sgs[1] = &buf;
> > +		ret = virtqueue_add_sgs(vq, sgs, 0, 2, pkt, GFP_KERNEL);
> > +		if (ret)
> > +			goto err;
> > +		vsock->rx_buf_nr++;
> > +	} while (vq->num_free);
> > +	if (vsock->rx_buf_nr > vsock->rx_buf_max_nr)
> > +		vsock->rx_buf_max_nr = vsock->rx_buf_nr;
> > +out:
> > +	virtqueue_kick(vq);
> > +	return;
> > +err:
> > +	virtqueue_kick(vq);
> > +	virtio_transport_free_pkt(pkt);
> 
> You could free the pkt memory at the fail site and just have one exit path.

Okay, I agree the err label is of marginal use.  Let's get rid of it.

> 
> > +	return;
> > +}
> > +
> > +static void virtio_transport_send_pkt_work(struct work_struct *work)
> > +{
> > +	struct virtio_vsock *vsock =
> > +		container_of(work, struct virtio_vsock, tx_work);
> > +	struct virtio_vsock_pkt *pkt;
> > +	bool added = false;
> > +	struct virtqueue *vq;
> > +	unsigned int len;
> > +	struct sock *sk;
> > +
> > +	vq = vsock->vqs[VSOCK_VQ_TX];
> > +	mutex_lock(&vsock->tx_lock);
> > +	do {
> 
> You can move the declarations of pkt/len into the do block.

Okay.

> 
> > +		virtqueue_disable_cb(vq);
> > +		while ((pkt = virtqueue_get_buf(vq, &len)) != NULL) {
> 
> And the sk declaration here

Okay.

> > +static void virtio_transport_recv_pkt_work(struct work_struct *work)
> > +{
> > +	struct virtio_vsock *vsock =
> > +		container_of(work, struct virtio_vsock, rx_work);
> > +	struct virtio_vsock_pkt *pkt;
> > +	struct virtqueue *vq;
> > +	unsigned int len;
> 
> Same as above for pkt, len.

Okay.

> > +	vsock = kzalloc(sizeof(*vsock), GFP_KERNEL);
> > +	if (!vsock) {
> > +		ret = -ENOMEM;
> > +		goto out;
> 
> Won't this attempt to kfree a NULL vsock?

kfree(NULL) is a nop so this is safe.

Download attachment "signature.asc" of type "application/pgp-signature" (474 bytes)

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ