Commit a0293eb2 authored by Xiyu Yang's avatar Xiyu Yang Committed by Jason Gunthorpe
Browse files

RDMA/hfi1: Convert from atomic_t to refcount_t on hfi1_devdata->user_refcount

refcount_t type and corresponding API can protect refcounters from
accidental underflow and overflow and further use-after-free situations.

Link: https://lore.kernel.org/r/1626674454-56075-1-git-send-email-xiyuyang19@fudan.edu.cn


Signed-off-by: default avatarXiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: default avatarXin Tan <tanxin.ctf@gmail.com>
Tested-by: default avatarJosh Fisher <josh.fisher@cornelisnetworks.com>
Acked-by: default avatarDennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 62004871
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -15336,7 +15336,7 @@ int hfi1_init_dd(struct hfi1_devdata *dd)
	init_completion(&dd->user_comp);

	/* The user refcount starts with one to inidicate an active device */
	atomic_set(&dd->user_refcount, 1);
	refcount_set(&dd->user_refcount, 1);

	goto bail;

+3 −3
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
	if (!((dd->flags & HFI1_PRESENT) && dd->kregbase1))
		return -EINVAL;

	if (!atomic_inc_not_zero(&dd->user_refcount))
	if (!refcount_inc_not_zero(&dd->user_refcount))
		return -ENXIO;

	/* The real work is performed later in assign_ctxt() */
@@ -213,7 +213,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
nomem:
	kfree(fd);
	fp->private_data = NULL;
	if (atomic_dec_and_test(&dd->user_refcount))
	if (refcount_dec_and_test(&dd->user_refcount))
		complete(&dd->user_comp);
	return -ENOMEM;
}
@@ -711,7 +711,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
	deallocate_ctxt(uctxt);
done:

	if (atomic_dec_and_test(&dd->user_refcount))
	if (refcount_dec_and_test(&dd->user_refcount))
		complete(&dd->user_comp);

	cleanup_srcu_struct(&fdata->pq_srcu);
+2 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@
 *
 */

#include <linux/refcount.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
@@ -1384,7 +1385,7 @@ struct hfi1_devdata {
	/* Number of verbs contexts which have disabled ASPM */
	atomic_t aspm_disabled_cnt;
	/* Keeps track of user space clients */
	atomic_t user_refcount;
	refcount_t user_refcount;
	/* Used to wait for outstanding user space clients before dev removal */
	struct completion user_comp;

+1 −1
Original line number Diff line number Diff line
@@ -1747,7 +1747,7 @@ static void wait_for_clients(struct hfi1_devdata *dd)
	 * Remove the device init value and complete the device if there is
	 * no clients or wait for active clients to finish.
	 */
	if (atomic_dec_and_test(&dd->user_refcount))
	if (refcount_dec_and_test(&dd->user_refcount))
		complete(&dd->user_comp);

	wait_for_completion(&dd->user_comp);