aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReshetova, Elena <elena.reshetova@intel.com>2017-06-30 06:07:57 -0400
committerDavid S. Miller <davem@davemloft.net>2017-07-01 10:39:07 -0400
commit53869cebce4bc53f71a080e7830600d4ae1ab712 (patch)
treec99b8ea34f0b909e5db784b7426e1afcb21aeabf
parent6343944bc1050dcec7c959f484ee0fb6928db3be (diff)
net: convert nf_bridge_info.use from atomic_t to refcount_t
refcount_t type and corresponding API should be used instead of atomic_t when the variable is used as a reference counter. This allows to avoid accidental refcounter overflows that might lead to use-after-free situations. Signed-off-by: Elena Reshetova <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>
-rw-r--r--include/linux/skbuff.h6
-rw-r--r--include/net/netfilter/br_netfilter.h2
-rw-r--r--net/bridge/br_netfilter_hooks.c4
3 files changed, 6 insertions, 6 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index a17e235639ae..005793e01bd2 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -252,7 +252,7 @@ struct nf_conntrack {
252 252
253#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 253#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
254struct nf_bridge_info { 254struct nf_bridge_info {
255 atomic_t use; 255 refcount_t use;
256 enum { 256 enum {
257 BRNF_PROTO_UNCHANGED, 257 BRNF_PROTO_UNCHANGED,
258 BRNF_PROTO_8021Q, 258 BRNF_PROTO_8021Q,
@@ -3589,13 +3589,13 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
3589#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER) 3589#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3590static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) 3590static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
3591{ 3591{
3592 if (nf_bridge && atomic_dec_and_test(&nf_bridge->use)) 3592 if (nf_bridge && refcount_dec_and_test(&nf_bridge->use))
3593 kfree(nf_bridge); 3593 kfree(nf_bridge);
3594} 3594}
3595static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge) 3595static inline void nf_bridge_get(struct nf_bridge_info *nf_bridge)
3596{ 3596{
3597 if (nf_bridge) 3597 if (nf_bridge)
3598 atomic_inc(&nf_bridge->use); 3598 refcount_inc(&nf_bridge->use);
3599} 3599}
3600#endif /* CONFIG_BRIDGE_NETFILTER */ 3600#endif /* CONFIG_BRIDGE_NETFILTER */
3601static inline void nf_reset(struct sk_buff *skb) 3601static inline void nf_reset(struct sk_buff *skb)
diff --git a/include/net/netfilter/br_netfilter.h b/include/net/netfilter/br_netfilter.h
index 0b0c35c37125..925524ede6c8 100644
--- a/include/net/netfilter/br_netfilter.h
+++ b/include/net/netfilter/br_netfilter.h
@@ -8,7 +8,7 @@ static inline struct nf_bridge_info *nf_bridge_alloc(struct sk_buff *skb)
8 skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC); 8 skb->nf_bridge = kzalloc(sizeof(struct nf_bridge_info), GFP_ATOMIC);
9 9
10 if (likely(skb->nf_bridge)) 10 if (likely(skb->nf_bridge))
11 atomic_set(&(skb->nf_bridge->use), 1); 11 refcount_set(&(skb->nf_bridge->use), 1);
12 12
13 return skb->nf_bridge; 13 return skb->nf_bridge;
14} 14}
diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c
index 067cf0313449..2261e5194c82 100644
--- a/net/bridge/br_netfilter_hooks.c
+++ b/net/bridge/br_netfilter_hooks.c
@@ -149,12 +149,12 @@ static inline struct nf_bridge_info *nf_bridge_unshare(struct sk_buff *skb)
149{ 149{
150 struct nf_bridge_info *nf_bridge = skb->nf_bridge; 150 struct nf_bridge_info *nf_bridge = skb->nf_bridge;
151 151
152 if (atomic_read(&nf_bridge->use) > 1) { 152 if (refcount_read(&nf_bridge->use) > 1) {
153 struct nf_bridge_info *tmp = nf_bridge_alloc(skb); 153 struct nf_bridge_info *tmp = nf_bridge_alloc(skb);
154 154
155 if (tmp) { 155 if (tmp) {
156 memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info)); 156 memcpy(tmp, nf_bridge, sizeof(struct nf_bridge_info));
157 atomic_set(&tmp->use, 1); 157 refcount_set(&tmp->use, 1);
158 } 158 }
159 nf_bridge_put(nf_bridge); 159 nf_bridge_put(nf_bridge);
160 nf_bridge = tmp; 160 nf_bridge = tmp;