net: convert sock.sk_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. This patch uses refcount_inc_not_zero() instead of atomic_inc_not_zero_hint() due to absense of a _hint() version of refcount API. If the hint() version must be used, we might need to revisit API. Signed-off-by: Elena Reshetova <elena.reshetova@intel.com> Signed-off-by: Hans Liljestrand <ishkamiel@gmail.com> Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: David Windsor <dwindsor@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

parent
14afee4b60
commit
41c6d650f6
@@ -19,6 +19,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/refcount.h>
|
||||
|
||||
#include <net/sock.h>
|
||||
|
||||
@@ -89,7 +90,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
|
||||
return NULL;
|
||||
req->rsk_listener = NULL;
|
||||
if (attach_listener) {
|
||||
if (unlikely(!atomic_inc_not_zero(&sk_listener->sk_refcnt))) {
|
||||
if (unlikely(!refcount_inc_not_zero(&sk_listener->sk_refcnt))) {
|
||||
kmem_cache_free(ops->slab, req);
|
||||
return NULL;
|
||||
}
|
||||
@@ -100,7 +101,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
|
||||
sk_node_init(&req_to_sk(req)->sk_node);
|
||||
sk_tx_queue_clear(req_to_sk(req));
|
||||
req->saved_syn = NULL;
|
||||
atomic_set(&req->rsk_refcnt, 0);
|
||||
refcount_set(&req->rsk_refcnt, 0);
|
||||
|
||||
return req;
|
||||
}
|
||||
@@ -108,7 +109,7 @@ reqsk_alloc(const struct request_sock_ops *ops, struct sock *sk_listener,
|
||||
static inline void reqsk_free(struct request_sock *req)
|
||||
{
|
||||
/* temporary debugging */
|
||||
WARN_ON_ONCE(atomic_read(&req->rsk_refcnt) != 0);
|
||||
WARN_ON_ONCE(refcount_read(&req->rsk_refcnt) != 0);
|
||||
|
||||
req->rsk_ops->destructor(req);
|
||||
if (req->rsk_listener)
|
||||
@@ -119,7 +120,7 @@ static inline void reqsk_free(struct request_sock *req)
|
||||
|
||||
static inline void reqsk_put(struct request_sock *req)
|
||||
{
|
||||
if (atomic_dec_and_test(&req->rsk_refcnt))
|
||||
if (refcount_dec_and_test(&req->rsk_refcnt))
|
||||
reqsk_free(req);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user