2017-03-17 12:11:00

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 00/23] various networking refcount conversions, part 2

This series, for the rest of network subsystem components, replaces atomic_t reference
counters with the new refcount_t type and API (see include/linux/refcount.h).
By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.

The patches are fully independent and can be cherry-picked separately.
Since we convert all kernel subsystems in the same fashion, resulting
in about 300 patches, we have to group them for sending at least in some
fashion to be manageable. Please excuse the long cc list.

If there are no objections to the patches, please merge them via respective trees.

Elena Reshetova (23):
net, sunrpc: convert rpc_cred.cr_count from atomic_t to refcount_t
net, sunrpc: convert gss_cl_ctx.count from atomic_t to refcount_t
net, sunrpc: convert gss_upcall_msg.count from atomic_t to refcount_t
net, ceph: convert ceph_snap_context.nref from atomic_t to refcount_t
net, ceph: convert ceph_osd.o_ref from atomic_t to refcount_t
net, ceph: convert ceph_pagelist.refcnt from atomic_t to refcount_t
net, rds: convert rds_ib_device.refcount from atomic_t to refcount_t
net, rds: convert rds_incoming.i_refcount from atomic_t to refcount_t
net, rds: convert rds_mr.r_refcount from atomic_t to refcount_t
net, rds: convert rds_message.m_refcount from atomic_t to refcount_t
net, x25: convert x25_route.refcnt from atomic_t to refcount_t
net, x25: convert x25_neigh.refcnt from atomic_t to refcount_t
net, xfrm: convert xfrm_state.refcnt from atomic_t to refcount_t
net, xfrm: convert xfrm_policy.refcnt from atomic_t to refcount_t
net, xfrm: convert sec_path.refcnt from atomic_t to refcount_t
net, sctp: convert sctp_auth_bytes.refcnt from atomic_t to refcount_t
net, sctp: convert sctp_datamsg.refcnt from atomic_t to refcount_t
net, sctp: convert sctp_chunk.refcnt from atomic_t to refcount_t
net, sctp: convert sctp_transport.refcnt from atomic_t to refcount_t
net, sctp: convert sctp_ep_common.refcnt from atomic_t to refcount_t
net, ax25: convert ax25_uid_assoc.refcount from atomic_t to refcount_t
net, ax25: convert ax25_route.refcount from atomic_t to refcount_t
net, ax25: convert ax25_cb.refcount from atomic_t to refcount_t

fs/ceph/mds_client.c | 2 +-
include/linux/ceph/libceph.h | 3 ++-
include/linux/ceph/osd_client.h | 3 ++-
include/linux/ceph/pagelist.h | 6 +++---
include/linux/sunrpc/auth.h | 8 ++++----
include/linux/sunrpc/auth_gss.h | 3 ++-
include/net/ax25.h | 20 ++++++++++----------
include/net/sctp/auth.h | 5 +++--
include/net/sctp/structs.h | 8 ++++----
include/net/x25.h | 13 +++++++------
include/net/xfrm.h | 21 +++++++++++----------
net/ax25/af_ax25.c | 2 +-
net/ax25/ax25_route.c | 2 +-
net/ax25/ax25_uid.c | 2 +-
net/ceph/osd_client.c | 16 ++++++++--------
net/ceph/pagelist.c | 2 +-
net/ceph/snapshot.c | 6 +++---
net/key/af_key.c | 2 +-
net/rds/ib.c | 12 ++++++------
net/rds/ib.h | 2 +-
net/rds/ib_rdma.c | 4 ++--
net/rds/message.c | 12 ++++++------
net/rds/rdma.c | 10 +++++-----
net/rds/rds.h | 9 +++++----
net/rds/recv.c | 12 ++++++------
net/sctp/associola.c | 6 +++---
net/sctp/auth.c | 4 ++--
net/sctp/chunk.c | 6 +++---
net/sctp/endpointola.c | 6 +++---
net/sctp/sm_make_chunk.c | 6 +++---
net/sctp/transport.c | 8 ++++----
net/sunrpc/auth.c | 12 ++++++------
net/sunrpc/auth_gss/auth_gss.c | 28 ++++++++++++++--------------
net/x25/x25_link.c | 2 +-
net/x25/x25_route.c | 2 +-
net/xfrm/xfrm_input.c | 4 ++--
net/xfrm/xfrm_policy.c | 4 ++--
net/xfrm/xfrm_state.c | 4 ++--
38 files changed, 142 insertions(+), 135 deletions(-)

--
2.7.4


2017-03-17 12:11:17

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 02/23] net, sunrpc: convert gss_cl_ctx.count from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/linux/sunrpc/auth_gss.h | 3 ++-
net/sunrpc/auth_gss/auth_gss.c | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index 36eebc4..cebdf87 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -13,6 +13,7 @@
#define _LINUX_SUNRPC_AUTH_GSS_H

#ifdef __KERNEL__
+#include <linux/refcount.h>
#include <linux/sunrpc/auth.h>
#include <linux/sunrpc/svc.h>
#include <linux/sunrpc/gss_api.h>
@@ -65,7 +66,7 @@ struct rpc_gss_init_res {
* the wire when communicating with a server. */

struct gss_cl_ctx {
- atomic_t count;
+ refcount_t count;
enum rpc_gss_proc gc_proc;
u32 gc_seq;
spinlock_t gc_seq_lock;
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 4f16953..72f129c 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -117,14 +117,14 @@ static const struct rpc_pipe_ops gss_upcall_ops_v1;
static inline struct gss_cl_ctx *
gss_get_ctx(struct gss_cl_ctx *ctx)
{
- atomic_inc(&ctx->count);
+ refcount_inc(&ctx->count);
return ctx;
}

static inline void
gss_put_ctx(struct gss_cl_ctx *ctx)
{
- if (atomic_dec_and_test(&ctx->count))
+ if (refcount_dec_and_test(&ctx->count))
gss_free_ctx(ctx);
}

@@ -200,7 +200,7 @@ gss_alloc_context(void)
ctx->gc_proc = RPC_GSS_PROC_DATA;
ctx->gc_seq = 1; /* NetApp 6.4R1 doesn't accept seq. no. 0 */
spin_lock_init(&ctx->gc_seq_lock);
- atomic_set(&ctx->count,1);
+ refcount_set(&ctx->count,1);
}
return ctx;
}
--
2.7.4

2017-03-17 12:11:08

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 01/23] net, sunrpc: convert rpc_cred.cr_count from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/linux/sunrpc/auth.h | 8 ++++----
net/sunrpc/auth.c | 12 ++++++------
2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index b1bc62b..bd36e0b 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -15,7 +15,7 @@
#include <linux/sunrpc/msg_prot.h>
#include <linux/sunrpc/xdr.h>

-#include <linux/atomic.h>
+#include <linux/refcount.h>
#include <linux/rcupdate.h>
#include <linux/uidgid.h>
#include <linux/utsname.h>
@@ -68,7 +68,7 @@ struct rpc_cred {
#endif
unsigned long cr_expire; /* when to gc */
unsigned long cr_flags; /* various flags */
- atomic_t cr_count; /* ref count */
+ refcount_t cr_count; /* ref count */

kuid_t cr_uid;

@@ -209,7 +209,7 @@ static inline
struct rpc_cred * get_rpccred(struct rpc_cred *cred)
{
if (cred != NULL)
- atomic_inc(&cred->cr_count);
+ refcount_inc(&cred->cr_count);
return cred;
}

@@ -226,7 +226,7 @@ struct rpc_cred * get_rpccred(struct rpc_cred *cred)
static inline struct rpc_cred *
get_rpccred_rcu(struct rpc_cred *cred)
{
- if (atomic_inc_not_zero(&cred->cr_count))
+ if (refcount_inc_not_zero(&cred->cr_count))
return cred;
return NULL;
}
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c
index 2bff63a..b6439b9 100644
--- a/net/sunrpc/auth.c
+++ b/net/sunrpc/auth.c
@@ -310,7 +310,7 @@ rpcauth_unhash_cred(struct rpc_cred *cred)

cache_lock = &cred->cr_auth->au_credcache->lock;
spin_lock(cache_lock);
- ret = atomic_read(&cred->cr_count) == 0;
+ ret = refcount_read(&cred->cr_count) == 0;
if (ret)
rpcauth_unhash_cred_locked(cred);
spin_unlock(cache_lock);
@@ -470,12 +470,12 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan)
list_del_init(&cred->cr_lru);
number_cred_unused--;
freed++;
- if (atomic_read(&cred->cr_count) != 0)
+ if (refcount_read(&cred->cr_count) != 0)
continue;

