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: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
Tested-by: Josh Fisher <josh.fisher@cornelisnetworks.com>
Acked-by: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
This commit is contained in:
Xiyu Yang 2021-07-19 14:00:53 +08:00 коммит произвёл Jason Gunthorpe
Родитель 62004871e1
Коммит a0293eb249
4 изменённых файлов: 7 добавлений и 6 удалений

Просмотреть файл

@ -15336,7 +15336,7 @@ int hfi1_init_dd(struct hfi1_devdata *dd)
init_completion(&dd->user_comp); init_completion(&dd->user_comp);
/* The user refcount starts with one to inidicate an active device */ /* 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; goto bail;

Просмотреть файл

@ -194,7 +194,7 @@ static int hfi1_file_open(struct inode *inode, struct file *fp)
if (!((dd->flags & HFI1_PRESENT) && dd->kregbase1)) if (!((dd->flags & HFI1_PRESENT) && dd->kregbase1))
return -EINVAL; return -EINVAL;
if (!atomic_inc_not_zero(&dd->user_refcount)) if (!refcount_inc_not_zero(&dd->user_refcount))
return -ENXIO; return -ENXIO;
/* The real work is performed later in assign_ctxt() */ /* 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: nomem:
kfree(fd); kfree(fd);
fp->private_data = NULL; fp->private_data = NULL;
if (atomic_dec_and_test(&dd->user_refcount)) if (refcount_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp); complete(&dd->user_comp);
return -ENOMEM; return -ENOMEM;
} }
@ -711,7 +711,7 @@ static int hfi1_file_close(struct inode *inode, struct file *fp)
deallocate_ctxt(uctxt); deallocate_ctxt(uctxt);
done: done:
if (atomic_dec_and_test(&dd->user_refcount)) if (refcount_dec_and_test(&dd->user_refcount))
complete(&dd->user_comp); complete(&dd->user_comp);
cleanup_srcu_struct(&fdata->pq_srcu); cleanup_srcu_struct(&fdata->pq_srcu);

Просмотреть файл

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

Просмотреть файл

@ -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 * Remove the device init value and complete the device if there is
* no clients or wait for active clients to finish. * 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); complete(&dd->user_comp);
wait_for_completion(&dd->user_comp); wait_for_completion(&dd->user_comp);