Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1678672 > unrolled thread
| Started by | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| First post | 2017-06-30 12:20 +0200 |
| Last post | 2017-07-10 09:20 +0200 |
| Articles | 9 — 4 participants |
Back to article view | Back to linux.kernel
[PATCH 00/17] v3 net generic subsystem refcount conversions Elena Reshetova <elena.reshetova@intel.com> - 2017-06-30 12:20 +0200
[PATCH 05/17] net: convert sk_buff.users from atomic_t to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-06-30 12:20 +0200
[PATCH 03/17] net: convert neigh_params.refcnt from atomic_t to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-06-30 12:20 +0200
[PATCH 16/17] net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t Elena Reshetova <elena.reshetova@intel.com> - 2017-06-30 12:20 +0200
Re: [PATCH 00/17] v3 net generic subsystem refcount conversions Eric Dumazet <eric.dumazet@gmail.com> - 2017-07-03 11:30 +0200
RE: [PATCH 00/17] v3 net generic subsystem refcount conversions "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-07-03 12:00 +0200
Re: [PATCH 00/17] v3 net generic subsystem refcount conversions Eric Dumazet <eric.dumazet@gmail.com> - 2017-07-03 12:40 +0200
Re: [PATCH 00/17] v3 net generic subsystem refcount conversions "Levin, Alexander (Sasha Levin)" <alexander.levin@verizon.com> - 2017-07-08 21:00 +0200
RE: [PATCH 00/17] v3 net generic subsystem refcount conversions "Reshetova, Elena" <elena.reshetova@intel.com> - 2017-07-10 09:20 +0200
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-30 12:20 +0200 |
| Subject | [PATCH 00/17] v3 net generic subsystem refcount conversions |
| Message-ID | <tY12a-497-11@gated-at.bofh.it> |
Changes in v3: Rebased on top of the net-next tree. Changes in v2: No changes in patches apart from rebases, but now 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 core 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. These patches contain only generic net pieces. Other changes will be sent separately. The patches are fully independent and can be cherry-picked separately. The big patches, such as conversions for sock structure, need a very detailed look from maintainers: refcount managing is quite complex in them and while it seems that they would benefit from the change, extra checking is needed. The biggest corner issue is the fact that refcount_inc() does not increment from zero. If there are no objections to the patches, please merge them via respective trees. * The respective change is currently merged into -next as "locking/refcount: Create unchecked atomic_t implementation". Elena Reshetova (17): net: convert inet_peer.refcnt from atomic_t to refcount_t net: convert neighbour.refcnt from atomic_t to refcount_t net: convert neigh_params.refcnt from atomic_t to refcount_t net: convert nf_bridge_info.use from atomic_t to refcount_t net: convert sk_buff.users from atomic_t to refcount_t net: convert sk_buff_fclones.fclone_ref from atomic_t to refcount_t net: convert sock.sk_wmem_alloc from atomic_t to refcount_t net: convert sock.sk_refcnt from atomic_t to refcount_t net: convert ip_mc_list.refcnt from atomic_t to refcount_t net: convert in_device.refcnt from atomic_t to refcount_t net: convert netpoll_info.refcnt from atomic_t to refcount_t net: convert unix_address.refcnt from atomic_t to refcount_t net: convert fib_rule.refcnt from atomic_t to refcount_t net: convert inet_frag_queue.refcnt from atomic_t to refcount_t net: convert net.passive from atomic_t to refcount_t net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t net: convert packet_fanout.sk_ref from atomic_t to refcount_t crypto/algif_aead.c | 2 +- drivers/atm/fore200e.c | 12 +----------- drivers/atm/he.c | 2 +- drivers/atm/idt77252.c | 4 ++-- drivers/infiniband/hw/nes/nes_cm.c | 4 ++-- drivers/isdn/mISDN/socket.c | 2 +- drivers/net/rionet.c | 2 +- drivers/s390/net/ctcm_main.c | 26 +++++++++++++------------- drivers/s390/net/netiucv.c | 10 +++++----- drivers/s390/net/qeth_core_main.c | 4 ++-- include/linux/atmdev.h | 2 +- include/linux/igmp.h | 3 ++- include/linux/inetdevice.h | 11 ++++++----- include/linux/netpoll.h | 3 ++- include/linux/skbuff.h | 20 ++++++++++---------- include/net/af_unix.h | 3 ++- include/net/arp.h | 2 +- include/net/fib_rules.h | 7 ++++--- include/net/inet_frag.h | 4 ++-- include/net/inet_hashtables.h | 4 ++-- include/net/inetpeer.h | 4 ++-- include/net/ndisc.h | 2 +- include/net/neighbour.h | 15 ++++++++------- include/net/net_namespace.h | 3 ++- include/net/netfilter/br_netfilter.h | 2 +- include/net/netlabel.h | 8 ++++---- include/net/request_sock.h | 9 +++++---- include/net/sock.h | 25 +++++++++++++------------ net/atm/br2684.c | 2 +- net/atm/clip.c | 8 ++++---- net/atm/common.c | 10 +++++----- net/atm/lec.c | 4 ++-- net/atm/mpc.c | 4 ++-- net/atm/pppoatm.c | 2 +- net/atm/proc.c | 2 +- net/atm/raw.c | 2 +- net/atm/signaling.c | 2 +- net/bluetooth/af_bluetooth.c | 2 +- net/bluetooth/rfcomm/sock.c | 2 +- net/bridge/br_netfilter_hooks.c | 4 ++-- net/caif/caif_socket.c | 2 +- net/core/datagram.c | 6 +++--- net/core/dev.c | 10 +++++----- net/core/fib_rules.c | 4 ++-- net/core/neighbour.c | 22 +++++++++++----------- net/core/net-sysfs.c | 2 +- net/core/net_namespace.c | 4 ++-- net/core/netpoll.c | 10 +++++----- net/core/pktgen.c | 16 ++++++++-------- net/core/rtnetlink.c | 2 +- net/core/skbuff.c | 26 +++++++++++++------------- net/core/sock.c | 32 ++++++++++++++++---------------- net/dccp/ipv6.c | 2 +- net/decnet/dn_neigh.c | 2 +- net/ipv4/af_inet.c | 2 +- net/ipv4/cipso_ipv4.c | 4 ++-- net/ipv4/devinet.c | 2 +- net/ipv4/esp4.c | 2 +- net/ipv4/igmp.c | 10 +++++----- net/ipv4/inet_connection_sock.c | 2 +- net/ipv4/inet_fragment.c | 14 +++++++------- net/ipv4/inet_hashtables.c | 4 ++-- net/ipv4/inet_timewait_sock.c | 8 ++++---- net/ipv4/inetpeer.c | 18 +++++++++--------- net/ipv4/ip_fragment.c | 2 +- net/ipv4/ip_output.c | 6 +++--- net/ipv4/ping.c | 4 ++-- net/ipv4/raw.c | 2 +- net/ipv4/syncookies.c | 2 +- net/ipv4/tcp.c | 4 ++-- net/ipv4/tcp_fastopen.c | 2 +- net/ipv4/tcp_ipv4.c | 4 ++-- net/ipv4/tcp_offload.c | 2 +- net/ipv4/tcp_output.c | 15 +++++++-------- net/ipv4/udp.c | 6 +++--- net/ipv4/udp_diag.c | 4 ++-- net/ipv6/calipso.c | 4 ++-- net/ipv6/datagram.c | 2 +- net/ipv6/esp6.c | 2 +- net/ipv6/inet6_hashtables.c | 4 ++-- net/ipv6/ip6_output.c | 4 ++-- net/ipv6/syncookies.c | 2 +- net/ipv6/tcp_ipv6.c | 6 +++--- net/ipv6/udp.c | 4 ++-- net/kcm/kcmproc.c | 2 +- net/key/af_key.c | 8 ++++---- net/l2tp/l2tp_debugfs.c | 3 +-- net/llc/llc_conn.c | 8 ++++---- net/llc/llc_sap.c | 2 +- net/netfilter/xt_TPROXY.c | 4 ++-- net/netlink/af_netlink.c | 14 +++++++------- net/packet/af_packet.c | 14 +++++++------- net/packet/internal.h | 4 +++- net/phonet/socket.c | 4 ++-- net/rds/tcp_send.c | 2 +- net/rxrpc/af_rxrpc.c | 6 +++--- net/rxrpc/skbuff.c | 12 ++++++------ net/sched/em_meta.c | 2 +- net/sched/sch_atm.c | 2 +- net/sctp/output.c | 2 +- net/sctp/outqueue.c | 2 +- net/sctp/proc.c | 2 +- net/sctp/socket.c | 6 +++--- net/tipc/socket.c | 2 +- net/unix/af_unix.c | 16 ++++++++-------- 105 files changed, 321 insertions(+), 322 deletions(-) -- 2.7.4
[toc] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-30 12:20 +0200 |
| Subject | [PATCH 05/17] net: convert sk_buff.users from atomic_t to refcount_t |
| Message-ID | <tY1bR-4cr-37@gated-at.bofh.it> |
| In reply to | #1678672 |
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: Elena Reshetova <elena.reshetova@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>
---
drivers/infiniband/hw/nes/nes_cm.c | 4 ++--
drivers/isdn/mISDN/socket.c | 2 +-
drivers/net/rionet.c | 2 +-
drivers/s390/net/ctcm_main.c | 26 +++++++++++++-------------
drivers/s390/net/netiucv.c | 10 +++++-----
drivers/s390/net/qeth_core_main.c | 4 ++--
include/linux/skbuff.h | 10 +++++-----
net/core/datagram.c | 4 ++--
net/core/dev.c | 10 +++++-----
net/core/netpoll.c | 4 ++--
net/core/pktgen.c | 16 ++++++++--------
net/core/rtnetlink.c | 2 +-
net/core/skbuff.c | 8 ++++----
net/dccp/ipv6.c | 2 +-
net/ipv6/syncookies.c | 2 +-
net/ipv6/tcp_ipv6.c | 2 +-
net/key/af_key.c | 4 ++--
net/netlink/af_netlink.c | 6 +++---
net/rxrpc/skbuff.c | 12 ++++++------
net/sctp/outqueue.c | 2 +-
net/sctp/socket.c | 2 +-
21 files changed, 67 insertions(+), 67 deletions(-)
diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c
index 30b256a..de4025d 100644
--- a/drivers/infiniband/hw/nes/nes_cm.c
+++ b/drivers/infiniband/hw/nes/nes_cm.c
@@ -742,7 +742,7 @@ int schedule_nes_timer(struct nes_cm_node *cm_node, struct sk_buff *skb,
if (type == NES_TIMER_TYPE_SEND) {
new_send->seq_num = ntohl(tcp_hdr(skb)->seq);
- atomic_inc(&new_send->skb->users);
+ refcount_inc(&new_send->skb->users);
spin_lock_irqsave(&cm_node->retrans_list_lock, flags);
cm_node->send_entry = new_send;
add_ref_cm_node(cm_node);
@@ -924,7 +924,7 @@ static void nes_cm_timer_tick(unsigned long pass)
flags);
break;
}
- atomic_inc(&send_entry->skb->users);
+ refcount_inc(&send_entry->skb->users);
cm_packets_retrans++;
nes_debug(NES_DBG_CM, "Retransmitting send_entry %p "
"for node %p, jiffies = %lu, time to send = "
diff --git a/drivers/isdn/mISDN/socket.c b/drivers/isdn/mISDN/socket.c
index 99e5f97..c5603d1 100644
--- a/drivers/isdn/mISDN/socket.c
+++ b/drivers/isdn/mISDN/socket.c
@@ -155,7 +155,7 @@ mISDN_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
copied = skb->len + MISDN_HEADER_LEN;
if (len < copied) {
if (flags & MSG_PEEK)
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
else
skb_queue_head(&sk->sk_receive_queue, skb);
return -ENOSPC;
diff --git a/drivers/net/rionet.c b/drivers/net/rionet.c
index 300bb14..e9f101c 100644
--- a/drivers/net/rionet.c
+++ b/drivers/net/rionet.c
@@ -201,7 +201,7 @@ static int rionet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
rionet_queue_tx_msg(skb, ndev,
nets[rnet->mport->id].active[i]);
if (count)
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
count++;
}
} else if (RIONET_MAC_MATCH(eth->h_dest)) {
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 9912135..e8782a8 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -483,7 +483,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
spin_unlock_irqrestore(&ch->collect_lock, saveflags);
return -EBUSY;
} else {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
header.length = l;
header.type = be16_to_cpu(skb->protocol);
header.unused = 0;
@@ -500,7 +500,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
* Protect skb against beeing free'd by upper
* layers.
*/
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
ch->prof.txlen += skb->len;
header.length = skb->len + LL_HEADER_LENGTH;
header.type = be16_to_cpu(skb->protocol);
@@ -517,14 +517,14 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
if (hi) {
nskb = alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA);
if (!nskb) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
ctcm_clear_busy(ch->netdev);
return -ENOMEM;
} else {
skb_put_data(nskb, skb->data, skb->len);
- atomic_inc(&nskb->users);
- atomic_dec(&skb->users);
+ refcount_inc(&nskb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
skb = nskb;
}
@@ -542,7 +542,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
* Remove our header. It gets added
* again on retransmit.
*/
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
skb_pull(skb, LL_HEADER_LENGTH + 2);
ctcm_clear_busy(ch->netdev);
return -ENOMEM;
@@ -553,7 +553,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->ccw[1].count = skb->len;
skb_copy_from_linear_data(skb,
skb_put(ch->trans_skb, skb->len), skb->len);
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
ccw_idx = 0;
} else {
@@ -679,7 +679,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
if ((fsm_getstate(ch->fsm) != CTC_STATE_TXIDLE) || grp->in_sweep) {
spin_lock_irqsave(&ch->collect_lock, saveflags);
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
p_header = kmalloc(PDU_HEADER_LENGTH, gfp_type());
if (!p_header) {
@@ -716,7 +716,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
* Protect skb against beeing free'd by upper
* layers.
*/
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
/*
* IDAL support in CTCM is broken, so we have to
@@ -729,8 +729,8 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
goto nomem_exit;
} else {
skb_put_data(nskb, skb->data, skb->len);
- atomic_inc(&nskb->users);
- atomic_dec(&skb->users);
+ refcount_inc(&nskb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
skb = nskb;
}
@@ -810,7 +810,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
ch->trans_skb->len = 0;
ch->ccw[1].count = skb->len;
skb_put_data(ch->trans_skb, skb->data, skb->len);
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_irq(skb);
ccw_idx = 0;
CTCM_PR_DBGDATA("%s(%s): trans_skb len: %04x\n"
@@ -855,7 +855,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb)
"%s(%s): MEMORY allocation ERROR\n",
CTCM_FUNTAIL, ch->id);
rc = -ENOMEM;
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
fsm_event(priv->mpcg->fsm, MPCG_EVENT_INOP, dev);
done:
diff --git a/drivers/s390/net/netiucv.c b/drivers/s390/net/netiucv.c
index 7db427c..1579695 100644
--- a/drivers/s390/net/netiucv.c
+++ b/drivers/s390/net/netiucv.c
@@ -743,7 +743,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
conn->prof.tx_pending--;
if (single_flag) {
if ((skb = skb_dequeue(&conn->commit_queue))) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
if (privptr) {
privptr->stats.tx_packets++;
privptr->stats.tx_bytes +=
@@ -766,7 +766,7 @@ static void conn_action_txdone(fsm_instance *fi, int event, void *arg)
txbytes += skb->len;
txpackets++;
stat_maxcq++;
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
}
if (conn->collect_len > conn->prof.maxmulti)
@@ -958,7 +958,7 @@ static void netiucv_purge_skb_queue(struct sk_buff_head *q)
struct sk_buff *skb;
while ((skb = skb_dequeue(q))) {
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
}
}
@@ -1176,7 +1176,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
IUCV_DBF_TEXT(data, 2,
"EBUSY from netiucv_transmit_skb\n");
} else {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
skb_queue_tail(&conn->collect_queue, skb);
conn->collect_len += l;
rc = 0;
@@ -1245,7 +1245,7 @@ static int netiucv_transmit_skb(struct iucv_connection *conn,
} else {
if (copied)
dev_kfree_skb(skb);
- atomic_inc(&nskb->users);
+ refcount_inc(&nskb->users);
skb_queue_tail(&conn->commit_queue, nskb);
}
}
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c
index 3b657d5..aec06e1 100644
--- a/drivers/s390/net/qeth_core_main.c
+++ b/drivers/s390/net/qeth_core_main.c
@@ -1242,7 +1242,7 @@ static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf)
iucv->sk_txnotify(skb, TX_NOTIFY_GENERALERROR);
}
}
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
dev_kfree_skb_any(skb);
skb = skb_dequeue(&buf->skb_list);
}
@@ -3975,7 +3975,7 @@ static inline int qeth_fill_buffer(struct qeth_qdio_out_q *queue,
int flush_cnt = 0, hdr_len, large_send = 0;
buffer = buf->buffer;
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
skb_queue_tail(&buf->skb_list, skb);
/*check first on TSO ....*/
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 005793e..90cbd86 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -761,7 +761,7 @@ struct sk_buff {
unsigned char *head,
*data;
unsigned int truesize;
- atomic_t users;
+ refcount_t users;
};
#ifdef __KERNEL__
@@ -872,9 +872,9 @@ static inline bool skb_unref(struct sk_buff *skb)
{
if (unlikely(!skb))
return false;
- if (likely(atomic_read(&skb->users) == 1))
+ if (likely(refcount_read(&skb->users) == 1))
smp_rmb();
- else if (likely(!atomic_dec_and_test(&skb->users)))
+ else if (likely(!refcount_dec_and_test(&skb->users)))
return false;
return true;
@@ -1283,7 +1283,7 @@ static inline struct sk_buff *skb_queue_prev(const struct sk_buff_head *list,
*/
static inline struct sk_buff *skb_get(struct sk_buff *skb)
{
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
return skb;
}
@@ -1384,7 +1384,7 @@ static inline void __skb_header_release(struct sk_buff *skb)
*/
static inline int skb_shared(const struct sk_buff *skb)
{
- return atomic_read(&skb->users) != 1;
+ return refcount_read(&skb->users) != 1;
}
/**
diff --git a/net/core/datagram.c b/net/core/datagram.c
index e5311a7..95d4354 100644
--- a/net/core/datagram.c
+++ b/net/core/datagram.c
@@ -188,7 +188,7 @@ struct sk_buff *__skb_try_recv_from_queue(struct sock *sk,
}
}
*peeked = 1;
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
} else {
__skb_unlink(skb, queue);
if (destructor)
@@ -358,7 +358,7 @@ int __sk_queue_drop_skb(struct sock *sk, struct sk_buff_head *sk_queue,
spin_lock_bh(&sk_queue->lock);
if (skb == skb_peek(sk_queue)) {
__skb_unlink(skb, sk_queue);
- atomic_dec(&skb->users);
+ refcount_dec(&skb->users);
if (destructor)
destructor(sk, skb);
err = 0;
diff --git a/net/core/dev.c b/net/core/dev.c
index a91572a..fcc0b75 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1862,7 +1862,7 @@ static inline int deliver_skb(struct sk_buff *skb,
{
if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
return -ENOMEM;
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
return pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
}
@@ -2484,10 +2484,10 @@ void __dev_kfree_skb_irq(struct sk_buff *skb, enum skb_free_reason reason)
if (unlikely(!skb))
return;
- if (likely(atomic_read(&skb->users) == 1)) {
+ if (likely(refcount_read(&skb->users) == 1)) {
smp_rmb();
- atomic_set(&skb->users, 0);
- } else if (likely(!atomic_dec_and_test(&skb->users))) {
+ refcount_set(&skb->users, 0);
+ } else if (likely(!refcount_dec_and_test(&skb->users))) {
return;
}
get_kfree_skb_cb(skb)->reason = reason;
@@ -3955,7 +3955,7 @@ static __latent_entropy void net_tx_action(struct softirq_action *h)
clist = clist->next;
- WARN_ON(atomic_read(&skb->users));
+ WARN_ON(refcount_read(&skb->users));
if (likely(get_kfree_skb_cb(skb)->reason == SKB_REASON_CONSUMED))
trace_consume_skb(skb);
else
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 37c1e34..a835155 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -277,7 +277,7 @@ static void zap_completion_queue(void)
struct sk_buff *skb = clist;
clist = clist->next;
if (!skb_irq_freeable(skb)) {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
dev_kfree_skb_any(skb); /* put this one back */
} else {
__kfree_skb(skb);
@@ -309,7 +309,7 @@ static struct sk_buff *find_skb(struct netpoll *np, int len, int reserve)
return NULL;
}
- atomic_set(&skb->users, 1);
+ refcount_set(&skb->users, 1);
skb_reserve(skb, reserve);
return skb;
}
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 2dd42c5..6e1e10f 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3363,7 +3363,7 @@ static void pktgen_wait_for_skb(struct pktgen_dev *pkt_dev)
{
ktime_t idle_start = ktime_get();
- while (atomic_read(&(pkt_dev->skb->users)) != 1) {
+ while (refcount_read(&(pkt_dev->skb->users)) != 1) {
if (signal_pending(current))
break;
@@ -3420,7 +3420,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
if (pkt_dev->xmit_mode == M_NETIF_RECEIVE) {
skb = pkt_dev->skb;
skb->protocol = eth_type_trans(skb, skb->dev);
- atomic_add(burst, &skb->users);
+ refcount_add(burst, &skb->users);
local_bh_disable();
do {
ret = netif_receive_skb(skb);
@@ -3428,11 +3428,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->errors++;
pkt_dev->sofar++;
pkt_dev->seq_num++;
- if (atomic_read(&skb->users) != burst) {
+ if (refcount_read(&skb->users) != burst) {
/* skb was queued by rps/rfs or taps,
* so cannot reuse this skb
*/
- atomic_sub(burst - 1, &skb->users);
+ WARN_ON(refcount_sub_and_test(burst - 1, &skb->users));
/* get out of the loop and wait
* until skb is consumed
*/
@@ -3446,7 +3446,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
goto out; /* Skips xmit_mode M_START_XMIT */
} else if (pkt_dev->xmit_mode == M_QUEUE_XMIT) {
local_bh_disable();
- atomic_inc(&pkt_dev->skb->users);
+ refcount_inc(&pkt_dev->skb->users);
ret = dev_queue_xmit(pkt_dev->skb);
switch (ret) {
@@ -3487,7 +3487,7 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
pkt_dev->last_ok = 0;
goto unlock;
}
- atomic_add(burst, &pkt_dev->skb->users);
+ refcount_add(burst, &pkt_dev->skb->users);
xmit_more:
ret = netdev_start_xmit(pkt_dev->skb, odev, txq, --burst > 0);
@@ -3513,11 +3513,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev)
/* fallthru */
case NETDEV_TX_BUSY:
/* Retry it next time */
- atomic_dec(&(pkt_dev->skb->users));
+ refcount_dec(&(pkt_dev->skb->users));
pkt_dev->last_ok = 0;
}
if (unlikely(burst))
- atomic_sub(burst, &pkt_dev->skb->users);
+ WARN_ON(refcount_sub_and_test(burst, &pkt_dev->skb->users));
unlock:
HARD_TX_UNLOCK(odev, txq);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index ed51de5..d1ba909 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -649,7 +649,7 @@ int rtnetlink_send(struct sk_buff *skb, struct net *net, u32 pid, unsigned int g
NETLINK_CB(skb).dst_group = group;
if (echo)
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
netlink_broadcast(rtnl, skb, pid, group, GFP_KERNEL);
if (echo)
err = netlink_unicast(rtnl, skb, pid, MSG_DONTWAIT);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index f75897a..45dc662 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -176,7 +176,7 @@ struct sk_buff *__alloc_skb_head(gfp_t gfp_mask, int node)
memset(skb, 0, offsetof(struct sk_buff, tail));
skb->head = NULL;
skb->truesize = sizeof(struct sk_buff);
- atomic_set(&skb->users, 1);
+ refcount_set(&skb->users, 1);
skb->mac_header = (typeof(skb->mac_header))~0U;
out:
@@ -247,7 +247,7 @@ struct sk_buff *__alloc_skb(unsigned int size, gfp_t gfp_mask,
/* Account for allocated memory : skb + skb->head */
skb->truesize = SKB_TRUESIZE(size);
skb->pfmemalloc = pfmemalloc;
- atomic_set(&skb->users, 1);
+ refcount_set(&skb->users, 1);
skb->head = data;
skb->data = data;
skb_reset_tail_pointer(skb);
@@ -314,7 +314,7 @@ struct sk_buff *__build_skb(void *data, unsigned int frag_size)
memset(skb, 0, offsetof(struct sk_buff, tail));
skb->truesize = SKB_TRUESIZE(size);
- atomic_set(&skb->users, 1);
+ refcount_set(&skb->users, 1);
skb->head = data;
skb->data = data;
skb_reset_tail_pointer(skb);
@@ -915,7 +915,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
C(head_frag);
C(data);
C(truesize);
- atomic_set(&n->users, 1);
+ refcount_set(&n->users, 1);
atomic_inc(&(skb_shinfo(skb)->dataref));
skb->cloned = 1;
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c
index 4fccc0c..c376af5 100644
--- a/net/dccp/ipv6.c
+++ b/net/dccp/ipv6.c
@@ -353,7 +353,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb)
if (ipv6_opt_accepted(sk, skb, IP6CB(skb)) ||
np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
ireq->pktopts = skb;
}
ireq->ir_iif = sk->sk_bound_dev_if;
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c
index 2f7e99a..7b75b06 100644
--- a/net/ipv6/syncookies.c
+++ b/net/ipv6/syncookies.c
@@ -194,7 +194,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb)
if (ipv6_opt_accepted(sk, skb, &TCP_SKB_CB(skb)->header.h6) ||
np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo ||
np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
ireq->pktopts = skb;
}
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c
index f85cbfc..f1a4881 100644
--- a/net/ipv6/tcp_ipv6.c
+++ b/net/ipv6/tcp_ipv6.c
@@ -734,7 +734,7 @@ static void tcp_v6_init_req(struct request_sock *req,
np->rxopt.bits.rxinfo ||
np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim ||
np->rxopt.bits.rxohlim || np->repflow)) {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
ireq->pktopts = skb;
}
}
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ce9b856..0fe7ff3 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -203,11 +203,11 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
sock_hold(sk);
if (*skb2 == NULL) {
- if (atomic_read(&skb->users) != 1) {
+ if (refcount_read(&skb->users) != 1) {
*skb2 = skb_clone(skb, allocation);
} else {
*skb2 = skb;
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
}
}
if (*skb2 != NULL) {
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index a88745e..05030ad 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1848,7 +1848,7 @@ static int netlink_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
}
if (dst_group) {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
netlink_broadcast(sk, skb, dst_portid, dst_group, GFP_KERNEL);
}
err = netlink_unicast(sk, skb, dst_portid, msg->msg_flags&MSG_DONTWAIT);
@@ -2226,7 +2226,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
struct netlink_sock *nlk;
int ret;
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
sk = netlink_lookup(sock_net(ssk), ssk->sk_protocol, NETLINK_CB(skb).portid);
if (sk == NULL) {
@@ -2431,7 +2431,7 @@ int nlmsg_notify(struct sock *sk, struct sk_buff *skb, u32 portid,
int exclude_portid = 0;
if (report) {
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
exclude_portid = portid;
}
diff --git a/net/rxrpc/skbuff.c b/net/rxrpc/skbuff.c
index 67b02c4..b8985d0 100644
--- a/net/rxrpc/skbuff.c
+++ b/net/rxrpc/skbuff.c
@@ -27,7 +27,7 @@ void rxrpc_new_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
{
const void *here = __builtin_return_address(0);
int n = atomic_inc_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
}
/*
@@ -38,7 +38,7 @@ void rxrpc_see_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
const void *here = __builtin_return_address(0);
if (skb) {
int n = atomic_read(select_skb_count(op));
- trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
}
}
@@ -49,7 +49,7 @@ void rxrpc_get_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
{
const void *here = __builtin_return_address(0);
int n = atomic_inc_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
skb_get(skb);
}
@@ -63,7 +63,7 @@ void rxrpc_free_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
int n;
CHECK_SLAB_OKAY(&skb->users);
n = atomic_dec_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
kfree_skb(skb);
}
}
@@ -78,7 +78,7 @@ void rxrpc_lose_skb(struct sk_buff *skb, enum rxrpc_skb_trace op)
int n;
CHECK_SLAB_OKAY(&skb->users);
n = atomic_dec_return(select_skb_count(op));
- trace_rxrpc_skb(skb, op, atomic_read(&skb->users), n, here);
+ trace_rxrpc_skb(skb, op, refcount_read(&skb->users), n, here);
kfree_skb(skb);
}
}
@@ -93,7 +93,7 @@ void rxrpc_purge_queue(struct sk_buff_head *list)
while ((skb = skb_dequeue((list))) != NULL) {
int n = atomic_dec_return(select_skb_count(rxrpc_skb_rx_purged));
trace_rxrpc_skb(skb, rxrpc_skb_rx_purged,
- atomic_read(&skb->users), n, here);
+ refcount_read(&skb->users), n, here);
kfree_skb(skb);
}
}
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 20299df..e876270 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -1102,7 +1102,7 @@ static void sctp_outq_flush(struct sctp_outq *q, int rtx_timeout, gfp_t gfp)
sctp_cname(SCTP_ST_CHUNK(chunk->chunk_hdr->type)) :
"illegal chunk", ntohl(chunk->subh.data_hdr->tsn),
chunk->skb ? chunk->skb->head : NULL, chunk->skb ?
- atomic_read(&chunk->skb->users) : -1);
+ refcount_read(&chunk->skb->users) : -1);
/* Add the chunk to the packet. */
status = sctp_packet_transmit_chunk(packet, chunk, 0, gfp);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index 7b6e20e..b497ee8 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -7563,7 +7563,7 @@ struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags,
if (flags & MSG_PEEK) {
skb = skb_peek(&sk->sk_receive_queue);
if (skb)
- atomic_inc(&skb->users);
+ refcount_inc(&skb->users);
} else {
skb = __skb_dequeue(&sk->sk_receive_queue);
}
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-30 12:20 +0200 |
| Subject | [PATCH 03/17] net: convert neigh_params.refcnt from atomic_t to refcount_t |
| Message-ID | <tY1bR-4cr-41@gated-at.bofh.it> |
| In reply to | #1678672 |
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: Elena Reshetova <elena.reshetova@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>
---
include/net/neighbour.h | 6 +++---
net/core/neighbour.c | 8 ++++----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index e5ee739..afc39e3 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -77,7 +77,7 @@ struct neigh_parms {
void *sysctl_table;
int dead;
- atomic_t refcnt;
+ refcount_t refcnt;
struct rcu_head rcu_head;
int reachable_time;
@@ -396,12 +396,12 @@ void neigh_sysctl_unregister(struct neigh_parms *p);
static inline void __neigh_parms_put(struct neigh_parms *parms)
{
- atomic_dec(&parms->refcnt);
+ refcount_dec(&parms->refcnt);
}
static inline struct neigh_parms *neigh_parms_clone(struct neigh_parms *parms)
{
- atomic_inc(&parms->refcnt);
+ refcount_inc(&parms->refcnt);
return parms;
}
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 0c78c8e..e31fc11 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -709,7 +709,7 @@ static void neigh_parms_destroy(struct neigh_parms *parms);
static inline void neigh_parms_put(struct neigh_parms *parms)
{
- if (atomic_dec_and_test(&parms->refcnt))
+ if (refcount_dec_and_test(&parms->refcnt))
neigh_parms_destroy(parms);
}
@@ -1479,7 +1479,7 @@ struct neigh_parms *neigh_parms_alloc(struct net_device *dev,
p = kmemdup(&tbl->parms, sizeof(*p), GFP_KERNEL);
if (p) {
p->tbl = tbl;
- atomic_set(&p->refcnt, 1);
+ refcount_set(&p->refcnt, 1);
p->reachable_time =
neigh_rand_reach_time(NEIGH_VAR(p, BASE_REACHABLE_TIME));
dev_hold(dev);
@@ -1542,7 +1542,7 @@ void neigh_table_init(int index, struct neigh_table *tbl)
INIT_LIST_HEAD(&tbl->parms_list);
list_add(&tbl->parms.list, &tbl->parms_list);
write_pnet(&tbl->parms.net, &init_net);
- atomic_set(&tbl->parms.refcnt, 1);
+ refcount_set(&tbl->parms.refcnt, 1);
tbl->parms.reachable_time =
neigh_rand_reach_time(NEIGH_VAR(&tbl->parms, BASE_REACHABLE_TIME));
@@ -1796,7 +1796,7 @@ static int neightbl_fill_parms(struct sk_buff *skb, struct neigh_parms *parms)
if ((parms->dev &&
nla_put_u32(skb, NDTPA_IFINDEX, parms->dev->ifindex)) ||
- nla_put_u32(skb, NDTPA_REFCNT, atomic_read(&parms->refcnt)) ||
+ nla_put_u32(skb, NDTPA_REFCNT, refcount_read(&parms->refcnt)) ||
nla_put_u32(skb, NDTPA_QUEUE_LENBYTES,
NEIGH_VAR(parms, QUEUE_LEN_BYTES)) ||
/* approximative value for deprecated QUEUE_LEN (in packets) */
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Elena Reshetova <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-06-30 12:20 +0200 |
| Subject | [PATCH 16/17] net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t |
| Message-ID | <tY1bQ-4cr-25@gated-at.bofh.it> |
| In reply to | #1678672 |
refcount_t type and corresponding API should be
used instead of atomic_t when the variable is used as
a reference counter. This allows to avoid accidental
refcounter overflows that might lead to use-after-free
situations.
Signed-off-by: Elena Reshetova <elena.reshetova@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>
---
include/net/netlabel.h | 8 ++++----
net/ipv4/cipso_ipv4.c | 4 ++--
net/ipv6/calipso.c | 4 ++--
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/include/net/netlabel.h b/include/net/netlabel.h
index efe9806..72d6435 100644
--- a/include/net/netlabel.h
+++ b/include/net/netlabel.h
@@ -37,7 +37,7 @@
#include <linux/in6.h>
#include <net/netlink.h>
#include <net/request_sock.h>
-#include <linux/atomic.h>
+#include <linux/refcount.h>
struct cipso_v4_doi;
struct calipso_doi;
@@ -136,7 +136,7 @@ struct netlbl_audit {
*
*/
struct netlbl_lsm_cache {
- atomic_t refcount;
+ refcount_t refcount;
void (*free) (const void *data);
void *data;
};
@@ -295,7 +295,7 @@ static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
cache = kzalloc(sizeof(*cache), flags);
if (cache)
- atomic_set(&cache->refcount, 1);
+ refcount_set(&cache->refcount, 1);
return cache;
}
@@ -309,7 +309,7 @@ static inline struct netlbl_lsm_cache *netlbl_secattr_cache_alloc(gfp_t flags)
*/
static inline void netlbl_secattr_cache_free(struct netlbl_lsm_cache *cache)
{
- if (!atomic_dec_and_test(&cache->refcount))
+ if (!refcount_dec_and_test(&cache->refcount))
return;
if (cache->free)
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c
index ae20616..c204477 100644
--- a/net/ipv4/cipso_ipv4.c
+++ b/net/ipv4/cipso_ipv4.c
@@ -265,7 +265,7 @@ static int cipso_v4_cache_check(const unsigned char *key,
entry->key_len == key_len &&
memcmp(entry->key, key, key_len) == 0) {
entry->activity += 1;
- atomic_inc(&entry->lsm_data->refcount);
+ refcount_inc(&entry->lsm_data->refcount);
secattr->cache = entry->lsm_data;
secattr->flags |= NETLBL_SECATTR_CACHE;
secattr->type = NETLBL_NLTYPE_CIPSOV4;
@@ -332,7 +332,7 @@ int cipso_v4_cache_add(const unsigned char *cipso_ptr,
}
entry->key_len = cipso_ptr_len;
entry->hash = cipso_v4_map_cache_hash(cipso_ptr, cipso_ptr_len);
- atomic_inc(&secattr->cache->refcount);
+ refcount_inc(&secattr->cache->refcount);
entry->lsm_data = secattr->cache;
bkt = entry->hash & (CIPSO_V4_CACHE_BUCKETS - 1);
diff --git a/net/ipv6/calipso.c b/net/ipv6/calipso.c
index 8d772fe..4406752 100644
--- a/net/ipv6/calipso.c
+++ b/net/ipv6/calipso.c
@@ -227,7 +227,7 @@ static int calipso_cache_check(const unsigned char *key,
entry->key_len == key_len &&
memcmp(entry->key, key, key_len) == 0) {
entry->activity += 1;
- atomic_inc(&entry->lsm_data->refcount);
+ refcount_inc(&entry->lsm_data->refcount);
secattr->cache = entry->lsm_data;
secattr->flags |= NETLBL_SECATTR_CACHE;
secattr->type = NETLBL_NLTYPE_CALIPSO;
@@ -296,7 +296,7 @@ static int calipso_cache_add(const unsigned char *calipso_ptr,
}
entry->key_len = calipso_ptr_len;
entry->hash = calipso_map_cache_hash(calipso_ptr, calipso_ptr_len);
- atomic_inc(&secattr->cache->refcount);
+ refcount_inc(&secattr->cache->refcount);
entry->lsm_data = secattr->cache;
bkt = entry->hash & (CALIPSO_CACHE_BUCKETS - 1);
--
2.7.4
[toc] | [prev] | [next] | [standalone]
| From | Eric Dumazet <eric.dumazet@gmail.com> |
|---|---|
| Date | 2017-07-03 11:30 +0200 |
| Message-ID | <tZ5Q8-7za-37@gated-at.bofh.it> |
| In reply to | #1678672 |
On Fri, 2017-06-30 at 13:07 +0300, Elena Reshetova wrote: > Changes in v3: > Rebased on top of the net-next tree. > > Changes in v2: > No changes in patches apart from rebases, but now 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 core 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. > These patches contain only generic net pieces. Other changes will be sent separately. > > The patches are fully independent and can be cherry-picked separately. > The big patches, such as conversions for sock structure, need a very detailed > look from maintainers: refcount managing is quite complex in them and while > it seems that they would benefit from the change, extra checking is needed. > The biggest corner issue is the fact that refcount_inc() does not increment > from zero. > > If there are no objections to the patches, please merge them via respective trees. > > * The respective change is currently merged into -next as > "locking/refcount: Create unchecked atomic_t implementation". > > Elena Reshetova (17): > net: convert inet_peer.refcnt from atomic_t to refcount_t > net: convert neighbour.refcnt from atomic_t to refcount_t > net: convert neigh_params.refcnt from atomic_t to refcount_t > net: convert nf_bridge_info.use from atomic_t to refcount_t > net: convert sk_buff.users from atomic_t to refcount_t > net: convert sk_buff_fclones.fclone_ref from atomic_t to refcount_t > net: convert sock.sk_wmem_alloc from atomic_t to refcount_t > net: convert sock.sk_refcnt from atomic_t to refcount_t > net: convert ip_mc_list.refcnt from atomic_t to refcount_t > net: convert in_device.refcnt from atomic_t to refcount_t > net: convert netpoll_info.refcnt from atomic_t to refcount_t > net: convert unix_address.refcnt from atomic_t to refcount_t > net: convert fib_rule.refcnt from atomic_t to refcount_t > net: convert inet_frag_queue.refcnt from atomic_t to refcount_t > net: convert net.passive from atomic_t to refcount_t > net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t > net: convert packet_fanout.sk_ref from atomic_t to refcount_t Can you take a look at this please ? Thanks. [ 64.601749] ------------[ cut here ]------------ [ 64.601757] WARNING: CPU: 0 PID: 6476 at lib/refcount.c:184 refcount_sub_and_test+0x75/0xa0 [ 64.601758] Modules linked in: w1_therm wire cdc_acm ehci_pci ehci_hcd mlx4_en ib_uverbs mlx4_ib ib_core mlx4_core [ 64.601769] CPU: 0 PID: 6476 Comm: ip Tainted: G W 4.12.0-smp-DEV #274 [ 64.601770] Hardware name: Intel RML,PCH/Iota_QC_19, BIOS 2.40.0 06/22/2016 [ 64.601771] task: ffff8837bf482040 task.stack: ffff8837bdc08000 [ 64.601773] RIP: 0010:refcount_sub_and_test+0x75/0xa0 [ 64.601774] RSP: 0018:ffff8837bdc0f5c0 EFLAGS: 00010286 [ 64.601776] RAX: 0000000000000026 RBX: 0000000000000001 RCX: 0000000000000000 [ 64.601777] RDX: 0000000000000026 RSI: 0000000000000096 RDI: ffffed06f7b81eae [ 64.601778] RBP: ffff8837bdc0f5d0 R08: 0000000000000004 R09: fffffbfff4a54c25 [ 64.601779] R10: 00000000cbc500e5 R11: ffffffffa52a6128 R12: ffff881febcf6f24 [ 64.601779] R13: ffff881fbf4eaf00 R14: ffff881febcf6f80 R15: ffff8837d7a4ed00 [ 64.601781] FS: 00007ff5a2f6b700(0000) GS:ffff881fff800000(0000) knlGS:0000000000000000 [ 64.601782] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 64.601783] CR2: 00007ffcdc70d000 CR3: 0000001f9c91e000 CR4: 00000000001406f0 [ 64.601783] Call Trace: [ 64.601786] refcount_dec_and_test+0x11/0x20 [ 64.601790] fib_nl_delrule+0xc39/0x1630 [ 64.601793] ? is_bpf_text_address+0xe/0x20 [ 64.601795] ? fib_nl_newrule+0x25e0/0x25e0 [ 64.601798] ? depot_save_stack+0x133/0x470 [ 64.601801] ? ns_capable+0x13/0x20 [ 64.601803] ? __netlink_ns_capable+0xcc/0x100 [ 64.601806] rtnetlink_rcv_msg+0x23a/0x6a0 [ 64.601808] ? rtnl_newlink+0x1630/0x1630 [ 64.601811] ? memset+0x31/0x40 [ 64.601813] netlink_rcv_skb+0x2d7/0x440 [ 64.601815] ? rtnl_newlink+0x1630/0x1630 [ 64.601816] ? netlink_ack+0xaf0/0xaf0 [ 64.601818] ? kasan_unpoison_shadow+0x35/0x50 [ 64.601820] ? __kmalloc_node_track_caller+0x4c/0x70 [ 64.601821] rtnetlink_rcv+0x28/0x30 [ 64.601823] netlink_unicast+0x422/0x610 [ 64.601824] ? netlink_attachskb+0x650/0x650 [ 64.601826] netlink_sendmsg+0x7b7/0xb60 [ 64.601828] ? netlink_unicast+0x610/0x610 [ 64.601830] ? netlink_unicast+0x610/0x610 [ 64.601832] sock_sendmsg+0xba/0xf0 [ 64.601834] ___sys_sendmsg+0x6a9/0x8c0 [ 64.601835] ? copy_msghdr_from_user+0x520/0x520 [ 64.601837] ? __alloc_pages_nodemask+0x160/0x520 [ 64.601839] ? memcg_write_event_control+0xd60/0xd60 [ 64.601841] ? __alloc_pages_slowpath+0x1d50/0x1d50 [ 64.601843] ? kasan_slab_free+0x71/0xc0 [ 64.601845] ? mem_cgroup_commit_charge+0xb2/0x11d0 [ 64.601847] ? lru_cache_add_active_or_unevictable+0x7d/0x1a0 [ 64.601849] ? __handle_mm_fault+0x1af8/0x2810 [ 64.601851] ? may_open_dev+0xc0/0xc0 [ 64.601852] ? __pmd_alloc+0x2c0/0x2c0 [ 64.601853] ? __fdget+0x13/0x20 [ 64.601855] __sys_sendmsg+0xc6/0x150 [ 64.601856] ? __sys_sendmsg+0xc6/0x150 [ 64.601857] ? SyS_shutdown+0x170/0x170 [ 64.601859] ? handle_mm_fault+0x28a/0x650 [ 64.601861] SyS_sendmsg+0x12/0x20 [ 64.601863] entry_SYSCALL_64_fastpath+0x13/0x94 [ 64.601864] RIP: 0033:0x7ff5a29b6080 [ 64.601865] RSP: 002b:00007ffcdc707e08 EFLAGS: 00000246 ORIG_RAX: 000000000000002e [ 64.601867] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007ff5a29b6080 [ 64.601867] RDX: 0000000000000000 RSI: 00007ffcdc707e58 RDI: 0000000000000003 [ 64.601868] RBP: 00007ffcdc70fec0 R08: 0000000000000001 R09: 0000000000000000 [ 64.601869] R10: 00007ffcdc711eb7 R11: 0000000000000246 R12: 0000000000456000 [ 64.601870] R13: 00007ffcdc7108b0 R14: 0000000000000000 R15: 0000000000000001 [ 64.601871] Code: 16 75 33 85 d2 0f 94 c0 48 83 c4 08 5b 5d c3 80 3d 7d 5b 84 01 00 75 15 48 c7 c7 60 8e 57 a4 c6 05 6d 5b 84 01 01 e8 bb e2 99 ff <0f> ff 31 c0 48 83 c4 08 5b 5d c3 83 f8 ff 75 b3 31 c0 eb f0 48
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-07-03 12:00 +0200 |
| Message-ID | <tZ6j8-7MN-23@gated-at.bofh.it> |
| In reply to | #1679822 |
> On Fri, 2017-06-30 at 13:07 +0300, Elena Reshetova wrote: > > Changes in v3: > > Rebased on top of the net-next tree. > > > > Changes in v2: > > No changes in patches apart from rebases, but now 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 core 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. > > These patches contain only generic net pieces. Other changes will be sent > separately. > > > > The patches are fully independent and can be cherry-picked separately. > > The big patches, such as conversions for sock structure, need a very detailed > > look from maintainers: refcount managing is quite complex in them and while > > it seems that they would benefit from the change, extra checking is needed. > > The biggest corner issue is the fact that refcount_inc() does not increment > > from zero. > > > > If there are no objections to the patches, please merge them via respective trees. > > > > * The respective change is currently merged into -next as > > "locking/refcount: Create unchecked atomic_t implementation". > > > > Elena Reshetova (17): > > net: convert inet_peer.refcnt from atomic_t to refcount_t > > net: convert neighbour.refcnt from atomic_t to refcount_t > > net: convert neigh_params.refcnt from atomic_t to refcount_t > > net: convert nf_bridge_info.use from atomic_t to refcount_t > > net: convert sk_buff.users from atomic_t to refcount_t > > net: convert sk_buff_fclones.fclone_ref from atomic_t to refcount_t > > net: convert sock.sk_wmem_alloc from atomic_t to refcount_t > > net: convert sock.sk_refcnt from atomic_t to refcount_t > > net: convert ip_mc_list.refcnt from atomic_t to refcount_t > > net: convert in_device.refcnt from atomic_t to refcount_t > > net: convert netpoll_info.refcnt from atomic_t to refcount_t > > net: convert unix_address.refcnt from atomic_t to refcount_t > > net: convert fib_rule.refcnt from atomic_t to refcount_t > > net: convert inet_frag_queue.refcnt from atomic_t to refcount_t > > net: convert net.passive from atomic_t to refcount_t > > net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t > > net: convert packet_fanout.sk_ref from atomic_t to refcount_t > > > Can you take a look at this please ? > > Thanks. Thank you very much for the report! This is an underflow (dec/sub from zero) that is reported by WARNING. I guess it is unlikely that actual code underflows, so the most probable cause is that it attempted to do refcount_inc/add() from zero, but then failed. However in that case you should have seen another warning on refcount_inc() somewhere earlier. That one is actually the one I need to see to track the root cause. Could you tell me how do you arrive to the below output? Boot in what config/etc. I can try to reproduce to debug further. Best Regards, Elena > > [ 64.601749] ------------[ cut here ]------------ > [ 64.601757] WARNING: CPU: 0 PID: 6476 at lib/refcount.c:184 > refcount_sub_and_test+0x75/0xa0 > [ 64.601758] Modules linked in: w1_therm wire cdc_acm ehci_pci ehci_hcd > mlx4_en ib_uverbs mlx4_ib ib_core mlx4_core > [ 64.601769] CPU: 0 PID: 6476 Comm: ip Tainted: G W 4.12.0-smp-DEV #274 > [ 64.601770] Hardware name: Intel RML,PCH/Iota_QC_19, BIOS 2.40.0 06/22/2016 > [ 64.601771] task: ffff8837bf482040 task.stack: ffff8837bdc08000 > [ 64.601773] RIP: 0010:refcount_sub_and_test+0x75/0xa0 > [ 64.601774] RSP: 0018:ffff8837bdc0f5c0 EFLAGS: 00010286 > [ 64.601776] RAX: 0000000000000026 RBX: 0000000000000001 RCX: > 0000000000000000 > [ 64.601777] RDX: 0000000000000026 RSI: 0000000000000096 RDI: > ffffed06f7b81eae > [ 64.601778] RBP: ffff8837bdc0f5d0 R08: 0000000000000004 R09: fffffbfff4a54c25 > [ 64.601779] R10: 00000000cbc500e5 R11: ffffffffa52a6128 R12: ffff881febcf6f24 > [ 64.601779] R13: ffff881fbf4eaf00 R14: ffff881febcf6f80 R15: ffff8837d7a4ed00 > [ 64.601781] FS: 00007ff5a2f6b700(0000) GS:ffff881fff800000(0000) > knlGS:0000000000000000 > [ 64.601782] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > [ 64.601783] CR2: 00007ffcdc70d000 CR3: 0000001f9c91e000 CR4: > 00000000001406f0 > [ 64.601783] Call Trace: > [ 64.601786] refcount_dec_and_test+0x11/0x20 > [ 64.601790] fib_nl_delrule+0xc39/0x1630 > [ 64.601793] ? is_bpf_text_address+0xe/0x20 > [ 64.601795] ? fib_nl_newrule+0x25e0/0x25e0 > [ 64.601798] ? depot_save_stack+0x133/0x470 > [ 64.601801] ? ns_capable+0x13/0x20 > [ 64.601803] ? __netlink_ns_capable+0xcc/0x100 > [ 64.601806] rtnetlink_rcv_msg+0x23a/0x6a0 > [ 64.601808] ? rtnl_newlink+0x1630/0x1630 > [ 64.601811] ? memset+0x31/0x40 > [ 64.601813] netlink_rcv_skb+0x2d7/0x440 > [ 64.601815] ? rtnl_newlink+0x1630/0x1630 > [ 64.601816] ? netlink_ack+0xaf0/0xaf0 > [ 64.601818] ? kasan_unpoison_shadow+0x35/0x50 > [ 64.601820] ? __kmalloc_node_track_caller+0x4c/0x70 > [ 64.601821] rtnetlink_rcv+0x28/0x30 > [ 64.601823] netlink_unicast+0x422/0x610 > [ 64.601824] ? netlink_attachskb+0x650/0x650 > [ 64.601826] netlink_sendmsg+0x7b7/0xb60 > [ 64.601828] ? netlink_unicast+0x610/0x610 > [ 64.601830] ? netlink_unicast+0x610/0x610 > [ 64.601832] sock_sendmsg+0xba/0xf0 > [ 64.601834] ___sys_sendmsg+0x6a9/0x8c0 > [ 64.601835] ? copy_msghdr_from_user+0x520/0x520 > [ 64.601837] ? __alloc_pages_nodemask+0x160/0x520 > [ 64.601839] ? memcg_write_event_control+0xd60/0xd60 > [ 64.601841] ? __alloc_pages_slowpath+0x1d50/0x1d50 > [ 64.601843] ? kasan_slab_free+0x71/0xc0 > [ 64.601845] ? mem_cgroup_commit_charge+0xb2/0x11d0 > [ 64.601847] ? lru_cache_add_active_or_unevictable+0x7d/0x1a0 > [ 64.601849] ? __handle_mm_fault+0x1af8/0x2810 > [ 64.601851] ? may_open_dev+0xc0/0xc0 > [ 64.601852] ? __pmd_alloc+0x2c0/0x2c0 > [ 64.601853] ? __fdget+0x13/0x20 > [ 64.601855] __sys_sendmsg+0xc6/0x150 > [ 64.601856] ? __sys_sendmsg+0xc6/0x150 > [ 64.601857] ? SyS_shutdown+0x170/0x170 > [ 64.601859] ? handle_mm_fault+0x28a/0x650 > [ 64.601861] SyS_sendmsg+0x12/0x20 > [ 64.601863] entry_SYSCALL_64_fastpath+0x13/0x94 > [ 64.601864] RIP: 0033:0x7ff5a29b6080 > [ 64.601865] RSP: 002b:00007ffcdc707e08 EFLAGS: 00000246 ORIG_RAX: > 000000000000002e > [ 64.601867] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007ff5a29b6080 > [ 64.601867] RDX: 0000000000000000 RSI: 00007ffcdc707e58 RDI: > 0000000000000003 > [ 64.601868] RBP: 00007ffcdc70fec0 R08: 0000000000000001 R09: > 0000000000000000 > [ 64.601869] R10: 00007ffcdc711eb7 R11: 0000000000000246 R12: > 0000000000456000 > [ 64.601870] R13: 00007ffcdc7108b0 R14: 0000000000000000 R15: > 0000000000000001 > [ 64.601871] Code: 16 75 33 85 d2 0f 94 c0 48 83 c4 08 5b 5d c3 80 3d 7d 5b 84 01 > 00 75 15 48 c7 c7 60 8e 57 a4 c6 05 6d 5b 84 01 01 e8 bb e2 99 ff <0f> ff 31 c0 48 83 > c4 08 5b 5d c3 83 f8 ff 75 b3 31 c0 eb f0 48 >
[toc] | [prev] | [next] | [standalone]
| From | Eric Dumazet <eric.dumazet@gmail.com> |
|---|---|
| Date | 2017-07-03 12:40 +0200 |
| Message-ID | <tZ6VR-5S-23@gated-at.bofh.it> |
| In reply to | #1679853 |
On Mon, 2017-07-03 at 09:57 +0000, Reshetova, Elena wrote: > Thank you very much for the report! This is an underflow (dec/sub from > zero) that is reported by WARNING. > I guess it is unlikely that actual code underflows, so the most > probable cause is that it attempted to do refcount_inc/add() from > zero, but then failed. > However in that case you should have seen another warning on > refcount_inc() somewhere earlier. That one is actually the one I need > to see to track the root cause. > Could you tell me how do you arrive to the below output? Boot in what > config/etc. > I can try to reproduce to debug further. I sent this fix : https://patchwork.ozlabs.org/patch/783389/ Thanks.
[toc] | [prev] | [next] | [standalone]
| From | "Levin, Alexander (Sasha Levin)" <alexander.levin@verizon.com> |
|---|---|
| Date | 2017-07-08 21:00 +0200 |
| Message-ID | <u137r-5L6-1@gated-at.bofh.it> |
| In reply to | #1679822 |
On Mon, Jul 03, 2017 at 02:28:56AM -0700, Eric Dumazet wrote: >On Fri, 2017-06-30 at 13:07 +0300, Elena Reshetova wrote: >> Changes in v3: >> Rebased on top of the net-next tree. >> >> Changes in v2: >> No changes in patches apart from rebases, but now 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 core 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. >> These patches contain only generic net pieces. Other changes will be sent separately. >> >> The patches are fully independent and can be cherry-picked separately. >> The big patches, such as conversions for sock structure, need a very detailed >> look from maintainers: refcount managing is quite complex in them and while >> it seems that they would benefit from the change, extra checking is needed. >> The biggest corner issue is the fact that refcount_inc() does not increment >> from zero. >> >> If there are no objections to the patches, please merge them via respective trees. >> >> * The respective change is currently merged into -next as >> "locking/refcount: Create unchecked atomic_t implementation". >> >> Elena Reshetova (17): >> net: convert inet_peer.refcnt from atomic_t to refcount_t >> net: convert neighbour.refcnt from atomic_t to refcount_t >> net: convert neigh_params.refcnt from atomic_t to refcount_t >> net: convert nf_bridge_info.use from atomic_t to refcount_t >> net: convert sk_buff.users from atomic_t to refcount_t >> net: convert sk_buff_fclones.fclone_ref from atomic_t to refcount_t >> net: convert sock.sk_wmem_alloc from atomic_t to refcount_t >> net: convert sock.sk_refcnt from atomic_t to refcount_t >> net: convert ip_mc_list.refcnt from atomic_t to refcount_t >> net: convert in_device.refcnt from atomic_t to refcount_t >> net: convert netpoll_info.refcnt from atomic_t to refcount_t >> net: convert unix_address.refcnt from atomic_t to refcount_t >> net: convert fib_rule.refcnt from atomic_t to refcount_t >> net: convert inet_frag_queue.refcnt from atomic_t to refcount_t >> net: convert net.passive from atomic_t to refcount_t >> net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t >> net: convert packet_fanout.sk_ref from atomic_t to refcount_t > > >Can you take a look at this please ? > >[ 64.601749] ------------[ cut here ]------------ >[ 64.601757] WARNING: CPU: 0 PID: 6476 at lib/refcount.c:184 refcount_sub_and_test+0x75/0xa0 >[ 64.601758] Modules linked in: w1_therm wire cdc_acm ehci_pci ehci_hcd mlx4_en ib_uverbs mlx4_ib ib_core mlx4_core >[ 64.601769] CPU: 0 PID: 6476 Comm: ip Tainted: G W 4.12.0-smp-DEV #274 >[ 64.601770] Hardware name: Intel RML,PCH/Iota_QC_19, BIOS 2.40.0 06/22/2016 >[ 64.601771] task: ffff8837bf482040 task.stack: ffff8837bdc08000 >[ 64.601773] RIP: 0010:refcount_sub_and_test+0x75/0xa0 >[ 64.601774] RSP: 0018:ffff8837bdc0f5c0 EFLAGS: 00010286 >[ 64.601776] RAX: 0000000000000026 RBX: 0000000000000001 RCX: 0000000000000000 >[ 64.601777] RDX: 0000000000000026 RSI: 0000000000000096 RDI: ffffed06f7b81eae >[ 64.601778] RBP: ffff8837bdc0f5d0 R08: 0000000000000004 R09: fffffbfff4a54c25 >[ 64.601779] R10: 00000000cbc500e5 R11: ffffffffa52a6128 R12: ffff881febcf6f24 >[ 64.601779] R13: ffff881fbf4eaf00 R14: ffff881febcf6f80 R15: ffff8837d7a4ed00 >[ 64.601781] FS: 00007ff5a2f6b700(0000) GS:ffff881fff800000(0000) knlGS:0000000000000000 >[ 64.601782] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 >[ 64.601783] CR2: 00007ffcdc70d000 CR3: 0000001f9c91e000 CR4: 00000000001406f0 >[ 64.601783] Call Trace: >[ 64.601786] refcount_dec_and_test+0x11/0x20 >[ 64.601790] fib_nl_delrule+0xc39/0x1630 [snip] I'm seeing a similar one coming from sctp: refcount_t: underflow; use-after-free. ------------[ cut here ]------------ WARNING: CPU: 3 PID: 15570 at lib/refcount.c:186 refcount_sub_and_test.cold.13+0x18/0x21 lib/refcount.c:186 Kernel panic - not syncing: panic_on_warn set ... CPU: 3 PID: 15570 Comm: syz-executor0 Not tainted 4.12.0-next-20170706+ #186 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 04/01/2014 Call Trace: __dump_stack lib/dump_stack.c:16 [inline] dump_stack+0x11d/0x1ef lib/dump_stack.c:52 panic+0x1bc/0x3ad kernel/panic.c:180 __warn.cold.6+0x2f/0x2f kernel/panic.c:541 report_bug+0x20d/0x2d0 lib/bug.c:183 fixup_bug+0x3f/0x90 arch/x86/kernel/traps.c:190 do_trap_no_signal arch/x86/kernel/traps.c:224 [inline] do_trap+0x132/0x390 arch/x86/kernel/traps.c:273 do_error_trap+0x133/0x380 arch/x86/kernel/traps.c:310 do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:323 invalid_op+0x1e/0x30 arch/x86/entry/entry_64.S:845 RIP: 0010:refcount_sub_and_test.cold.13+0x18/0x21 lib/refcount.c:186 RSP: 0018:ffff880062f7e270 EFLAGS: 00010282 RAX: 0000000000000026 RBX: ffff88006086a8cc RCX: 0000000000000000 RDX: 0000000000000000 RSI: 1ffff1000c5efc0a RDI: ffffffffac15c400 RBP: ffff880062f7e2f8 R08: 0000000000000006 R09: 0000000000000000 R10: ffff880069914040 R11: 0000000000000000 R12: 00000000ffffff01 R13: 0000000000000100 R14: 1ffff1000c5efc4e R15: 0000000000000001 sctp_wfree+0x183/0x620 net/sctp/socket.c:7745 skb_release_head_state+0x124/0x250 net/core/skbuff.c:652 skb_release_all+0x15/0x60 net/core/skbuff.c:665 __kfree_skb net/core/skbuff.c:681 [inline] consume_skb+0x16c/0x500 net/core/skbuff.c:748 sctp_chunk_destroy net/sctp/sm_make_chunk.c:1441 [inline] sctp_chunk_put+0x206/0x430 net/sctp/sm_make_chunk.c:1468 sctp_chunk_free+0x53/0x60 net/sctp/sm_make_chunk.c:1455 __sctp_outq_teardown+0x274/0x15b0 net/sctp/outqueue.c:228 sctp_outq_free+0x15/0x20 net/sctp/outqueue.c:284 sctp_association_free+0x2d4/0x934 net/sctp/associola.c:358 sctp_cmd_delete_tcb net/sctp/sm_sideeffect.c:917 [inline] sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1333 [inline] sctp_side_effects net/sctp/sm_sideeffect.c:1198 [inline] sctp_do_sm+0x4024/0x6d60 net/sctp/sm_sideeffect.c:1170 sctp_primitive_ABORT+0xa0/0xd0 net/sctp/primitive.c:119 sctp_close+0x293/0x9b0 net/sctp/socket.c:1529 inet_release+0xed/0x1c0 net/ipv4/af_inet.c:425 inet6_release+0x50/0x70 net/ipv6/af_inet6.c:432 sock_release+0x8d/0x1b0 net/socket.c:597 sock_close+0x16/0x20 net/socket.c:1112 __fput+0x327/0x920 fs/file_table.c:210 ____fput+0x15/0x20 fs/file_table.c:246 llcp: llcp_sock_recvmsg: Recv datagram failed state 5 -11 0 task_work_run+0x192/0x270 kernel/task_work.c:116 exit_task_work include/linux/task_work.h:21 [inline] do_exit+0xa42/0x1ba0 kernel/exit.c:864 do_group_exit+0x151/0x410 kernel/exit.c:966 get_signal+0x84e/0x18a0 kernel/signal.c:2330 do_signal+0x9c/0x2210 arch/x86/kernel/signal.c:808 exit_to_usermode_loop+0x187/0x220 arch/x86/entry/common.c:157 prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline] syscall_return_slowpath arch/x86/entry/common.c:263 [inline] do_syscall_64+0x50b/0x740 arch/x86/entry/common.c:289 llcp: llcp_sock_recvmsg: Recv datagram failed state 5 -11 0 entry_SYSCALL64_slow_path+0x25/0x25 RIP: 0033:0x452309 RSP: 002b:00007f6aed443cf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca RAX: fffffffffffffe00 RBX: 0000000000718218 RCX: 0000000000452309 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000718218 RBP: 00000000007181f8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 00007fffb90a5aae R13: 00007fffb90a5aaf R14: 00007f6aed4449c0 R15: 00007f6aed444700 Dumping ftrace buffer: (ftrace buffer empty) Kernel Offset: 0x24000000 from 0xffffffff81000000 (relocation range: 0xffffffff80000000-0xffffffffbfffffff) Rebooting in 86400 seconds.. -- Thanks, Sasha
[toc] | [prev] | [next] | [standalone]
| From | "Reshetova, Elena" <elena.reshetova@intel.com> |
|---|---|
| Date | 2017-07-10 09:20 +0200 |
| Message-ID | <u1B97-1VK-5@gated-at.bofh.it> |
| In reply to | #1683636 |
> On Mon, Jul 03, 2017 at 02:28:56AM -0700, Eric Dumazet wrote: > >On Fri, 2017-06-30 at 13:07 +0300, Elena Reshetova wrote: > >> Changes in v3: > >> Rebased on top of the net-next tree. > >> > >> Changes in v2: > >> No changes in patches apart from rebases, but now 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 core 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. > >> These patches contain only generic net pieces. Other changes will be sent > separately. > >> > >> The patches are fully independent and can be cherry-picked separately. > >> The big patches, such as conversions for sock structure, need a very detailed > >> look from maintainers: refcount managing is quite complex in them and while > >> it seems that they would benefit from the change, extra checking is needed. > >> The biggest corner issue is the fact that refcount_inc() does not increment > >> from zero. > >> > >> If there are no objections to the patches, please merge them via respective > trees. > >> > >> * The respective change is currently merged into -next as > >> "locking/refcount: Create unchecked atomic_t implementation". > >> > >> Elena Reshetova (17): > >> net: convert inet_peer.refcnt from atomic_t to refcount_t > >> net: convert neighbour.refcnt from atomic_t to refcount_t > >> net: convert neigh_params.refcnt from atomic_t to refcount_t > >> net: convert nf_bridge_info.use from atomic_t to refcount_t > >> net: convert sk_buff.users from atomic_t to refcount_t > >> net: convert sk_buff_fclones.fclone_ref from atomic_t to refcount_t > >> net: convert sock.sk_wmem_alloc from atomic_t to refcount_t > >> net: convert sock.sk_refcnt from atomic_t to refcount_t > >> net: convert ip_mc_list.refcnt from atomic_t to refcount_t > >> net: convert in_device.refcnt from atomic_t to refcount_t > >> net: convert netpoll_info.refcnt from atomic_t to refcount_t > >> net: convert unix_address.refcnt from atomic_t to refcount_t > >> net: convert fib_rule.refcnt from atomic_t to refcount_t > >> net: convert inet_frag_queue.refcnt from atomic_t to refcount_t > >> net: convert net.passive from atomic_t to refcount_t > >> net: convert netlbl_lsm_cache.refcount from atomic_t to refcount_t > >> net: convert packet_fanout.sk_ref from atomic_t to refcount_t > > > > > >Can you take a look at this please ? > > > >[ 64.601749] ------------[ cut here ]------------ > >[ 64.601757] WARNING: CPU: 0 PID: 6476 at lib/refcount.c:184 > refcount_sub_and_test+0x75/0xa0 > >[ 64.601758] Modules linked in: w1_therm wire cdc_acm ehci_pci ehci_hcd > mlx4_en ib_uverbs mlx4_ib ib_core mlx4_core > >[ 64.601769] CPU: 0 PID: 6476 Comm: ip Tainted: G W 4.12.0-smp-DEV > #274 > >[ 64.601770] Hardware name: Intel RML,PCH/Iota_QC_19, BIOS 2.40.0 > 06/22/2016 > >[ 64.601771] task: ffff8837bf482040 task.stack: ffff8837bdc08000 > >[ 64.601773] RIP: 0010:refcount_sub_and_test+0x75/0xa0 > >[ 64.601774] RSP: 0018:ffff8837bdc0f5c0 EFLAGS: 00010286 > >[ 64.601776] RAX: 0000000000000026 RBX: 0000000000000001 RCX: > 0000000000000000 > >[ 64.601777] RDX: 0000000000000026 RSI: 0000000000000096 RDI: > ffffed06f7b81eae > >[ 64.601778] RBP: ffff8837bdc0f5d0 R08: 0000000000000004 R09: > fffffbfff4a54c25 > >[ 64.601779] R10: 00000000cbc500e5 R11: ffffffffa52a6128 R12: ffff881febcf6f24 > >[ 64.601779] R13: ffff881fbf4eaf00 R14: ffff881febcf6f80 R15: ffff8837d7a4ed00 > >[ 64.601781] FS: 00007ff5a2f6b700(0000) GS:ffff881fff800000(0000) > knlGS:0000000000000000 > >[ 64.601782] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 > >[ 64.601783] CR2: 00007ffcdc70d000 CR3: 0000001f9c91e000 CR4: > 00000000001406f0 > >[ 64.601783] Call Trace: > >[ 64.601786] refcount_dec_and_test+0x11/0x20 > >[ 64.601790] fib_nl_delrule+0xc39/0x1630 > [snip] > > I'm seeing a similar one coming from sctp: > > refcount_t: underflow; use-after-free. > ------------[ cut here ]------------ > WARNING: CPU: 3 PID: 15570 at lib/refcount.c:186 > refcount_sub_and_test.cold.13+0x18/0x21 lib/refcount.c:186 > Kernel panic - not syncing: panic_on_warn set ... > > CPU: 3 PID: 15570 Comm: syz-executor0 Not tainted 4.12.0-next-20170706+ #186 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.1-1ubuntu1 > 04/01/2014 > Call Trace: > __dump_stack lib/dump_stack.c:16 [inline] > dump_stack+0x11d/0x1ef lib/dump_stack.c:52 > panic+0x1bc/0x3ad kernel/panic.c:180 > __warn.cold.6+0x2f/0x2f kernel/panic.c:541 > report_bug+0x20d/0x2d0 lib/bug.c:183 > fixup_bug+0x3f/0x90 arch/x86/kernel/traps.c:190 > do_trap_no_signal arch/x86/kernel/traps.c:224 [inline] > do_trap+0x132/0x390 arch/x86/kernel/traps.c:273 > do_error_trap+0x133/0x380 arch/x86/kernel/traps.c:310 > do_invalid_op+0x1b/0x20 arch/x86/kernel/traps.c:323 > invalid_op+0x1e/0x30 arch/x86/entry/entry_64.S:845 > RIP: 0010:refcount_sub_and_test.cold.13+0x18/0x21 lib/refcount.c:186 > RSP: 0018:ffff880062f7e270 EFLAGS: 00010282 > RAX: 0000000000000026 RBX: ffff88006086a8cc RCX: 0000000000000000 > RDX: 0000000000000000 RSI: 1ffff1000c5efc0a RDI: ffffffffac15c400 > RBP: ffff880062f7e2f8 R08: 0000000000000006 R09: 0000000000000000 > R10: ffff880069914040 R11: 0000000000000000 R12: 00000000ffffff01 > R13: 0000000000000100 R14: 1ffff1000c5efc4e R15: 0000000000000001 > sctp_wfree+0x183/0x620 net/sctp/socket.c:7745 > skb_release_head_state+0x124/0x250 net/core/skbuff.c:652 > skb_release_all+0x15/0x60 net/core/skbuff.c:665 > __kfree_skb net/core/skbuff.c:681 [inline] > consume_skb+0x16c/0x500 net/core/skbuff.c:748 > sctp_chunk_destroy net/sctp/sm_make_chunk.c:1441 [inline] > sctp_chunk_put+0x206/0x430 net/sctp/sm_make_chunk.c:1468 > sctp_chunk_free+0x53/0x60 net/sctp/sm_make_chunk.c:1455 > __sctp_outq_teardown+0x274/0x15b0 net/sctp/outqueue.c:228 > sctp_outq_free+0x15/0x20 net/sctp/outqueue.c:284 > sctp_association_free+0x2d4/0x934 net/sctp/associola.c:358 > sctp_cmd_delete_tcb net/sctp/sm_sideeffect.c:917 [inline] > sctp_cmd_interpreter net/sctp/sm_sideeffect.c:1333 [inline] > sctp_side_effects net/sctp/sm_sideeffect.c:1198 [inline] > sctp_do_sm+0x4024/0x6d60 net/sctp/sm_sideeffect.c:1170 > sctp_primitive_ABORT+0xa0/0xd0 net/sctp/primitive.c:119 > sctp_close+0x293/0x9b0 net/sctp/socket.c:1529 > inet_release+0xed/0x1c0 net/ipv4/af_inet.c:425 > inet6_release+0x50/0x70 net/ipv6/af_inet6.c:432 > sock_release+0x8d/0x1b0 net/socket.c:597 > sock_close+0x16/0x20 net/socket.c:1112 > __fput+0x327/0x920 fs/file_table.c:210 > ____fput+0x15/0x20 fs/file_table.c:246 > llcp: llcp_sock_recvmsg: Recv datagram failed state 5 -11 0 > task_work_run+0x192/0x270 kernel/task_work.c:116 > exit_task_work include/linux/task_work.h:21 [inline] > do_exit+0xa42/0x1ba0 kernel/exit.c:864 > do_group_exit+0x151/0x410 kernel/exit.c:966 > get_signal+0x84e/0x18a0 kernel/signal.c:2330 > do_signal+0x9c/0x2210 arch/x86/kernel/signal.c:808 > exit_to_usermode_loop+0x187/0x220 arch/x86/entry/common.c:157 > prepare_exit_to_usermode arch/x86/entry/common.c:194 [inline] > syscall_return_slowpath arch/x86/entry/common.c:263 [inline] > do_syscall_64+0x50b/0x740 arch/x86/entry/common.c:289 > llcp: llcp_sock_recvmsg: Recv datagram failed state 5 -11 0 > entry_SYSCALL64_slow_path+0x25/0x25 > RIP: 0033:0x452309 > RSP: 002b:00007f6aed443cf8 EFLAGS: 00000246 ORIG_RAX: 00000000000000ca > RAX: fffffffffffffe00 RBX: 0000000000718218 RCX: 0000000000452309 > RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000718218 > RBP: 00000000007181f8 R08: 0000000000000000 R09: 0000000000000000 > R10: 0000000000000000 R11: 0000000000000246 R12: 00007fffb90a5aae > R13: 00007fffb90a5aaf R14: 00007f6aed4449c0 R15: 00007f6aed444700 > Dumping ftrace buffer: > (ftrace buffer empty) > Kernel Offset: 0x24000000 from 0xffffffff81000000 (relocation range: > 0xffffffff80000000-0xffffffffbfffffff) > Rebooting in 86400 seconds.. > Thank you for reporting this! However, I might need some help checking what is going on there. Your kernel is enabled to panic on warn, which is great since it gives us understanding that this is a different issue than previous one (otherwise we would see a panic earlier when failing to increment from zero somewhere). The code that causes the warning here is this: @@ -7684,7 +7684,7 @@ static void sctp_wfree(struct sk_buff *skb) sizeof(struct sk_buff) + sizeof(struct sctp_chunk); - atomic_sub(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc); + WARN_ON(refcount_sub_and_test(sizeof(struct sctp_chunk), &sk->sk_wmem_alloc)); As you can see previously it would just do a atomic_sub() and not care of end result, but now it issues a warning if result underflows. Is it possible that it just uncovered the existing bug or was it supposed to underflow in certain conditions? Best Regards, Elena. > -- > > Thanks, > Sasha
[toc] | [prev] | [standalone]
Back to top | Article view | linux.kernel
csiph-web