Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dcc13ee8 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'net-subsystem-misc-refcounter-conversions'



Elena Reshetova says:

====================
v2 net subsystem misc refcounter conversions

Changes in v2:
 * rebase on top of net-next
 * currently by default refcount_t = atomic_t (*) and uses all
   atomic standard operations unless CONFIG_REFCOUNT_FULL is enabled.
   This is a compromise for the systems that are critical on
   performance (such as net) and cannot accept even slight delay
   on the refcounter operations.

This series, for various misc network 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.
These are the last networking-related conversions with the exception of
network drivers (to be send separately).

Please excuse the long patch set, but seems like breaking it up
won't save that much on CC list and most of the changes are
trivial.

The patches are fully independent and can be cherry-picked separately.
In order to try with refcount functionality enabled in run-time,
CONFIG_REFCOUNT_FULL must be enabled.

NOTE: automatic kernel builder for some reason doesn't like all my
network branches and regularly times out the builds on these branches.
Suggestion for "waiting a day for a good coverage" doesn't work, as
we have seen with generic network conversions. So please wait for the
full report from kernel test rebot before merging further up.
This has been compile-tested in 116 configs, but 71 timed out (including
all s390-related configs again). I am trying to see if they can fix
build coverage for me in meanwhile.

* The respective change is currently merged into -next as
  "locking/refcount: Create unchecked atomic_t implementation".
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents bf72acef b6d52ede
Loading
Loading
Loading
Loading
+5 −5
Original line number Diff line number Diff line
@@ -1034,11 +1034,11 @@ static bool vxlan_group_used(struct vxlan_net *vn, struct vxlan_dev *dev)
	/* The vxlan_sock is only used by dev, leaving group has
	 * no effect on other vxlan devices.
	 */
	if (family == AF_INET && sock4 && atomic_read(&sock4->refcnt) == 1)
	if (family == AF_INET && sock4 && refcount_read(&sock4->refcnt) == 1)
		return false;
#if IS_ENABLED(CONFIG_IPV6)
	sock6 = rtnl_dereference(dev->vn6_sock);
	if (family == AF_INET6 && sock6 && atomic_read(&sock6->refcnt) == 1)
	if (family == AF_INET6 && sock6 && refcount_read(&sock6->refcnt) == 1)
		return false;
#endif

@@ -1075,7 +1075,7 @@ static bool __vxlan_sock_release_prep(struct vxlan_sock *vs)

	if (!vs)
		return false;
	if (!atomic_dec_and_test(&vs->refcnt))
	if (!refcount_dec_and_test(&vs->refcnt))
		return false;

	vn = net_generic(sock_net(vs->sock->sk), vxlan_net_id);
@@ -2825,7 +2825,7 @@ static struct vxlan_sock *vxlan_socket_create(struct net *net, bool ipv6,
	}

	vs->sock = sock;
	atomic_set(&vs->refcnt, 1);
	refcount_set(&vs->refcnt, 1);
	vs->flags = (flags & VXLAN_F_RCV_FLAGS);

	spin_lock(&vn->sock_lock);
@@ -2860,7 +2860,7 @@ static int __vxlan_sock_add(struct vxlan_dev *vxlan, bool ipv6)
		spin_lock(&vn->sock_lock);
		vs = vxlan_find_sock(vxlan->net, ipv6 ? AF_INET6 : AF_INET,
				     vxlan->cfg.dst_port, vxlan->cfg.flags);
		if (vs && !atomic_add_unless(&vs->refcnt, 1, 0)) {
		if (vs && !refcount_inc_not_zero(&vs->refcnt)) {
			spin_unlock(&vn->sock_lock);
			return -EBUSY;
		}
+4 −3
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/uio.h>
#include <net/sock.h>
#include <linux/atomic.h>
#include <linux/refcount.h>
#include <uapi/linux/atmdev.h>

#ifdef CONFIG_PROC_FS
@@ -158,7 +159,7 @@ struct atm_dev {
	struct k_atm_dev_stats stats;	/* statistics */
	char		signal;		/* signal status (ATM_PHY_SIG_*) */
	int		link_rate;	/* link rate (default: OC3) */
	atomic_t	refcnt;		/* reference count */
	refcount_t	refcnt;		/* reference count */
	spinlock_t	lock;		/* protect internal members */
#ifdef CONFIG_PROC_FS
	struct proc_dir_entry *proc_entry; /* proc entry */
@@ -261,13 +262,13 @@ static inline int atm_may_send(struct atm_vcc *vcc,unsigned int size)

static inline void atm_dev_hold(struct atm_dev *dev)
{
	atomic_inc(&dev->refcnt);
	refcount_inc(&dev->refcnt);
}


static inline void atm_dev_put(struct atm_dev *dev)
{
	if (atomic_dec_and_test(&dev->refcnt)) {
	if (refcount_dec_and_test(&dev->refcnt)) {
		BUG_ON(!test_bit(ATM_DF_REMOVED, &dev->flags));
		if (dev->ops->dev_close)
			dev->ops->dev_close(dev);
+2 −1
Original line number Diff line number Diff line
@@ -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;
+10 −10
Original line number Diff line number Diff line
@@ -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);
	}
}
@@ -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);
}

@@ -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);
	}
+2 −2
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@
#include <linux/skbuff.h>
#include <net/netlabel.h>
#include <net/request_sock.h>
#include <linux/atomic.h>
#include <linux/refcount.h>
#include <asm/unaligned.h>

/* known doi values */
@@ -57,7 +57,7 @@ struct calipso_doi {
	u32 doi;
	u32 type;

	atomic_t refcount;
	refcount_t refcount;
	struct list_head list;
	struct rcu_head rcu;
};
Loading