refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Elena Reshetova <elena.reshetova@xxxxxxxxx> Signed-off-by: Hans Liljestrand <ishkamiel@xxxxxxxxx> Signed-off-by: Kees Cook <keescook@xxxxxxxxxxxx> Signed-off-by: David Windsor <dwindsor@xxxxxxxxx> --- fs/cachefiles/rdwr.c | 2 +- fs/fscache/operation.c | 38 +++++++++++++++++++------------------- fs/fscache/page.c | 2 +- include/linux/fscache-cache.h | 4 ++-- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index afbdc41..c987de6 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -692,7 +692,7 @@ int cachefiles_read_or_alloc_pages(struct fscache_retrieval *op, struct cachefiles_cache, cache); _enter("{OBJ%x,%d},,%d,,", - object->fscache.debug_id, atomic_read(&op->op.usage), + object->fscache.debug_id, refcount_read(&op->op.usage), *nr_pages); if (!object->backer) diff --git a/fs/fscache/operation.c b/fs/fscache/operation.c index de67745..eb84c95 100644 --- a/fs/fscache/operation.c +++ b/fs/fscache/operation.c @@ -38,7 +38,7 @@ void fscache_operation_init(struct fscache_operation *op, fscache_operation_release_t release) { INIT_WORK(&op->work, fscache_op_work_func); - atomic_set(&op->usage, 1); + refcount_set(&op->usage, 1); op->state = FSCACHE_OP_ST_INITIALISED; op->debug_id = atomic_inc_return(&fscache_op_debug_id); op->processor = processor; @@ -60,19 +60,19 @@ EXPORT_SYMBOL(fscache_operation_init); void fscache_enqueue_operation(struct fscache_operation *op) { _enter("{OBJ%x OP%x,%u}", - op->object->debug_id, op->debug_id, atomic_read(&op->usage)); + op->object->debug_id, op->debug_id, refcount_read(&op->usage)); ASSERT(list_empty(&op->pend_link)); ASSERT(op->processor != NULL); ASSERT(fscache_object_is_available(op->object)); - ASSERTCMP(atomic_read(&op->usage), >, 0); + ASSERTCMP(refcount_read(&op->usage), >, 0); ASSERTCMP(op->state, ==, FSCACHE_OP_ST_IN_PROGRESS); fscache_stat(&fscache_n_op_enqueue); switch (op->flags & FSCACHE_OP_TYPE) { case FSCACHE_OP_ASYNC: _debug("queue async"); - atomic_inc(&op->usage); + refcount_inc(&op->usage); if (!queue_work(fscache_op_wq, &op->work)) fscache_put_operation(op); break; @@ -156,7 +156,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object, _enter("{OBJ%x OP%x},", object->debug_id, op->debug_id); ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED); - ASSERTCMP(atomic_read(&op->usage), >, 0); + ASSERTCMP(refcount_read(&op->usage), >, 0); spin_lock(&object->lock); ASSERTCMP(object->n_ops, >=, object->n_in_progress); @@ -183,11 +183,11 @@ int fscache_submit_exclusive_op(struct fscache_object *object, object->n_exclusive++; /* reads and writes must wait */ if (object->n_in_progress > 0) { - atomic_inc(&op->usage); + refcount_inc(&op->usage); list_add_tail(&op->pend_link, &object->pending_ops); fscache_stat(&fscache_n_op_pend); } else if (!list_empty(&object->pending_ops)) { - atomic_inc(&op->usage); + refcount_inc(&op->usage); list_add_tail(&op->pend_link, &object->pending_ops); fscache_stat(&fscache_n_op_pend); fscache_start_operations(object); @@ -203,7 +203,7 @@ int fscache_submit_exclusive_op(struct fscache_object *object, op->object = object; object->n_ops++; object->n_exclusive++; /* reads and writes must wait */ - atomic_inc(&op->usage); + refcount_inc(&op->usage); list_add_tail(&op->pend_link, &object->pending_ops); fscache_stat(&fscache_n_op_pend); ret = 0; @@ -238,10 +238,10 @@ int fscache_submit_op(struct fscache_object *object, int ret; _enter("{OBJ%x OP%x},{%u}", - object->debug_id, op->debug_id, atomic_read(&op->usage)); + object->debug_id, op->debug_id, refcount_read(&op->usage)); ASSERTCMP(op->state, ==, FSCACHE_OP_ST_INITIALISED); - ASSERTCMP(atomic_read(&op->usage), >, 0); + ASSERTCMP(refcount_read(&op->usage), >, 0); spin_lock(&object->lock); ASSERTCMP(object->n_ops, >=, object->n_in_progress); @@ -267,11 +267,11 @@ int fscache_submit_op(struct fscache_object *object, object->n_ops++; if (object->n_exclusive > 0) { - atomic_inc(&op->usage); + refcount_inc(&op->usage); list_add_tail(&op->pend_link, &object->pending_ops); fscache_stat(&fscache_n_op_pend); } else if (!list_empty(&object->pending_ops)) { - atomic_inc(&op->usage); + refcount_inc(&op->usage); list_add_tail(&op->pend_link, &object->pending_ops); fscache_stat(&fscache_n_op_pend); fscache_start_operations(object); @@ -283,7 +283,7 @@ int fscache_submit_op(struct fscache_object *object, } else if (flags & BIT(FSCACHE_OBJECT_IS_LOOKED_UP)) { op->object = object; object->n_ops++; - atomic_inc(&op->usage); + refcount_inc(&op->usage); list_add_tail(&op->pend_link, &object->pending_ops); fscache_stat(&fscache_n_op_pend); ret = 0; @@ -359,7 +359,7 @@ int fscache_cancel_op(struct fscache_operation *op, ASSERTCMP(op->state, >=, FSCACHE_OP_ST_PENDING); ASSERTCMP(op->state, !=, FSCACHE_OP_ST_CANCELLED); - ASSERTCMP(atomic_read(&op->usage), >, 0); + ASSERTCMP(refcount_read(&op->usage), >, 0); spin_lock(&object->lock); @@ -481,11 +481,11 @@ void fscache_put_operation(struct fscache_operation *op) struct fscache_cache *cache; _enter("{OBJ%x OP%x,%d}", - op->object->debug_id, op->debug_id, atomic_read(&op->usage)); + op->object->debug_id, op->debug_id, refcount_read(&op->usage)); - ASSERTCMP(atomic_read(&op->usage), >, 0); + ASSERTCMP(refcount_read(&op->usage), >, 0); - if (!atomic_dec_and_test(&op->usage)) + if (!refcount_dec_and_test(&op->usage)) return; _debug("PUT OP"); @@ -569,7 +569,7 @@ void fscache_operation_gc(struct work_struct *work) object->debug_id, op->debug_id); fscache_stat(&fscache_n_op_gc); - ASSERTCMP(atomic_read(&op->usage), ==, 0); + ASSERTCMP(refcount_read(&op->usage), ==, 0); ASSERTCMP(op->state, ==, FSCACHE_OP_ST_DEAD); ASSERTCMP(object->n_ops, >, 0); @@ -599,7 +599,7 @@ void fscache_op_work_func(struct work_struct *work) unsigned long start; _enter("{OBJ%x OP%x,%d}", - op->object->debug_id, op->debug_id, atomic_read(&op->usage)); + op->object->debug_id, op->debug_id, refcount_read(&op->usage)); ASSERT(op->processor != NULL); start = jiffies; diff --git a/fs/fscache/page.c b/fs/fscache/page.c index c8c4f79..352393c 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -774,7 +774,7 @@ static void fscache_write_op(struct fscache_operation *_op) void *results[1]; int ret; - _enter("{OP%x,%d}", op->op.debug_id, atomic_read(&op->op.usage)); + _enter("{OP%x,%d}", op->op.debug_id, refcount_read(&op->op.usage)); spin_lock(&object->lock); cookie = object->cookie; diff --git a/include/linux/fscache-cache.h b/include/linux/fscache-cache.h index dcec7b3..0093158 100644 --- a/include/linux/fscache-cache.h +++ b/include/linux/fscache-cache.h @@ -103,7 +103,7 @@ struct fscache_operation { #define FSCACHE_OP_KEEP_FLAGS 0x00f0 /* flags to keep when repurposing an op */ enum fscache_operation_state state; - atomic_t usage; + refcount_t usage; unsigned debug_id; /* debugging ID */ /* operation processor callback @@ -161,7 +161,7 @@ typedef int (*fscache_pages_retrieval_func_t)(struct fscache_retrieval *op, static inline struct fscache_retrieval *fscache_get_retrieval(struct fscache_retrieval *op) { - atomic_inc(&op->op.usage); + refcount_inc(&op->op.usage); return op; } -- 2.7.4 -- To unsubscribe from this list: send the line "unsubscribe linux-cifs" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html