cache_lock = &cred->cr_auth->au_credcache->lock;
spin_lock(cache_lock);
- if (atomic_read(&cred->cr_count) == 0) {
+ if (refcount_read(&cred->cr_count) == 0) {
get_rpccred(cred);
list_add_tail(&cred->cr_lru, free);
rpcauth_unhash_cred_locked(cred);
@@ -642,7 +642,7 @@ rpcauth_init_cred(struct rpc_cred *cred, const struct auth_cred *acred,
{
INIT_HLIST_NODE(&cred->cr_hash);
INIT_LIST_HEAD(&cred->cr_lru);
- atomic_set(&cred->cr_count, 1);
+ refcount_set(&cred->cr_count, 1);
cred->cr_auth = auth;
cred->cr_ops = ops;
cred->cr_expire = jiffies;
@@ -715,12 +715,12 @@ put_rpccred(struct rpc_cred *cred)
return;
/* Fast path for unhashed credentials */
if (test_bit(RPCAUTH_CRED_HASHED, &cred->cr_flags) == 0) {
- if (atomic_dec_and_test(&cred->cr_count))
+ if (refcount_dec_and_test(&cred->cr_count))
cred->cr_ops->crdestroy(cred);
return;
}

- if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+ if (!refcount_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
return;
if (!list_empty(&cred->cr_lru)) {
number_cred_unused--;
--
2.7.4

2017-03-17 12:11:32

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 03/23] net, sunrpc: convert gss_upcall_msg.count from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
net/sunrpc/auth_gss/auth_gss.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 72f129c..e7c941a 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -287,7 +287,7 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct
#define UPCALL_BUF_LEN 128

struct gss_upcall_msg {
- atomic_t count;
+ refcount_t count;
kuid_t uid;
struct rpc_pipe_msg msg;
struct list_head list;
@@ -328,7 +328,7 @@ static void
gss_release_msg(struct gss_upcall_msg *gss_msg)
{
struct net *net = gss_msg->auth->net;
- if (!atomic_dec_and_test(&gss_msg->count))
+ if (!refcount_dec_and_test(&gss_msg->count))
return;
put_pipe_version(net);
BUG_ON(!list_empty(&gss_msg->list));
@@ -348,7 +348,7 @@ __gss_find_upcall(struct rpc_pipe *pipe, kuid_t uid, const struct gss_auth *auth
continue;
if (auth && pos->auth->service != auth->service)
continue;
- atomic_inc(&pos->count);
+ refcount_inc(&pos->count);
dprintk("RPC: %s found msg %p\n", __func__, pos);
return pos;
}
@@ -369,7 +369,7 @@ gss_add_msg(struct gss_upcall_msg *gss_msg)
spin_lock(&pipe->lock);
old = __gss_find_upcall(pipe, gss_msg->uid, gss_msg->auth);
if (old == NULL) {
- atomic_inc(&gss_msg->count);
+ refcount_inc(&gss_msg->count);
list_add(&gss_msg->list, &pipe->in_downcall);
} else
gss_msg = old;
@@ -383,7 +383,7 @@ __gss_unhash_msg(struct gss_upcall_msg *gss_msg)
list_del_init(&gss_msg->list);
rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
wake_up_all(&gss_msg->waitqueue);
- atomic_dec(&gss_msg->count);
+ WARN_ON(refcount_dec_and_test(&gss_msg->count));
}

static void
@@ -506,7 +506,7 @@ gss_alloc_msg(struct gss_auth *gss_auth,
INIT_LIST_HEAD(&gss_msg->list);
rpc_init_wait_queue(&gss_msg->rpc_waitqueue, "RPCSEC_GSS upcall waitq");
init_waitqueue_head(&gss_msg->waitqueue);
- atomic_set(&gss_msg->count, 1);
+ refcount_set(&gss_msg->count, 1);
gss_msg->uid = uid;
gss_msg->auth = gss_auth;
switch (vers) {
@@ -542,11 +542,11 @@ gss_setup_upcall(struct gss_auth *gss_auth, struct rpc_cred *cred)
gss_msg = gss_add_msg(gss_new);
if (gss_msg == gss_new) {
int res;
- atomic_inc(&gss_msg->count);
+ refcount_inc(&gss_msg->count);
res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg);
if (res) {
gss_unhash_msg(gss_new);
- atomic_dec(&gss_msg->count);
+ refcount_dec(&gss_msg->count);
gss_release_msg(gss_new);
gss_msg = ERR_PTR(res);
}
@@ -595,7 +595,7 @@ gss_refresh_upcall(struct rpc_task *task)
task->tk_timeout = 0;
gss_cred->gc_upcall = gss_msg;
/* gss_upcall_callback will release the reference to gss_upcall_msg */
- atomic_inc(&gss_msg->count);
+ refcount_inc(&gss_msg->count);
rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
} else {
gss_handle_downcall_result(gss_cred, gss_msg);
@@ -815,7 +815,7 @@ gss_pipe_release(struct inode *inode)
if (!list_empty(&gss_msg->msg.list))
continue;
gss_msg->msg.errno = -EPIPE;
- atomic_inc(&gss_msg->count);
+ refcount_inc(&gss_msg->count);
__gss_unhash_msg(gss_msg);
spin_unlock(&pipe->lock);
gss_release_msg(gss_msg);
@@ -834,7 +834,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg *msg)
if (msg->errno < 0) {
dprintk("RPC: %s releasing msg %p\n",
__func__, gss_msg);
- atomic_inc(&gss_msg->count);
+ refcount_inc(&gss_msg->count);
gss_unhash_msg(gss_msg);
if (msg->errno == -ETIMEDOUT)
warn_gssd();
--
2.7.4

2017-03-17 12:11:45

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 05/23] net, ceph: convert ceph_osd.o_ref from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/linux/ceph/osd_client.h | 3 ++-
net/ceph/osd_client.c | 16 ++++++++--------
2 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index 2ea0c28..5ce0cd6 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -5,6 +5,7 @@
#include <linux/kref.h>
#include <linux/mempool.h>
#include <linux/rbtree.h>
+#include <linux/refcount.h>

#include <linux/ceph/types.h>
#include <linux/ceph/osdmap.h>
@@ -27,7 +28,7 @@ typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *);

/* a given osd we're communicating with */
struct ceph_osd {
- atomic_t o_ref;
+ refcount_t o_ref;
struct ceph_osd_client *o_osdc;
int o_osd;
int o_incarnation;
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index b65bbf9..99a51f0 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1005,7 +1005,7 @@ static bool osd_registered(struct ceph_osd *osd)
*/
static void osd_init(struct ceph_osd *osd)
{
- atomic_set(&osd->o_ref, 1);
+ refcount_set(&osd->o_ref, 1);
RB_CLEAR_NODE(&osd->o_node);
osd->o_requests = RB_ROOT;
osd->o_linger_requests = RB_ROOT;
@@ -1050,9 +1050,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)

static struct ceph_osd *get_osd(struct ceph_osd *osd)
{
- if (atomic_inc_not_zero(&osd->o_ref)) {
- dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
- atomic_read(&osd->o_ref));
+ if (refcount_inc_not_zero(&osd->o_ref)) {
+ dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
+ refcount_read(&osd->o_ref));
return osd;
} else {
dout("get_osd %p FAIL\n", osd);
@@ -1062,9 +1062,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)

static void put_osd(struct ceph_osd *osd)
{
- dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
- atomic_read(&osd->o_ref) - 1);
- if (atomic_dec_and_test(&osd->o_ref)) {
+ dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
+ refcount_read(&osd->o_ref) - 1);
+ if (refcount_dec_and_test(&osd->o_ref)) {
osd_cleanup(osd);
kfree(osd);
}
@@ -4092,7 +4092,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
close_osd(osd);
}
up_write(&osdc->lock);
- WARN_ON(atomic_read(&osdc->homeless_osd.o_ref) != 1);
+ WARN_ON(refcount_read(&osdc->homeless_osd.o_ref) != 1);
osd_cleanup(&osdc->homeless_osd);

WARN_ON(!list_empty(&osdc->osd_lru));
--
2.7.4

2017-03-17 12:11:54

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 07/23] net, rds: convert rds_ib_device.refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
net/rds/ib.c | 12 ++++++------
net/rds/ib.h | 2 +-
net/rds/ib_rdma.c | 4 ++--
3 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/net/rds/ib.c b/net/rds/ib.c
index 91fe46f..bb19cda 100644
--- a/net/rds/ib.c
+++ b/net/rds/ib.c
@@ -118,8 +118,8 @@ static void rds_ib_dev_free(struct work_struct *work)

void rds_ib_dev_put(struct rds_ib_device *rds_ibdev)
{
- BUG_ON(atomic_read(&rds_ibdev->refcount) <= 0);
- if (atomic_dec_and_test(&rds_ibdev->refcount))
+ BUG_ON(refcount_read(&rds_ibdev->refcount) == 0);
+ if (refcount_dec_and_test(&rds_ibdev->refcount))
queue_work(rds_wq, &rds_ibdev->free_work);
}

@@ -137,7 +137,7 @@ static void rds_ib_add_one(struct ib_device *device)
return;

spin_lock_init(&rds_ibdev->spinlock);
- atomic_set(&rds_ibdev->refcount, 1);
+ refcount_set(&rds_ibdev->refcount, 1);
INIT_WORK(&rds_ibdev->free_work, rds_ib_dev_free);

rds_ibdev->max_wrs = device->attrs.max_qp_wr;
@@ -205,10 +205,10 @@ static void rds_ib_add_one(struct ib_device *device)
down_write(&rds_ib_devices_lock);
list_add_tail_rcu(&rds_ibdev->list, &rds_ib_devices);
up_write(&rds_ib_devices_lock);
- atomic_inc(&rds_ibdev->refcount);
+ refcount_inc(&rds_ibdev->refcount);

ib_set_client_data(device, &rds_ib_client, rds_ibdev);
- atomic_inc(&rds_ibdev->refcount);
+ refcount_inc(&rds_ibdev->refcount);

rds_ib_nodev_connect();

@@ -239,7 +239,7 @@ struct rds_ib_device *rds_ib_get_client_data(struct ib_device *device)
rcu_read_lock();
rds_ibdev = ib_get_client_data(device, &rds_ib_client);
if (rds_ibdev)
- atomic_inc(&rds_ibdev->refcount);
+ refcount_inc(&rds_ibdev->refcount);
rcu_read_unlock();
return rds_ibdev;
}
diff --git a/net/rds/ib.h b/net/rds/ib.h
index ec55062..bf48224 100644
--- a/net/rds/ib.h
+++ b/net/rds/ib.h
@@ -230,7 +230,7 @@ struct rds_ib_device {
unsigned int max_initiator_depth;
unsigned int max_responder_resources;
spinlock_t spinlock; /* protect the above */
- atomic_t refcount;
+ refcount_t refcount;
struct work_struct free_work;
int *vector_load;
};
diff --git a/net/rds/ib_rdma.c b/net/rds/ib_rdma.c
index 977f698..9a3c54e 100644
--- a/net/rds/ib_rdma.c
+++ b/net/rds/ib_rdma.c
@@ -52,7 +52,7 @@ static struct rds_ib_device *rds_ib_get_device(__be32 ipaddr)
list_for_each_entry_rcu(rds_ibdev, &rds_ib_devices, list) {
list_for_each_entry_rcu(i_ipaddr, &rds_ibdev->ipaddr_list, list) {
if (i_ipaddr->ipaddr == ipaddr) {
- atomic_inc(&rds_ibdev->refcount);
+ refcount_inc(&rds_ibdev->refcount);
rcu_read_unlock();
return rds_ibdev;
}
@@ -134,7 +134,7 @@ void rds_ib_add_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *con
spin_unlock_irq(&ib_nodev_conns_lock);

ic->rds_ibdev = rds_ibdev;
- atomic_inc(&rds_ibdev->refcount);
+ refcount_inc(&rds_ibdev->refcount);
}

void rds_ib_remove_conn(struct rds_ib_device *rds_ibdev, struct rds_connection *conn)
--
2.7.4

2017-03-17 12:12:05

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 06/23] net, ceph: convert ceph_pagelist.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
fs/ceph/mds_client.c | 2 +-
include/linux/ceph/pagelist.h | 6 +++---
net/ceph/pagelist.c | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index c681762..7b38e6c 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -1991,7 +1991,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,

if (req->r_pagelist) {
struct ceph_pagelist *pagelist = req->r_pagelist;
- atomic_inc(&pagelist->refcnt);
+ refcount_inc(&pagelist->refcnt);
ceph_msg_data_add_pagelist(msg, pagelist);
msg->hdr.data_len = cpu_to_le32(pagelist->length);
} else {
diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h
index 13d71fe..75a7db2 100644
--- a/include/linux/ceph/pagelist.h
+++ b/include/linux/ceph/pagelist.h
@@ -2,7 +2,7 @@
#define __FS_CEPH_PAGELIST_H

#include <asm/byteorder.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
#include <linux/list.h>
#include <linux/types.h>

@@ -13,7 +13,7 @@ struct ceph_pagelist {
size_t room;
struct list_head free_list;
size_t num_pages_free;
- atomic_t refcnt;
+ refcount_t refcnt;
};

struct ceph_pagelist_cursor {
@@ -30,7 +30,7 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
pl->room = 0;
INIT_LIST_HEAD(&pl->free_list);
pl->num_pages_free = 0;
- atomic_set(&pl->refcnt, 1);
+ refcount_set(&pl->refcnt, 1);
}

extern void ceph_pagelist_release(struct ceph_pagelist *pl);
diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
index 6864007..ce09f73 100644
--- a/net/ceph/pagelist.c
+++ b/net/ceph/pagelist.c
@@ -16,7 +16,7 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)

void ceph_pagelist_release(struct ceph_pagelist *pl)
{
- if (!atomic_dec_and_test(&pl->refcnt))
+ if (!refcount_dec_and_test(&pl->refcnt))
return;
ceph_pagelist_unmap_tail(pl);
while (!list_empty(&pl->head)) {
--
2.7.4

2017-03-17 12:11:30

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 04/23] net, ceph: convert ceph_snap_context.nref from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/linux/ceph/libceph.h | 3 ++-
net/ceph/snapshot.c | 6 +++---
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 1816c5e..26dc674 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -14,6 +14,7 @@
#include <linux/wait.h>
#include <linux/writeback.h>
#include <linux/slab.h>
+#include <linux/refcount.h>

#include <linux/ceph/types.h>
#include <linux/ceph/messenger.h>
@@ -159,7 +160,7 @@ struct ceph_client {
* dirtied.
*/
struct ceph_snap_context {
- atomic_t nref;
+ refcount_t nref;
u64 seq;
u32 num_snaps;
u64 snaps[];
diff --git a/net/ceph/snapshot.c b/net/ceph/snapshot.c
index 705414e..e14a5d0 100644
--- a/net/ceph/snapshot.c
+++ b/net/ceph/snapshot.c
@@ -49,7 +49,7 @@ struct ceph_snap_context *ceph_create_snap_context(u32 snap_count,
if (!snapc)
return NULL;

- atomic_set(&snapc->nref, 1);
+ refcount_set(&snapc->nref, 1);
snapc->num_snaps = snap_count;

return snapc;
@@ -59,7 +59,7 @@ EXPORT_SYMBOL(ceph_create_snap_context);
struct ceph_snap_context *ceph_get_snap_context(struct ceph_snap_context *sc)
{
if (sc)
- atomic_inc(&sc->nref);
+ refcount_inc(&sc->nref);
return sc;
}
EXPORT_SYMBOL(ceph_get_snap_context);
@@ -68,7 +68,7 @@ void ceph_put_snap_context(struct ceph_snap_context *sc)
{
if (!sc)
return;
- if (atomic_dec_and_test(&sc->nref)) {
+ if (refcount_dec_and_test(&sc->nref)) {
/*printk(" deleting snap_context %p\n", sc);*/
kfree(sc);
}
--
2.7.4

2017-03-17 12:17:08

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 08/23] net, rds: convert rds_incoming.i_refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
net/rds/rds.h | 3 ++-
net/rds/recv.c | 12 ++++++------
2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/net/rds/rds.h b/net/rds/rds.h
index 966d2ee..d8070c7 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -8,6 +8,7 @@
#include <linux/mutex.h>
#include <linux/rds.h>
#include <linux/rhashtable.h>
+#include <linux/refcount.h>

#include "info.h"

@@ -260,7 +261,7 @@ struct rds_ext_header_rdma_dest {
#define RDS_MSG_RX_CMSG 3

struct rds_incoming {
- atomic_t i_refcount;
+ refcount_t i_refcount;
struct list_head i_item;
struct rds_connection *i_conn;
struct rds_conn_path *i_conn_path;
diff --git a/net/rds/recv.c b/net/rds/recv.c
index 8b7e7b7..7d5e35e 100644
--- a/net/rds/recv.c
+++ b/net/rds/recv.c
@@ -45,7 +45,7 @@ void rds_inc_init(struct rds_incoming *inc, struct rds_connection *conn,
{
int i;

- atomic_set(&inc->i_refcount, 1);
+ refcount_set(&inc->i_refcount, 1);
INIT_LIST_HEAD(&inc->i_item);
inc->i_conn = conn;
inc->i_saddr = saddr;
@@ -61,7 +61,7 @@ EXPORT_SYMBOL_GPL(rds_inc_init);
void rds_inc_path_init(struct rds_incoming *inc, struct rds_conn_path *cp,
__be32 saddr)
{
- atomic_set(&inc->i_refcount, 1);
+ refcount_set(&inc->i_refcount, 1);
INIT_LIST_HEAD(&inc->i_item);
inc->i_conn = cp->cp_conn;
inc->i_conn_path = cp;
@@ -74,14 +74,14 @@ EXPORT_SYMBOL_GPL(rds_inc_path_init);

static void rds_inc_addref(struct rds_incoming *inc)
{
- rdsdebug("addref inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
- atomic_inc(&inc->i_refcount);
+ rdsdebug("addref inc %p ref %d\n", inc, refcount_read(&inc->i_refcount));
+ refcount_inc(&inc->i_refcount);
}

void rds_inc_put(struct rds_incoming *inc)
{
- rdsdebug("put inc %p ref %d\n", inc, atomic_read(&inc->i_refcount));
- if (atomic_dec_and_test(&inc->i_refcount)) {
+ rdsdebug("put inc %p ref %d\n", inc, refcount_read(&inc->i_refcount));
+ if (refcount_dec_and_test(&inc->i_refcount)) {
BUG_ON(!list_empty(&inc->i_item));

inc->i_conn->c_trans->inc_free(inc);
--
2.7.4

2017-03-17 12:17:07

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 17/23] net, sctp: convert sctp_datamsg.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/sctp/structs.h | 2 +-
net/sctp/chunk.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index a244db5..106e1d3 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -491,7 +491,7 @@ struct sctp_datamsg {
/* Chunks waiting to be submitted to lower layer. */
struct list_head chunks;
/* Reference counting. */
- atomic_t refcnt;
+ refcount_t refcnt;
/* When is this message no longer interesting to the peer? */
unsigned long expires_at;
/* Did the messenge fail to send? */
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c
index e3621cb..30c73ce 100644
--- a/net/sctp/chunk.c
+++ b/net/sctp/chunk.c
@@ -49,7 +49,7 @@
/* Initialize datamsg from memory. */
static void sctp_datamsg_init(struct sctp_datamsg *msg)
{
- atomic_set(&msg->refcnt, 1);
+ refcount_set(&msg->refcnt, 1);
msg->send_failed = 0;
msg->send_error = 0;
msg->can_delay = 1;
@@ -136,13 +136,13 @@ static void sctp_datamsg_destroy(struct sctp_datamsg *msg)
/* Hold a reference. */
static void sctp_datamsg_hold(struct sctp_datamsg *msg)
{
- atomic_inc(&msg->refcnt);
+ refcount_inc(&msg->refcnt);
}

/* Release a reference. */
void sctp_datamsg_put(struct sctp_datamsg *msg)
{
- if (atomic_dec_and_test(&msg->refcnt))
+ if (refcount_dec_and_test(&msg->refcnt))
sctp_datamsg_destroy(msg);
}

--
2.7.4

2017-03-17 12:17:06

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 14/23] net, xfrm: convert xfrm_policy.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/xfrm.h | 6 +++---
net/key/af_key.c | 2 +-
net/xfrm/xfrm_policy.c | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 163cda5..be30846 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -525,7 +525,7 @@ struct xfrm_policy {

/* This lock only affects elements except for entry. */
rwlock_t lock;
- atomic_t refcnt;
+ refcount_t refcnt;
struct timer_list timer;

struct flow_cache_object flo;
@@ -781,14 +781,14 @@ static inline void xfrm_audit_state_icvfail(struct xfrm_state *x,
static inline void xfrm_pol_hold(struct xfrm_policy *policy)
{
if (likely(policy != NULL))
- atomic_inc(&policy->refcnt);
+ refcount_inc(&policy->refcnt);
}

void xfrm_policy_destroy(struct xfrm_policy *policy);

static inline void xfrm_pol_put(struct xfrm_policy *policy)
{
- if (atomic_dec_and_test(&policy->refcnt))
+ if (refcount_dec_and_test(&policy->refcnt))
xfrm_policy_destroy(policy);
}

diff --git a/net/key/af_key.c b/net/key/af_key.c
index c6252ed..d3611af 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -2152,7 +2152,7 @@ static int pfkey_xfrm_policy2msg(struct sk_buff *skb, const struct xfrm_policy *
}

hdr->sadb_msg_len = size / sizeof(uint64_t);
- hdr->sadb_msg_reserved = atomic_read(&xp->refcnt);
+ hdr->sadb_msg_reserved = refcount_read(&xp->refcnt);

return 0;
}
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 236cbbc..91cf3e7 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -62,7 +62,7 @@ static struct xfrm_policy *__xfrm_policy_unlink(struct xfrm_policy *pol,

static inline bool xfrm_pol_hold_rcu(struct xfrm_policy *policy)
{
- return atomic_inc_not_zero(&policy->refcnt);
+ return refcount_inc_not_zero(&policy->refcnt);
}

static inline bool
@@ -292,7 +292,7 @@ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp)
INIT_HLIST_NODE(&policy->bydst);
INIT_HLIST_NODE(&policy->byidx);
rwlock_init(&policy->lock);
- atomic_set(&policy->refcnt, 1);
+ refcount_set(&policy->refcnt, 1);
skb_queue_head_init(&policy->polq.hold_queue);
setup_timer(&policy->timer, xfrm_policy_timer,
(unsigned long)policy);
--
2.7.4

2017-03-17 12:17:04

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 16/23] net, sctp: convert sctp_auth_bytes.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/sctp/auth.h | 5 +++--
net/sctp/auth.c | 4 ++--
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/net/sctp/auth.h b/include/net/sctp/auth.h
index 9b9fb12..328fccc 100644
--- a/include/net/sctp/auth.h
+++ b/include/net/sctp/auth.h
@@ -31,6 +31,7 @@
#define __sctp_auth_h__

#include <linux/list.h>
+#include <linux/refcount.h>

struct sctp_endpoint;
struct sctp_association;
@@ -53,7 +54,7 @@ struct sctp_hmac {
* over SCTP-AUTH
*/
struct sctp_auth_bytes {
- atomic_t refcnt;
+ refcount_t refcnt;
__u32 len;
__u8 data[];
};
@@ -76,7 +77,7 @@ static inline void sctp_auth_key_hold(struct sctp_auth_bytes *key)
if (!key)
return;

- atomic_inc(&key->refcnt);
+ refcount_inc(&key->refcnt);
}

void sctp_auth_key_put(struct sctp_auth_bytes *key);
diff --git a/net/sctp/auth.c b/net/sctp/auth.c
index f99d485..b6c98fe 100644
--- a/net/sctp/auth.c
+++ b/net/sctp/auth.c
@@ -63,7 +63,7 @@ void sctp_auth_key_put(struct sctp_auth_bytes *key)
if (!key)
return;

- if (atomic_dec_and_test(&key->refcnt)) {
+ if (refcount_dec_and_test(&key->refcnt)) {
kzfree(key);
SCTP_DBG_OBJCNT_DEC(keys);
}
@@ -84,7 +84,7 @@ static struct sctp_auth_bytes *sctp_auth_create_key(__u32 key_len, gfp_t gfp)
return NULL;

key->len = key_len;
- atomic_set(&key->refcnt, 1);
+ refcount_set(&key->refcnt, 1);
SCTP_DBG_OBJCNT_INC(keys);

return key;
--
2.7.4

2017-03-17 12:18:16

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 22/23] net, ax25: convert ax25_route.refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/ax25.h | 6 +++---
net/ax25/ax25_route.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/ax25.h b/include/net/ax25.h
index edd82f0..e3467ba 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -185,7 +185,7 @@ typedef struct {

typedef struct ax25_route {
struct ax25_route *next;
- atomic_t refcount;
+ refcount_t refcount;
ax25_address callsign;
struct net_device *dev;
ax25_digi *digipeat;
@@ -194,14 +194,14 @@ typedef struct ax25_route {

static inline void ax25_hold_route(ax25_route *ax25_rt)
{
- atomic_inc(&ax25_rt->refcount);
+ refcount_inc(&ax25_rt->refcount);
}

void __ax25_put_route(ax25_route *ax25_rt);

static inline void ax25_put_route(ax25_route *ax25_rt)
{
- if (atomic_dec_and_test(&ax25_rt->refcount))
+ if (refcount_dec_and_test(&ax25_rt->refcount))
__ax25_put_route(ax25_rt);
}

diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index e1fda27..0446b89 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -114,7 +114,7 @@ static int __must_check ax25_rt_add(struct ax25_routes_struct *route)
return -ENOMEM;
}

- atomic_set(&ax25_rt->refcount, 1);
+ refcount_set(&ax25_rt->refcount, 1);
ax25_rt->callsign = route->dest_addr;
ax25_rt->dev = ax25_dev->dev;
ax25_rt->digipeat = NULL;
--
2.7.4

2017-03-17 12:19:09

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 20/23] net, sctp: convert sctp_ep_common.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/sctp/structs.h | 2 +-
net/sctp/associola.c | 6 +++---
net/sctp/endpointola.c | 6 +++---
3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index ac3184e..7a9ce11 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -1170,7 +1170,7 @@ struct sctp_ep_common {
* refcnt - Reference count access to this object.
* dead - Do not attempt to use this object.
*/
- atomic_t refcnt;
+ refcount_t refcnt;
bool dead;

/* What socket does this endpoint belong to? */
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index 2a6835b..e5b60b5 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -89,7 +89,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a
asoc->base.type = SCTP_EP_TYPE_ASSOCIATION;

/* Initialize the object handling fields. */
- atomic_set(&asoc->base.refcnt, 1);
+ refcount_set(&asoc->base.refcnt, 1);

/* Initialize the bind addr area. */
sctp_bind_addr_init(&asoc->base.bind_addr, ep->base.bind_addr.port);
@@ -869,7 +869,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
/* Hold a reference to an association. */
void sctp_association_hold(struct sctp_association *asoc)
{
- atomic_inc(&asoc->base.refcnt);
+ refcount_inc(&asoc->base.refcnt);
}

/* Release a reference to an association and cleanup
@@ -877,7 +877,7 @@ void sctp_association_hold(struct sctp_association *asoc)
*/
void sctp_association_put(struct sctp_association *asoc)
{
- if (atomic_dec_and_test(&asoc->base.refcnt))
+ if (refcount_dec_and_test(&asoc->base.refcnt))
sctp_association_destroy(asoc);
}

diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 8c58923..9189a9f 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -113,7 +113,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
ep->base.type = SCTP_EP_TYPE_SOCKET;

/* Initialize the basic object fields. */
- atomic_set(&ep->base.refcnt, 1);
+ refcount_set(&ep->base.refcnt, 1);
ep->base.dead = false;

/* Create an input queue. */
@@ -285,7 +285,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
/* Hold a reference to an endpoint. */
void sctp_endpoint_hold(struct sctp_endpoint *ep)
{
- atomic_inc(&ep->base.refcnt);
+ refcount_inc(&ep->base.refcnt);
}

/* Release a reference to an endpoint and clean up if there are
@@ -293,7 +293,7 @@ void sctp_endpoint_hold(struct sctp_endpoint *ep)
*/
void sctp_endpoint_put(struct sctp_endpoint *ep)
{
- if (atomic_dec_and_test(&ep->base.refcnt))
+ if (refcount_dec_and_test(&ep->base.refcnt))
sctp_endpoint_destroy(ep);
}

--
2.7.4

2017-03-17 12:19:06

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 19/23] net, sctp: convert sctp_transport.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/sctp/structs.h | 2 +-
net/sctp/transport.c | 8 ++++----
2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 7ee0c26..ac3184e 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -731,7 +731,7 @@ struct sctp_transport {
struct rhlist_head node;

/* Reference counting. */
- atomic_t refcnt;
+ refcount_t refcnt;
/* RTO-Pending : A flag used to track if one of the DATA
* chunks sent to this address is currently being
* used to compute a RTT. If this flag is 0,
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index 3379668..45a5774 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -99,7 +99,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
/* Initialize the 64-bit random nonce sent with heartbeat. */
get_random_bytes(&peer->hb_nonce, sizeof(peer->hb_nonce));

- atomic_set(&peer->refcnt, 1);
+ refcount_set(&peer->refcnt, 1);

return peer;
}
@@ -172,7 +172,7 @@ static void sctp_transport_destroy_rcu(struct rcu_head *head)
*/
static void sctp_transport_destroy(struct sctp_transport *transport)
{
- if (unlikely(atomic_read(&transport->refcnt))) {
+ if (unlikely(refcount_read(&transport->refcnt))) {
WARN(1, "Attempt to destroy undead transport %p!\n", transport);
return;
}
@@ -316,7 +316,7 @@ void sctp_transport_route(struct sctp_transport *transport,
/* Hold a reference to a transport. */
int sctp_transport_hold(struct sctp_transport *transport)
{
- return atomic_add_unless(&transport->refcnt, 1, 0);
+ return refcount_inc_not_zero(&transport->refcnt);
}

/* Release a reference to a transport and clean up
@@ -324,7 +324,7 @@ int sctp_transport_hold(struct sctp_transport *transport)
*/
void sctp_transport_put(struct sctp_transport *transport)
{
- if (atomic_dec_and_test(&transport->refcnt))
+ if (refcount_dec_and_test(&transport->refcnt))
sctp_transport_destroy(transport);
}

--
2.7.4

2017-03-17 12:19:57

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 18/23] net, sctp: convert sctp_chunk.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/sctp/structs.h | 2 +-
net/sctp/sm_make_chunk.c | 6 +++---
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 106e1d3..7ee0c26 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -520,7 +520,7 @@ int sctp_chunk_abandoned(struct sctp_chunk *);
struct sctp_chunk {
struct list_head list;

- atomic_t refcnt;
+ refcount_t refcnt;

/* How many times this chunk have been sent, for prsctp RTX policy */
int sent_count;
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 969a30c..a54add6 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -1346,7 +1346,7 @@ struct sctp_chunk *sctp_chunkify(struct sk_buff *skb,
INIT_LIST_HEAD(&retval->transmitted_list);
INIT_LIST_HEAD(&retval->frag_list);
SCTP_DBG_OBJCNT_INC(chunk);
- atomic_set(&retval->refcnt, 1);
+ refcount_set(&retval->refcnt, 1);

nodata:
return retval;
@@ -1459,13 +1459,13 @@ void sctp_chunk_free(struct sctp_chunk *chunk)
/* Grab a reference to the chunk. */
void sctp_chunk_hold(struct sctp_chunk *ch)
{
- atomic_inc(&ch->refcnt);
+ refcount_inc(&ch->refcnt);
}

/* Release a reference to the chunk. */
void sctp_chunk_put(struct sctp_chunk *ch)
{
- if (atomic_dec_and_test(&ch->refcnt))
+ if (refcount_dec_and_test(&ch->refcnt))
sctp_chunk_destroy(ch);
}

--
2.7.4

2017-03-17 12:20:57

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 23/23] net, ax25: convert ax25_cb.refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/ax25.h | 6 +++---
net/ax25/af_ax25.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/ax25.h b/include/net/ax25.h
index e3467ba..c4a0cf6 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -244,7 +244,7 @@ typedef struct ax25_cb {
unsigned char window;
struct timer_list timer, dtimer;
struct sock *sk; /* Backlink to socket */
- atomic_t refcount;
+ refcount_t refcount;
} ax25_cb;

struct ax25_sock {
@@ -266,11 +266,11 @@ static inline struct ax25_cb *sk_to_ax25(const struct sock *sk)
hlist_for_each_entry(__ax25, list, ax25_node)

#define ax25_cb_hold(__ax25) \
- atomic_inc(&((__ax25)->refcount))
+ refcount_inc(&((__ax25)->refcount))

static __inline__ void ax25_cb_put(ax25_cb *ax25)
{
- if (atomic_dec_and_test(&ax25->refcount)) {
+ if (refcount_dec_and_test(&ax25->refcount)) {
kfree(ax25->digipeat);
kfree(ax25);
}
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index 90fcf5f..163e81f 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -510,7 +510,7 @@ ax25_cb *ax25_create_cb(void)
if ((ax25 = kzalloc(sizeof(*ax25), GFP_ATOMIC)) == NULL)
return NULL;

- atomic_set(&ax25->refcount, 1);
+ refcount_set(&ax25->refcount, 1);

skb_queue_head_init(&ax25->write_queue);
skb_queue_head_init(&ax25->frag_queue);
--
2.7.4

2017-03-17 12:19:54

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 21/23] net, ax25: convert ax25_uid_assoc.refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/ax25.h | 8 ++++----
net/ax25/ax25_uid.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/net/ax25.h b/include/net/ax25.h
index e602f81..edd82f0 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -11,7 +11,7 @@
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/slab.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
#include <net/neighbour.h>
#include <net/sock.h>

@@ -158,7 +158,7 @@ enum {

typedef struct ax25_uid_assoc {
struct hlist_node uid_node;
- atomic_t refcount;
+ refcount_t refcount;
kuid_t uid;
ax25_address call;
} ax25_uid_assoc;
@@ -167,11 +167,11 @@ typedef struct ax25_uid_assoc {
hlist_for_each_entry(__ax25, list, uid_node)

#define ax25_uid_hold(ax25) \
- atomic_inc(&((ax25)->refcount))
+ refcount_inc(&((ax25)->refcount))

static inline void ax25_uid_put(ax25_uid_assoc *assoc)
{
- if (atomic_dec_and_test(&assoc->refcount)) {
+ if (refcount_dec_and_test(&assoc->refcount)) {
kfree(assoc);
}
}
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c
index 0403b0d..83b035f 100644
--- a/net/ax25/ax25_uid.c
+++ b/net/ax25/ax25_uid.c
@@ -107,7 +107,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax)
if ((ax25_uid = kmalloc(sizeof(*ax25_uid), GFP_KERNEL)) == NULL)
return -ENOMEM;

- atomic_set(&ax25_uid->refcount, 1);
+ refcount_set(&ax25_uid->refcount, 1);
ax25_uid->uid = sax25_kuid;
ax25_uid->call = sax->sax25_call;

--
2.7.4

2017-03-17 12:21:44

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 12/23] net, x25: convert x25_neigh.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/x25.h | 6 +++---
net/x25/x25_link.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/include/net/x25.h b/include/net/x25.h
index 83a6d31..265756c 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -142,7 +142,7 @@ struct x25_neigh {
unsigned long t20;
struct timer_list t20timer;
unsigned long global_facil_mask;
- atomic_t refcnt;
+ refcount_t refcnt;
};

struct x25_sock {
@@ -243,12 +243,12 @@ void x25_link_free(void);
/* x25_neigh.c */
static __inline__ void x25_neigh_hold(struct x25_neigh *nb)
{
- atomic_inc(&nb->refcnt);
+ refcount_inc(&nb->refcnt);
}

static __inline__ void x25_neigh_put(struct x25_neigh *nb)
{
- if (atomic_dec_and_test(&nb->refcnt))
+ if (refcount_dec_and_test(&nb->refcnt))
kfree(nb);
}

diff --git a/net/x25/x25_link.c b/net/x25/x25_link.c
index bcaa180..e0cd04d 100644
--- a/net/x25/x25_link.c
+++ b/net/x25/x25_link.c
@@ -266,7 +266,7 @@ void x25_link_device_up(struct net_device *dev)
X25_MASK_PACKET_SIZE |
X25_MASK_WINDOW_SIZE;
nb->t20 = sysctl_x25_restart_request_timeout;
- atomic_set(&nb->refcnt, 1);
+ refcount_set(&nb->refcnt, 1);

write_lock_bh(&x25_neigh_list_lock);
list_add(&nb->node, &x25_neigh_list);
--
2.7.4

2017-03-17 12:21:46

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 11/23] net, x25: convert x25_route.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/x25.h | 7 ++++---
net/x25/x25_route.c | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/include/net/x25.h b/include/net/x25.h
index c383aa4..83a6d31 100644
--- a/include/net/x25.h
+++ b/include/net/x25.h
@@ -11,6 +11,7 @@
#define _X25_H
#include <linux/x25.h>
#include <linux/slab.h>
+#include <linux/refcount.h>
#include <net/sock.h>

#define X25_ADDR_LEN 16
@@ -129,7 +130,7 @@ struct x25_route {
struct x25_address address;
unsigned int sigdigits;
struct net_device *dev;
- atomic_t refcnt;
+ refcount_t refcnt;
};

struct x25_neigh {
@@ -265,12 +266,12 @@ void x25_route_free(void);

static __inline__ void x25_route_hold(struct x25_route *rt)
{
- atomic_inc(&rt->refcnt);
+ refcount_inc(&rt->refcnt);
}

static __inline__ void x25_route_put(struct x25_route *rt)
{
- if (atomic_dec_and_test(&rt->refcnt))
+ if (refcount_dec_and_test(&rt->refcnt))
kfree(rt);
}

diff --git a/net/x25/x25_route.c b/net/x25/x25_route.c
index 277c8d2..b85b889 100644
--- a/net/x25/x25_route.c
+++ b/net/x25/x25_route.c
@@ -55,7 +55,7 @@ static int x25_add_route(struct x25_address *address, unsigned int sigdigits,

rt->sigdigits = sigdigits;
rt->dev = dev;
- atomic_set(&rt->refcnt, 1);
+ refcount_set(&rt->refcnt, 1);

list_add(&rt->node, &x25_route_list);
rc = 0;
--
2.7.4

2017-03-17 12:21:40

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 13/23] net, xfrm: convert xfrm_state.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/xfrm.h | 9 +++++----
net/xfrm/xfrm_state.c | 4 ++--
2 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index 14d82bf..163cda5 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -13,6 +13,7 @@
#include <linux/mutex.h>
#include <linux/audit.h>
#include <linux/slab.h>
+#include <linux/refcount.h>

#include <net/sock.h>
#include <net/dst.h>
@@ -130,7 +131,7 @@ struct xfrm_state {
struct hlist_node bysrc;
struct hlist_node byspi;

- atomic_t refcnt;
+ refcount_t refcnt;
spinlock_t lock;

struct xfrm_id id;
@@ -802,18 +803,18 @@ void __xfrm_state_destroy(struct xfrm_state *);

static inline void __xfrm_state_put(struct xfrm_state *x)
{
- atomic_dec(&x->refcnt);
+ refcount_dec(&x->refcnt);
}

static inline void xfrm_state_put(struct xfrm_state *x)
{
- if (atomic_dec_and_test(&x->refcnt))
+ if (refcount_dec_and_test(&x->refcnt))
__xfrm_state_destroy(x);
}

static inline void xfrm_state_hold(struct xfrm_state *x)
{
- atomic_inc(&x->refcnt);
+ refcount_inc(&x->refcnt);
}

static inline bool addr_match(const void *token1, const void *token2,
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 5a597db..a91109f 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -48,7 +48,7 @@ static HLIST_HEAD(xfrm_state_gc_list);

static inline bool xfrm_state_hold_rcu(struct xfrm_state __rcu *x)
{
- return atomic_inc_not_zero(&x->refcnt);
+ return refcount_inc_not_zero(&x->refcnt);
}

static inline unsigned int xfrm_dst_hash(struct net *net,
@@ -486,7 +486,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)

if (x) {
write_pnet(&x->xs_net, net);
- atomic_set(&x->refcnt, 1);
+ refcount_set(&x->refcnt, 1);
atomic_set(&x->tunnel_users, 0);
INIT_LIST_HEAD(&x->km.all);
INIT_HLIST_NODE(&x->bydst);
--
2.7.4

2017-03-17 12:25:24

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 15/23] net, xfrm: convert sec_path.refcnt from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
include/net/xfrm.h | 6 +++---
net/xfrm/xfrm_input.c | 4 ++--
2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index be30846..35d1cca 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -1005,7 +1005,7 @@ struct xfrm_offload {
};

struct sec_path {
- atomic_t refcnt;
+ refcount_t refcnt;
int len;
int olen;

@@ -1026,7 +1026,7 @@ static inline struct sec_path *
secpath_get(struct sec_path *sp)
{
if (sp)
- atomic_inc(&sp->refcnt);
+ refcount_inc(&sp->refcnt);
return sp;
}

@@ -1035,7 +1035,7 @@ void __secpath_destroy(struct sec_path *sp);
static inline void
secpath_put(struct sec_path *sp)
{
- if (sp && atomic_dec_and_test(&sp->refcnt))
+ if (sp && refcount_dec_and_test(&sp->refcnt))
__secpath_destroy(sp);
}

diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index 46bdb4f..203ba90 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -114,7 +114,7 @@ struct sec_path *secpath_dup(struct sec_path *src)
for (i = 0; i < sp->len; i++)
xfrm_state_hold(sp->xvec[i]);
}
- atomic_set(&sp->refcnt, 1);
+ refcount_set(&sp->refcnt, 1);
return sp;
}
EXPORT_SYMBOL(secpath_dup);
@@ -124,7 +124,7 @@ int secpath_set(struct sk_buff *skb)
struct sec_path *sp;

/* Allocate new secpath or COW existing one. */
- if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) {
+ if (!skb->sp || refcount_read(&skb->sp->refcnt) != 1) {
sp = secpath_dup(skb->sp);
if (!sp)
return -ENOMEM;
--
2.7.4

2017-03-17 12:26:48

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 09/23] net, rds: convert rds_mr.r_refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
net/rds/rdma.c | 10 +++++-----
net/rds/rds.h | 4 ++--
2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/rds/rdma.c b/net/rds/rdma.c
index f06fac4..8886f15 100644
--- a/net/rds/rdma.c
+++ b/net/rds/rdma.c
@@ -84,7 +84,7 @@ static struct rds_mr *rds_mr_tree_walk(struct rb_root *root, u64 key,
if (insert) {
rb_link_node(&insert->r_rb_node, parent, p);
rb_insert_color(&insert->r_rb_node, root);
- atomic_inc(&insert->r_refcount);
+ refcount_inc(&insert->r_refcount);
}
return NULL;
}
@@ -99,7 +99,7 @@ static void rds_destroy_mr(struct rds_mr *mr)
unsigned long flags;

rdsdebug("RDS: destroy mr key is %x refcnt %u\n",
- mr->r_key, atomic_read(&mr->r_refcount));
+ mr->r_key, refcount_read(&mr->r_refcount));

if (test_and_set_bit(RDS_MR_DEAD, &mr->r_state))
return;
@@ -223,7 +223,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,
goto out;
}

- atomic_set(&mr->r_refcount, 1);
+ refcount_set(&mr->r_refcount, 1);
RB_CLEAR_NODE(&mr->r_rb_node);
mr->r_trans = rs->rs_transport;
mr->r_sock = rs;
@@ -307,7 +307,7 @@ static int __rds_rdma_map(struct rds_sock *rs, struct rds_get_mr_args *args,

rdsdebug("RDS: get_mr key is %x\n", mr->r_key);
if (mr_ret) {
- atomic_inc(&mr->r_refcount);
+ refcount_inc(&mr->r_refcount);
*mr_ret = mr;
}

@@ -756,7 +756,7 @@ int rds_cmsg_rdma_dest(struct rds_sock *rs, struct rds_message *rm,
if (!mr)
err = -EINVAL; /* invalid r_key */
else
- atomic_inc(&mr->r_refcount);
+ refcount_inc(&mr->r_refcount);
spin_unlock_irqrestore(&rs->rs_rdma_lock, flags);

if (mr) {
diff --git a/net/rds/rds.h b/net/rds/rds.h
index d8070c7..7487597 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -276,7 +276,7 @@ struct rds_incoming {

struct rds_mr {
struct rb_node r_rb_node;
- atomic_t r_refcount;
+ refcount_t r_refcount;
u32 r_key;

/* A copy of the creation flags */
@@ -855,7 +855,7 @@ int rds_cmsg_atomic(struct rds_sock *rs, struct rds_message *rm,
void __rds_put_mr_final(struct rds_mr *mr);
static inline void rds_mr_put(struct rds_mr *mr)
{
- if (atomic_dec_and_test(&mr->r_refcount))
+ if (refcount_dec_and_test(&mr->r_refcount))
__rds_put_mr_final(mr);
}

--
2.7.4

2017-03-17 12:26:47

by Elena Reshetova

[permalink] [raw]
Subject: [PATCH 10/23] net, rds: convert rds_message.m_refcount from atomic_t to refcount_t

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 <[email protected]>
Signed-off-by: Hans Liljestrand <[email protected]>
Signed-off-by: Kees Cook <[email protected]>
Signed-off-by: David Windsor <[email protected]>
---
net/rds/message.c | 12 ++++++------
net/rds/rds.h | 2 +-
2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/net/rds/message.c b/net/rds/message.c
index 49bfb51..4318cc9 100644
--- a/net/rds/message.c
+++ b/net/rds/message.c
@@ -48,8 +48,8 @@ static unsigned int rds_exthdr_size[__RDS_EXTHDR_MAX] = {

void rds_message_addref(struct rds_message *rm)
{
- rdsdebug("addref rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
- atomic_inc(&rm->m_refcount);
+ rdsdebug("addref rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
+ refcount_inc(&rm->m_refcount);
}
EXPORT_SYMBOL_GPL(rds_message_addref);

@@ -83,9 +83,9 @@ static void rds_message_purge(struct rds_message *rm)

void rds_message_put(struct rds_message *rm)
{
- rdsdebug("put rm %p ref %d\n", rm, atomic_read(&rm->m_refcount));
- WARN(!atomic_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
- if (atomic_dec_and_test(&rm->m_refcount)) {
+ rdsdebug("put rm %p ref %d\n", rm, refcount_read(&rm->m_refcount));
+ WARN(!refcount_read(&rm->m_refcount), "danger refcount zero on %p\n", rm);
+ if (refcount_dec_and_test(&rm->m_refcount)) {
BUG_ON(!list_empty(&rm->m_sock_item));
BUG_ON(!list_empty(&rm->m_conn_item));
rds_message_purge(rm);
@@ -206,7 +206,7 @@ struct rds_message *rds_message_alloc(unsigned int extra_len, gfp_t gfp)
rm->m_used_sgs = 0;
rm->m_total_sgs = extra_len / sizeof(struct scatterlist);

- atomic_set(&rm->m_refcount, 1);
+ refcount_set(&rm->m_refcount, 1);
INIT_LIST_HEAD(&rm->m_sock_item);
INIT_LIST_HEAD(&rm->m_conn_item);
spin_lock_init(&rm->m_rs_lock);
diff --git a/net/rds/rds.h b/net/rds/rds.h
index 7487597..8c205ff 100644
--- a/net/rds/rds.h
+++ b/net/rds/rds.h
@@ -355,7 +355,7 @@ static inline u32 rds_rdma_cookie_offset(rds_rdma_cookie_t cookie)
#define RDS_MSG_FLUSH 8

struct rds_message {
- atomic_t m_refcount;
+ refcount_t m_refcount;
struct list_head m_sock_item;
struct list_head m_conn_item;
struct rds_incoming m_inc;
--
2.7.4

2017-03-17 12:53:48

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 01/23] net, sunrpc: convert rpc_cred.cr_count from atomic_t to refcount_t

On Fri, 2017-03-17 at 14:10 +0200, Elena Reshetova wrote:
> 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 <[email protected]>
> Signed-off-by: Hans Liljestrand <[email protected]>
> Signed-off-by: Kees Cook <[email protected]>
> Signed-off-by: David Windsor <[email protected]>
> ---
>  include/linux/sunrpc/auth.h |  8 ++++----
>  net/sunrpc/auth.c           | 12 ++++++------
>  2 files changed, 10 insertions(+), 10 deletions(-)
>
> diff --git a/include/linux/sunrpc/auth.h
> b/include/linux/sunrpc/auth.h
> index b1bc62b..bd36e0b 100644
> --- a/include/linux/sunrpc/auth.h
> +++ b/include/linux/sunrpc/auth.h
> @@ -15,7 +15,7 @@
>  #include <linux/sunrpc/msg_prot.h>
>  #include <linux/sunrpc/xdr.h>
>  
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
>  #include <linux/rcupdate.h>
>  #include <linux/uidgid.h>
>  #include <linux/utsname.h>
> @@ -68,7 +68,7 @@ struct rpc_cred {
>  #endif
>   unsigned long cr_expire; /* when to gc
> */
>   unsigned long cr_flags; /* various
> flags */
> - atomic_t cr_count; /* ref count */
> + refcount_t cr_count; /* ref count */
>

NACK. That's going to be hitting WARN_ONCE(!refcount_inc_not_zero(r),
"refcount_t: increment on 0; use-after-free.\n") like there's no
tomorrow...

Please stop with these automated conversions. They are going to cause a
lot more bugs than they fix.

--
Trond Myklebust
Linux NFS client maintainer, PrimaryData
[email protected]

2017-03-17 13:03:47

by Jeff Layton

[permalink] [raw]
Subject: Re: [PATCH 01/23] net, sunrpc: convert rpc_cred.cr_count from atomic_t to refcount_t

On Fri, 2017-03-17 at 12:50 +0000, Trond Myklebust wrote:
> On Fri, 2017-03-17 at 14:10 +0200, Elena Reshetova wrote:
> > 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 <[email protected]>
> > Signed-off-by: Hans Liljestrand <[email protected]>
> > Signed-off-by: Kees Cook <[email protected]>
> > Signed-off-by: David Windsor <[email protected]>
> > ---
> >  include/linux/sunrpc/auth.h |  8 ++++----
> >  net/sunrpc/auth.c           | 12 ++++++------
> >  2 files changed, 10 insertions(+), 10 deletions(-)
> >
> > diff --git a/include/linux/sunrpc/auth.h
> > b/include/linux/sunrpc/auth.h
> > index b1bc62b..bd36e0b 100644
> > --- a/include/linux/sunrpc/auth.h
> > +++ b/include/linux/sunrpc/auth.h
> > @@ -15,7 +15,7 @@
> >  #include <linux/sunrpc/msg_prot.h>
> >  #include <linux/sunrpc/xdr.h>
> >  
> > -#include <linux/atomic.h>
> > +#include <linux/refcount.h>
> >  #include <linux/rcupdate.h>
> >  #include <linux/uidgid.h>
> >  #include <linux/utsname.h>
> > @@ -68,7 +68,7 @@ struct rpc_cred {
> >  #endif
> >   unsigned long cr_expire; /* when to gc
> > */
> >   unsigned long cr_flags; /* various
> > flags */
> > - atomic_t cr_count; /* ref count */
> > + refcount_t cr_count; /* ref count */
> >
>
> NACK. That's going to be hitting WARN_ONCE(!refcount_inc_not_zero(r),
> "refcount_t: increment on 0; use-after-free.\n") like there's no
> tomorrow...
>
> Please stop with these automated conversions. They are going to cause a
> lot more bugs than they fix.
>

Agreed. These patchsets are touching places where we've already banged
out most of the refcounting bugs. I'm against doing large scale
conversions like this without a damned good reason.

I think it may be best to do this sort of thing in a more piecemeal
fashion. Pick a subsystem or two and do the conversions there to prove
that they're better than what we have. If the subsystem already has
problems with its refcounting, then so much the better. Point to bugs
that this new infrastructure helped find.

Encourage people to adopt your new infrastructure as new refcounted
objects are introduced into the kernel. You might even consider a LWN
article about this.

Eventually we'll get around to changing existing code to use it, once
there is a sufficient advantage to doing so. Most likely when we're
reworking the code for other reasons, or when we're chasing some horrid
refcounting bug and think that this might help find it.
--
Jeff Layton <[email protected]>

2017-03-17 14:31:29

by Trond Myklebust

[permalink] [raw]
Subject: Re: [PATCH 01/23] net, sunrpc: convert rpc_cred.cr_count from atomic_t to refcount_t

On Fri, 2017-03-17 at 09:02 -0400, Jeff Layton wrote:
> On Fri, 2017-03-17 at 12:50 +0000, Trond Myklebust wrote:
> > On Fri, 2017-03-17 at 14:10 +0200, Elena Reshetova wrote:
> > > 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 <[email protected]>
> > > Signed-off-by: Hans Liljestrand <[email protected]>
> > > Signed-off-by: Kees Cook <[email protected]>
> > > Signed-off-by: David Windsor <[email protected]>
> > > ---
> > >  include/linux/sunrpc/auth.h |  8 ++++----
> > >  net/sunrpc/auth.c           | 12 ++++++------
> > >  2 files changed, 10 insertions(+), 10 deletions(-)
> > >
> > > diff --git a/include/linux/sunrpc/auth.h
> > > b/include/linux/sunrpc/auth.h
> > > index b1bc62b..bd36e0b 100644
> > > --- a/include/linux/sunrpc/auth.h
> > > +++ b/include/linux/sunrpc/auth.h
> > > @@ -15,7 +15,7 @@
> > >  #include <linux/sunrpc/msg_prot.h>
> > >  #include <linux/sunrpc/xdr.h>
> > >  
> > > -#include <linux/atomic.h>
> > > +#include <linux/refcount.h>
> > >  #include <linux/rcupdate.h>
> > >  #include <linux/uidgid.h>
> > >  #include <linux/utsname.h>
> > > @@ -68,7 +68,7 @@ struct rpc_cred {
> > >  #endif
> > >   unsigned long cr_expire; /* when
> > > to gc
> > > */
> > >   unsigned long cr_flags; /* various
> > > flags */
> > > - atomic_t cr_count; /* ref count */
> > > + refcount_t cr_count; /* ref count
> > > */
> > >
> >
> > NACK. That's going to be hitting
> > WARN_ONCE(!refcount_inc_not_zero(r),
> > "refcount_t: increment on 0; use-after-free.\n") like there's no
> > tomorrow...
> >
> > Please stop with these automated conversions. They are going to
> > cause a
> > lot more bugs than they fix.
> >
>
> Agreed. These patchsets are touching places where we've already
> banged
> out most of the refcounting bugs. I'm against doing large scale
> conversions like this without a damned good reason.
>
> I think it may be best to do this sort of thing in a more piecemeal
> fashion. Pick a subsystem or two and do the conversions there to
> prove
> that they're better than what we have. If the subsystem already has
> problems with its refcounting, then so much the better. Point to bugs
> that this new infrastructure helped find.
>
> Encourage people to adopt your new infrastructure as new refcounted
> objects are introduced into the kernel. You might even consider a LWN
> article about this.
>
> Eventually we'll get around to changing existing code to use it, once
> there is a sufficient advantage to doing so. Most likely when we're
> reworking the code for other reasons, or when we're chasing some
> horrid
> refcounting bug and think that this might help find it.

The main issue is that this "refcount_t" implementation appears to be
assuming that there is one and only one model for refcounts (the one
where a value of "0" means "free me immediately").

The kernel has a plethora of object caching implementations where this
is simply not the case; the dcache is a prime example, and this cache
is another. In both these implementation, the atomic_t variable is
being used more as a semaphore-style lock that prevents freeing of the
object while it is in active use as opposed to being freeable, but
cached. This is why these automated conversions are a nuisance and a
source of bugs.

--
Trond Myklebust
Linux NFS client maintainer, PrimaryData
[email protected]

2017-03-20 16:16:48

by Elena Reshetova

[permalink] [raw]
Subject: RE: [PATCH 01/23] net, sunrpc: convert rpc_cred.cr_count from atomic_t to refcount_t

> On Fri, 2017-03-17 at 09:02 -0400, Jeff Layton wrote:
> > On Fri, 2017-03-17 at 12:50 +0000, Trond Myklebust wrote:
> > > On Fri, 2017-03-17 at 14:10 +0200, Elena Reshetova wrote:
> > > > 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 <[email protected]>
> > > > Signed-off-by: Hans Liljestrand <[email protected]>
> > > > Signed-off-by: Kees Cook <[email protected]>
> > > > Signed-off-by: David Windsor <[email protected]>
> > > > ---
> > > >  include/linux/sunrpc/auth.h |  8 ++++----
> > > >  net/sunrpc/auth.c           | 12 ++++++------
> > > >  2 files changed, 10 insertions(+), 10 deletions(-)
> > > >
> > > > diff --git a/include/linux/sunrpc/auth.h
> > > > b/include/linux/sunrpc/auth.h
> > > > index b1bc62b..bd36e0b 100644
> > > > --- a/include/linux/sunrpc/auth.h
> > > > +++ b/include/linux/sunrpc/auth.h
> > > > @@ -15,7 +15,7 @@
> > > >  #include <linux/sunrpc/msg_prot.h>
> > > >  #include <linux/sunrpc/xdr.h>
> > > >
> > > > -#include <linux/atomic.h>
> > > > +#include <linux/refcount.h>
> > > >  #include <linux/rcupdate.h>
> > > >  #include <linux/uidgid.h>
> > > >  #include <linux/utsname.h>
> > > > @@ -68,7 +68,7 @@ struct rpc_cred {
> > > >  #endif
> > > >   unsigned long cr_expire; /* when
> > > > to gc
> > > > */
> > > >   unsigned long cr_flags; /* various
> > > > flags */
> > > > - atomic_t cr_count; /* ref count */
> > > > + refcount_t cr_count; /* ref count
> > > > */
> > > >
> > >
> > > NACK. That's going to be hitting
> > > WARN_ONCE(!refcount_inc_not_zero(r),
> > > "refcount_t: increment on 0; use-after-free.\n") like there's no
> > > tomorrow...
> > >
> > > Please stop with these automated conversions. They are going to
> > > cause a
> > > lot more bugs than they fix.
> > >
> >
> > Agreed. These patchsets are touching places where we've already
> > banged
> > out most of the refcounting bugs. I'm against doing large scale
> > conversions like this without a damned good reason.
> >
> > I think it may be best to do this sort of thing in a more piecemeal
> > fashion. Pick a subsystem or two and do the conversions there to
> > prove
> > that they're better than what we have. If the subsystem already has
> > problems with its refcounting, then so much the better. Point to bugs
> > that this new infrastructure helped find.
> >
> > Encourage people to adopt your new infrastructure as new refcounted
> > objects are introduced into the kernel. You might even consider a LWN
> > article about this.
> >
> > Eventually we'll get around to changing existing code to use it, once
> > there is a sufficient advantage to doing so. Most likely when we're
> > reworking the code for other reasons, or when we're chasing some
> > horrid
> > refcounting bug and think that this might help find it.
>
> The main issue is that this "refcount_t" implementation appears to be
> assuming that there is one and only one model for refcounts (the one
> where a value of "0" means "free me immediately").
>
> The kernel has a plethora of object caching implementations where this
> is simply not the case; the dcache is a prime example, and this cache
> is another. In both these implementation, the atomic_t variable is
> being used more as a semaphore-style lock that prevents freeing of the
> object while it is in active use as opposed to being freeable, but
> cached. This is why these automated conversions are a nuisance and a
> source of bugs.

Ok, in this particular patch I agree that we missed that object is being reused
(and yes there are many parts in kernel where similar thing happens as we learned from this exercise).
Note that refcount_t implementation is fine with you "correctly" reusing your object:
i.e. when counter reaches zero, you take the object away from active use, but it might still stay in cache.
BUT when you get a new object from cache you should initialize refcounter properly: set it to one vs. just do a "inc" on it.
Problem really comes from this "increment me from zero".

And the goal with these conversions is to take a look broadly on the kernel source and determine (with the feedback from maintainers who know code best, like your feedback now) what can be converted already now.
Maintainers know their code and their usage of counters, so if it doesn't make sense to do it in a particular place (because of errors or other reasons), then it doesn't.
But more we cover with new refcount_t, less chances we have with ever hitting refcounter bugs anywhere in the future.

Best Regards,
Elena.

>
> --
> Trond Myklebust
> Linux NFS client maintainer, PrimaryData
> [email protected]

2017-03-24 13:20:49

by Ilya Dryomov

[permalink] [raw]
Subject: Re: [PATCH 04/23] net, ceph: convert ceph_snap_context.nref from atomic_t to refcount_t

On Fri, Mar 17, 2017 at 1:10 PM, Elena Reshetova
<[email protected]> wrote:
> 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 <[email protected]>
> Signed-off-by: Hans Liljestrand <[email protected]>
> Signed-off-by: Kees Cook <[email protected]>
> Signed-off-by: David Windsor <[email protected]>
> ---
> include/linux/ceph/libceph.h | 3 ++-
> net/ceph/snapshot.c | 6 +++---
> 2 files changed, 5 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
> index 1816c5e..26dc674 100644
> --- a/include/linux/ceph/libceph.h
> +++ b/include/linux/ceph/libceph.h
> @@ -14,6 +14,7 @@
> #include <linux/wait.h>
> #include <linux/writeback.h>
> #include <linux/slab.h>
> +#include <linux/refcount.h>
>
> #include <linux/ceph/types.h>
> #include <linux/ceph/messenger.h>
> @@ -159,7 +160,7 @@ struct ceph_client {
> * dirtied.
> */
> struct ceph_snap_context {
> - atomic_t nref;
> + refcount_t nref;
> u64 seq;
> u32 num_snaps;
> u64 snaps[];
> diff --git a/net/ceph/snapshot.c b/net/ceph/snapshot.c
> index 705414e..e14a5d0 100644
> --- a/net/ceph/snapshot.c
> +++ b/net/ceph/snapshot.c
> @@ -49,7 +49,7 @@ struct ceph_snap_context *ceph_create_snap_context(u32 snap_count,
> if (!snapc)
> return NULL;
>
> - atomic_set(&snapc->nref, 1);
> + refcount_set(&snapc->nref, 1);
> snapc->num_snaps = snap_count;
>
> return snapc;
> @@ -59,7 +59,7 @@ EXPORT_SYMBOL(ceph_create_snap_context);
> struct ceph_snap_context *ceph_get_snap_context(struct ceph_snap_context *sc)
> {
> if (sc)
> - atomic_inc(&sc->nref);
> + refcount_inc(&sc->nref);
> return sc;
> }
> EXPORT_SYMBOL(ceph_get_snap_context);
> @@ -68,7 +68,7 @@ void ceph_put_snap_context(struct ceph_snap_context *sc)
> {
> if (!sc)
> return;
> - if (atomic_dec_and_test(&sc->nref)) {
> + if (refcount_dec_and_test(&sc->nref)) {
> /*printk(" deleting snap_context %p\n", sc);*/
> kfree(sc);
> }

Applied.

Thanks,

Ilya

2017-03-24 13:49:36

by Ilya Dryomov

[permalink] [raw]
Subject: Re: [PATCH 05/23] net, ceph: convert ceph_osd.o_ref from atomic_t to refcount_t

On Fri, Mar 17, 2017 at 1:10 PM, Elena Reshetova
<[email protected]> wrote:
> 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 <[email protected]>
> Signed-off-by: Hans Liljestrand <[email protected]>
> Signed-off-by: Kees Cook <[email protected]>
> Signed-off-by: David Windsor <[email protected]>
> ---
> include/linux/ceph/osd_client.h | 3 ++-
> net/ceph/osd_client.c | 16 ++++++++--------
> 2 files changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
> index 2ea0c28..5ce0cd6 100644
> --- a/include/linux/ceph/osd_client.h
> +++ b/include/linux/ceph/osd_client.h
> @@ -5,6 +5,7 @@
> #include <linux/kref.h>
> #include <linux/mempool.h>
> #include <linux/rbtree.h>
> +#include <linux/refcount.h>
>
> #include <linux/ceph/types.h>
> #include <linux/ceph/osdmap.h>
> @@ -27,7 +28,7 @@ typedef void (*ceph_osdc_callback_t)(struct ceph_osd_request *);
>
> /* a given osd we're communicating with */
> struct ceph_osd {
> - atomic_t o_ref;
> + refcount_t o_ref;
> struct ceph_osd_client *o_osdc;
> int o_osd;
> int o_incarnation;
> diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
> index b65bbf9..99a51f0 100644
> --- a/net/ceph/osd_client.c
> +++ b/net/ceph/osd_client.c
> @@ -1005,7 +1005,7 @@ static bool osd_registered(struct ceph_osd *osd)
> */
> static void osd_init(struct ceph_osd *osd)
> {
> - atomic_set(&osd->o_ref, 1);
> + refcount_set(&osd->o_ref, 1);
> RB_CLEAR_NODE(&osd->o_node);
> osd->o_requests = RB_ROOT;
> osd->o_linger_requests = RB_ROOT;
> @@ -1050,9 +1050,9 @@ static struct ceph_osd *create_osd(struct ceph_osd_client *osdc, int onum)
>
> static struct ceph_osd *get_osd(struct ceph_osd *osd)
> {
> - if (atomic_inc_not_zero(&osd->o_ref)) {
> - dout("get_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref)-1,
> - atomic_read(&osd->o_ref));
> + if (refcount_inc_not_zero(&osd->o_ref)) {
> + dout("get_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref)-1,
> + refcount_read(&osd->o_ref));
> return osd;
> } else {
> dout("get_osd %p FAIL\n", osd);
> @@ -1062,9 +1062,9 @@ static struct ceph_osd *get_osd(struct ceph_osd *osd)
>
> static void put_osd(struct ceph_osd *osd)
> {
> - dout("put_osd %p %d -> %d\n", osd, atomic_read(&osd->o_ref),
> - atomic_read(&osd->o_ref) - 1);
> - if (atomic_dec_and_test(&osd->o_ref)) {
> + dout("put_osd %p %d -> %d\n", osd, refcount_read(&osd->o_ref),
> + refcount_read(&osd->o_ref) - 1);
> + if (refcount_dec_and_test(&osd->o_ref)) {
> osd_cleanup(osd);
> kfree(osd);
> }
> @@ -4092,7 +4092,7 @@ void ceph_osdc_stop(struct ceph_osd_client *osdc)
> close_osd(osd);
> }
> up_write(&osdc->lock);
> - WARN_ON(atomic_read(&osdc->homeless_osd.o_ref) != 1);
> + WARN_ON(refcount_read(&osdc->homeless_osd.o_ref) != 1);
> osd_cleanup(&osdc->homeless_osd);
>
> WARN_ON(!list_empty(&osdc->osd_lru));

Applied.

Thanks,

Ilya

2017-03-24 13:50:11

by Ilya Dryomov

[permalink] [raw]
Subject: Re: [PATCH 06/23] net, ceph: convert ceph_pagelist.refcnt from atomic_t to refcount_t

On Fri, Mar 17, 2017 at 1:10 PM, Elena Reshetova
<[email protected]> wrote:
> 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 <[email protected]>
> Signed-off-by: Hans Liljestrand <[email protected]>
> Signed-off-by: Kees Cook <[email protected]>
> Signed-off-by: David Windsor <[email protected]>
> ---
> fs/ceph/mds_client.c | 2 +-
> include/linux/ceph/pagelist.h | 6 +++---
> net/ceph/pagelist.c | 2 +-
> 3 files changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
> index c681762..7b38e6c 100644
> --- a/fs/ceph/mds_client.c
> +++ b/fs/ceph/mds_client.c
> @@ -1991,7 +1991,7 @@ static struct ceph_msg *create_request_message(struct ceph_mds_client *mdsc,
>
> if (req->r_pagelist) {
> struct ceph_pagelist *pagelist = req->r_pagelist;
> - atomic_inc(&pagelist->refcnt);
> + refcount_inc(&pagelist->refcnt);
> ceph_msg_data_add_pagelist(msg, pagelist);
> msg->hdr.data_len = cpu_to_le32(pagelist->length);
> } else {
> diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h
> index 13d71fe..75a7db2 100644
> --- a/include/linux/ceph/pagelist.h
> +++ b/include/linux/ceph/pagelist.h
> @@ -2,7 +2,7 @@
> #define __FS_CEPH_PAGELIST_H
>
> #include <asm/byteorder.h>
> -#include <linux/atomic.h>
> +#include <linux/refcount.h>
> #include <linux/list.h>
> #include <linux/types.h>
>
> @@ -13,7 +13,7 @@ struct ceph_pagelist {
> size_t room;
> struct list_head free_list;
> size_t num_pages_free;
> - atomic_t refcnt;
> + refcount_t refcnt;
> };
>
> struct ceph_pagelist_cursor {
> @@ -30,7 +30,7 @@ static inline void ceph_pagelist_init(struct ceph_pagelist *pl)
> pl->room = 0;
> INIT_LIST_HEAD(&pl->free_list);
> pl->num_pages_free = 0;
> - atomic_set(&pl->refcnt, 1);
> + refcount_set(&pl->refcnt, 1);
> }
>
> extern void ceph_pagelist_release(struct ceph_pagelist *pl);
> diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
> index 6864007..ce09f73 100644
> --- a/net/ceph/pagelist.c
> +++ b/net/ceph/pagelist.c
> @@ -16,7 +16,7 @@ static void ceph_pagelist_unmap_tail(struct ceph_pagelist *pl)
>
> void ceph_pagelist_release(struct ceph_pagelist *pl)
> {
> - if (!atomic_dec_and_test(&pl->refcnt))
> + if (!refcount_dec_and_test(&pl->refcnt))
> return;
> ceph_pagelist_unmap_tail(pl);
> while (!list_empty(&pl->head)) {

Applied.

Thanks,

Ilya