Skip to content

Commit

Permalink
Merge branch 'net-subsystem-misc-refcounter-conversions'
Browse files Browse the repository at this point in the history
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: David S. Miller <davem@davemloft.net>
  • Loading branch information
David S. Miller committed Jul 4, 2017
2 parents bf72ace + b6d52ed commit dcc13ee
Show file tree
Hide file tree
Showing 61 changed files with 223 additions and 209 deletions.
10 changes: 5 additions & 5 deletions drivers/net/vxlan.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}
Expand Down
7 changes: 4 additions & 3 deletions include/linux/atmdev.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion include/linux/sunrpc/auth_gss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down
20 changes: 10 additions & 10 deletions include/net/ax25.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -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;
Expand All @@ -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);
}
}
Expand All @@ -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;
Expand All @@ -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);
}

Expand Down Expand Up @@ -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 {
Expand All @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions include/net/calipso.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;
};
Expand Down
5 changes: 3 additions & 2 deletions include/net/dn_fib.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define _NET_DN_FIB_H

#include <linux/netlink.h>
#include <linux/refcount.h>

extern const struct nla_policy rtm_dn_policy[];

Expand All @@ -28,7 +29,7 @@ struct dn_fib_info {
struct dn_fib_info *fib_next;
struct dn_fib_info *fib_prev;
int fib_treeref;
atomic_t fib_clntref;
refcount_t fib_clntref;
int fib_dead;
unsigned int fib_flags;
int fib_protocol;
Expand Down Expand Up @@ -130,7 +131,7 @@ void dn_fib_free_info(struct dn_fib_info *fi);

static inline void dn_fib_info_put(struct dn_fib_info *fi)
{
if (atomic_dec_and_test(&fi->fib_clntref))
if (refcount_dec_and_test(&fi->fib_clntref))
dn_fib_free_info(fi);
}

Expand Down
13 changes: 7 additions & 6 deletions include/net/ipx.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/ipx.h>
#include <linux/list.h>
#include <linux/slab.h>
#include <linux/refcount.h>

struct ipx_address {
__be32 net;
Expand Down Expand Up @@ -54,7 +55,7 @@ struct ipx_interface {
/* IPX address */
__be32 if_netnum;
unsigned char if_node[IPX_NODE_LEN];
atomic_t refcnt;
refcount_t refcnt;

/* physical device info */
struct net_device *if_dev;
Expand All @@ -80,7 +81,7 @@ struct ipx_route {
unsigned char ir_routed;
unsigned char ir_router_node[IPX_NODE_LEN];
struct list_head node; /* node in ipx_routes list */
atomic_t refcnt;
refcount_t refcnt;
};

struct ipx_cb {
Expand Down Expand Up @@ -139,7 +140,7 @@ const char *ipx_device_name(struct ipx_interface *intrfc);

static __inline__ void ipxitf_hold(struct ipx_interface *intrfc)
{
atomic_inc(&intrfc->refcnt);
refcount_inc(&intrfc->refcnt);
}

void ipxitf_down(struct ipx_interface *intrfc);
Expand All @@ -157,18 +158,18 @@ int ipxrtr_ioctl(unsigned int cmd, void __user *arg);

static __inline__ void ipxitf_put(struct ipx_interface *intrfc)
{
if (atomic_dec_and_test(&intrfc->refcnt))
if (refcount_dec_and_test(&intrfc->refcnt))
ipxitf_down(intrfc);
}

static __inline__ void ipxrtr_hold(struct ipx_route *rt)
{
atomic_inc(&rt->refcnt);
refcount_inc(&rt->refcnt);
}

static __inline__ void ipxrtr_put(struct ipx_route *rt)
{
if (atomic_dec_and_test(&rt->refcnt))
if (refcount_dec_and_test(&rt->refcnt))
kfree(rt);
}
#endif /* _NET_INET_IPX_H_ */
3 changes: 2 additions & 1 deletion include/net/lapb.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef _LAPB_H
#define _LAPB_H
#include <linux/lapb.h>
#include <linux/refcount.h>

#define LAPB_HEADER_LEN 20 /* LAPB over Ethernet + a bit more */

Expand Down Expand Up @@ -101,7 +102,7 @@ struct lapb_cb {
struct lapb_frame frmr_data;
unsigned char frmr_type;

atomic_t refcnt;
refcount_t refcnt;
};

/* lapb_iface.c */
Expand Down
6 changes: 3 additions & 3 deletions include/net/llc.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ struct llc_sap {
unsigned char state;
unsigned char p_bit;
unsigned char f_bit;
atomic_t refcnt;
refcount_t refcnt;
int (*rcv_func)(struct sk_buff *skb,
struct net_device *dev,
struct packet_type *pt,
Expand Down Expand Up @@ -113,14 +113,14 @@ struct llc_sap *llc_sap_open(unsigned char lsap,
struct net_device *orig_dev));
static inline void llc_sap_hold(struct llc_sap *sap)
{
atomic_inc(&sap->refcnt);
refcount_inc(&sap->refcnt);
}

void llc_sap_close(struct llc_sap *sap);

static inline void llc_sap_put(struct llc_sap *sap)
{
if (atomic_dec_and_test(&sap->refcnt))
if (refcount_dec_and_test(&sap->refcnt))
llc_sap_close(sap);
}

Expand Down
13 changes: 7 additions & 6 deletions include/net/netrom.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include <linux/list.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <linux/refcount.h>

#define NR_NETWORK_LEN 15
#define NR_TRANSPORT_LEN 5
Expand Down Expand Up @@ -93,7 +94,7 @@ struct nr_neigh {
unsigned short count;
unsigned int number;
unsigned char failed;
atomic_t refcount;
refcount_t refcount;
};

struct nr_route {
Expand All @@ -109,7 +110,7 @@ struct nr_node {
unsigned char which;
unsigned char count;
struct nr_route routes[3];
atomic_t refcount;
refcount_t refcount;
spinlock_t node_lock;
};

Expand All @@ -118,21 +119,21 @@ struct nr_node {
*********************************************************************/

#define nr_node_hold(__nr_node) \
atomic_inc(&((__nr_node)->refcount))
refcount_inc(&((__nr_node)->refcount))

static __inline__ void nr_node_put(struct nr_node *nr_node)
{
if (atomic_dec_and_test(&nr_node->refcount)) {
if (refcount_dec_and_test(&nr_node->refcount)) {
kfree(nr_node);
}
}

#define nr_neigh_hold(__nr_neigh) \
atomic_inc(&((__nr_neigh)->refcount))
refcount_inc(&((__nr_neigh)->refcount))

static __inline__ void nr_neigh_put(struct nr_neigh *nr_neigh)
{
if (atomic_dec_and_test(&nr_neigh->refcount)) {
if (refcount_dec_and_test(&nr_neigh->refcount)) {
if (nr_neigh->ax25)
ax25_cb_put(nr_neigh->ax25);
kfree(nr_neigh->digipeat);
Expand Down
3 changes: 2 additions & 1 deletion include/net/sch_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <linux/percpu.h>
#include <linux/dynamic_queue_limits.h>
#include <linux/list.h>
#include <linux/refcount.h>
#include <net/gen_stats.h>
#include <net/rtnetlink.h>

Expand Down Expand Up @@ -95,7 +96,7 @@ struct Qdisc {
struct sk_buff *skb_bad_txq;
struct rcu_head rcu_head;
int padded;
atomic_t refcnt;
refcount_t refcnt;

spinlock_t busylock ____cacheline_aligned_in_smp;
};
Expand Down
Loading

0 comments on commit dcc13ee

Please sign in to comment.