lkml.org 
[lkml]   [2017]   [Jul]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
/
SubjectRe: [PATCH v2 11/13] xen/pvcalls: implement release command
From
Date

> +int pvcalls_front_release(struct socket *sock)
> +{
> + struct pvcalls_bedata *bedata;
> + struct sock_mapping *map;
> + int req_id, notify;
> + struct xen_pvcalls_request *req;
> +
> + if (!pvcalls_front_dev)
> + return -EIO;
> + bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
> + if (!bedata)
> + return -EIO;

Some (all?) other ops don't check bedata validity. Should they all do?

> +
> + if (sock->sk == NULL)
> + return 0;
> +
> + map = (struct sock_mapping *) READ_ONCE(sock->sk->sk_send_head);
> + if (map == NULL)
> + return 0;
> +
> + spin_lock(&bedata->pvcallss_lock);
> + req_id = bedata->ring.req_prod_pvt & (RING_SIZE(&bedata->ring) - 1);
> + if (RING_FULL(&bedata->ring) ||
> + READ_ONCE(bedata->rsp[req_id].req_id) != PVCALLS_INVALID_ID) {
> + spin_unlock(&bedata->pvcallss_lock);
> + return -EAGAIN;
> + }
> + WRITE_ONCE(sock->sk->sk_send_head, NULL);
> +
> + req = RING_GET_REQUEST(&bedata->ring, req_id);
> + req->req_id = req_id;
> + req->cmd = PVCALLS_RELEASE;
> + req->u.release.id = (uint64_t)sock;
> +
> + bedata->ring.req_prod_pvt++;
> + RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&bedata->ring, notify);
> + spin_unlock(&bedata->pvcallss_lock);
> + if (notify)
> + notify_remote_via_irq(bedata->irq);
> +
> + wait_event(bedata->inflight_req,
> + READ_ONCE(bedata->rsp[req_id].req_id) == req_id);
> +
> + if (map->active_socket) {
> + /*
> + * Set in_error and wake up inflight_conn_req to force
> + * recvmsg waiters to exit.
> + */
> + map->active.ring->in_error = -EBADF;
> + wake_up_interruptible(&map->active.inflight_conn_req);
> +
> + mutex_lock(&map->active.in_mutex);
> + mutex_lock(&map->active.out_mutex);
> + pvcalls_front_free_map(bedata, map);
> + mutex_unlock(&map->active.out_mutex);
> + mutex_unlock(&map->active.in_mutex);
> + kfree(map);

Since you are locking here I assume you expect that someone else might
also be trying to lock the map. But you are freeing it immediately after
unlocking. Wouldn't that mean that whoever is trying to grab the lock
might then dereference freed memory?


-boris

> + } else {
> + spin_lock(&bedata->pvcallss_lock);
> + list_del_init(&map->list);
> + kfree(map);
> + spin_unlock(&bedata->pvcallss_lock);
> + }
> + WRITE_ONCE(bedata->rsp[req_id].req_id, PVCALLS_INVALID_ID);
> +
> + return 0;
> +}
> +
> static const struct xenbus_device_id pvcalls_front_ids[] = {
> { "pvcalls" },
> { "" }
> diff --git a/drivers/xen/pvcalls-front.h b/drivers/xen/pvcalls-front.h
> index 25e05b8..3332978 100644
> --- a/drivers/xen/pvcalls-front.h
> +++ b/drivers/xen/pvcalls-front.h
> @@ -23,5 +23,6 @@ int pvcalls_front_recvmsg(struct socket *sock,
> unsigned int pvcalls_front_poll(struct file *file,
> struct socket *sock,
> poll_table *wait);
> +int pvcalls_front_release(struct socket *sock);
>
> #endif

\
 
 \ /
  Last update: 2017-07-27 20:38    [W:0.604 / U:0.408 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site