dm thin: use refcount_t for thin_c reference counting

The API surrounding refcount_t should be used in place of atomic_t
when variables are being used as reference counters.  It can
potentially prevent reference counter overflows and use-after-free
conditions.  In the dm thin layer, one such example is tc->refcount.
Change this from the atomic_t API to the refcount_t API to prevent
mentioned conditions.

Signed-off-by: John Pittman <jpittman@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
This commit is contained in:
John Pittman 2018-08-23 13:35:55 -04:00 committed by Mike Snitzer
parent cef6f55a9f
commit 22d4c291f5
1 changed files with 4 additions and 4 deletions

View File

@ -325,7 +325,7 @@ struct thin_c {
* Ensures the thin is not destroyed until the worker has finished * Ensures the thin is not destroyed until the worker has finished
* iterating the active_thins list. * iterating the active_thins list.
*/ */
atomic_t refcount; refcount_t refcount;
struct completion can_destroy; struct completion can_destroy;
}; };
@ -4044,12 +4044,12 @@ static struct target_type pool_target = {
*--------------------------------------------------------------*/ *--------------------------------------------------------------*/
static void thin_get(struct thin_c *tc) static void thin_get(struct thin_c *tc)
{ {
atomic_inc(&tc->refcount); refcount_inc(&tc->refcount);
} }
static void thin_put(struct thin_c *tc) static void thin_put(struct thin_c *tc)
{ {
if (atomic_dec_and_test(&tc->refcount)) if (refcount_dec_and_test(&tc->refcount))
complete(&tc->can_destroy); complete(&tc->can_destroy);
} }
@ -4193,7 +4193,7 @@ static int thin_ctr(struct dm_target *ti, unsigned argc, char **argv)
r = -EINVAL; r = -EINVAL;
goto bad; goto bad;
} }
atomic_set(&tc->refcount, 1); refcount_set(&tc->refcount, 1);
init_completion(&tc->can_destroy); init_completion(&tc->can_destroy);
list_add_tail_rcu(&tc->list, &tc->pool->active_thins); list_add_tail_rcu(&tc->list, &tc->pool->active_thins);
spin_unlock_irqrestore(&tc->pool->lock, flags); spin_unlock_irqrestore(&tc->pool->lock, flags);