Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drivers, connector: convert cn_callback_entry.refcnt from atomic_t to refcount_t

atomic_t variables are currently used to implement reference
counters with the following properties:
- counter is initialized to 1 using atomic_set()
- a resource is freed upon counter reaching zero
- once counter reaches zero, its further
increments aren't allowed
- counter schema uses basic atomic operations
(set, inc, inc_not_zero, dec_and_test, etc.)

Such atomic variables should be converted to a newly provided
refcount_t type and API that prevents accidental counter overflows
and underflows. This is important since overflows and underflows
can lead to use-after-free situation and be exploitable.

The variable cn_callback_entry.refcnt is used as pure reference counter.
Convert it to refcount_t and fix up the operations.

Suggested-by: Kees Cook <keescook@chromium.org>
Reviewed-by: David Windsor <dwindsor@gmail.com>
Reviewed-by: Hans Liljestrand <ishkamiel@gmail.com>
Signed-off-by: Elena Reshetova <elena.reshetova@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Elena Reshetova and committed by
David S. Miller
e65f7ee3 709c89b4

+5 -5
+2 -2
drivers/connector/cn_queue.c
··· 45 45 return NULL; 46 46 } 47 47 48 - atomic_set(&cbq->refcnt, 1); 48 + refcount_set(&cbq->refcnt, 1); 49 49 50 50 atomic_inc(&dev->refcnt); 51 51 cbq->pdev = dev; ··· 58 58 59 59 void cn_queue_release_callback(struct cn_callback_entry *cbq) 60 60 { 61 - if (!atomic_dec_and_test(&cbq->refcnt)) 61 + if (!refcount_dec_and_test(&cbq->refcnt)) 62 62 return; 63 63 64 64 atomic_dec(&cbq->pdev->refcnt);
+1 -1
drivers/connector/connector.c
··· 157 157 spin_lock_bh(&dev->cbdev->queue_lock); 158 158 list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) { 159 159 if (cn_cb_equal(&i->id.id, &msg->id)) { 160 - atomic_inc(&i->refcnt); 160 + refcount_inc(&i->refcnt); 161 161 cbq = i; 162 162 break; 163 163 }
+2 -2
include/linux/connector.h
··· 22 22 #define __CONNECTOR_H 23 23 24 24 25 - #include <linux/atomic.h> 25 + #include <linux/refcount.h> 26 26 27 27 #include <linux/list.h> 28 28 #include <linux/workqueue.h> ··· 49 49 50 50 struct cn_callback_entry { 51 51 struct list_head callback_entry; 52 - atomic_t refcnt; 52 + refcount_t refcnt; 53 53 struct cn_queue_dev *pdev; 54 54 55 55 struct cn_callback_id id;