[PATCH nf] netfilter: helper: Fix possible panic after nf_conntrack_helper_unregister

2018-06-12 Thread gfree . wind
From: Gao Feng 

The helper module would be unloaded after nf_conntrack_helper_unregister,
so it may cause a possible panic caused by race.

nf_ct_iterate_destroy(unhelp, me) reset the helper of conntrack as NULL,
but maybe someone has gotten the helper pointer during this period. Then
it would panic, when it accesses the helper and the module was unloaded.

Take an example as following:
CPU0   CPU1
ctnetlink_dump_helpinfo
helper = rcu_dereference(help->helper);
   unhelp
   set helper as NULL
   unload helper module
helper->to_nlattr(skb, ct);

As above, the cpu0 tries to access the helper and its module is unloaded,
then the panic happens.

Signed-off-by: Gao Feng 
---
 net/netfilter/nf_conntrack_helper.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 551a1ed..b5b655d 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -465,6 +465,11 @@ void nf_conntrack_helper_unregister(struct 
nf_conntrack_helper *me)
 
nf_ct_expect_iterate_destroy(expect_iter_me, NULL);
nf_ct_iterate_destroy(unhelp, me);
+
+   /* Maybe someone has gotten the helper already when unhelp above.
+* So need to wait it.
+*/
+   synchronize_rcu();
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister);
 
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next] netfilter: nf_conntrack: Increase __IPS_MAX_BIT with new bit IPS_OFFLOAD_BIT

2018-06-07 Thread gfree . wind
From: Gao Feng 

The __IPS_MAX_BIT is used in __ctnetlink_change_status as the max bit
value. When add new bit IPS_OFFLOAD_BIT whose value is 14, we should
increase the __IPS_MAX_BIT too, from 14 to 15.

There is no any bug in current codes, although it lost one loop in
__ctnetlink_change_status. Because the new bit IPS_OFFLOAD_BIT belongs
the IPS_UNCHANGEABLE_MASK.

Signed-off-by: Gao Feng 
---
 include/uapi/linux/netfilter/nf_conntrack_common.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/uapi/linux/netfilter/nf_conntrack_common.h 
b/include/uapi/linux/netfilter/nf_conntrack_common.h
index c712eb6..336014b 100644
--- a/include/uapi/linux/netfilter/nf_conntrack_common.h
+++ b/include/uapi/linux/netfilter/nf_conntrack_common.h
@@ -112,7 +112,7 @@ enum ip_conntrack_status {
 IPS_EXPECTED | IPS_CONFIRMED | IPS_DYING |
 IPS_SEQ_ADJUST | IPS_TEMPLATE | IPS_OFFLOAD),
 
-   __IPS_MAX_BIT = 14,
+   __IPS_MAX_BIT = 15,
 };
 
 /* Connection tracking event types */
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v2] netfilter: xt_CT: Reject the non-null terminated string from user space

2018-05-29 Thread gfree . wind
From: Gao Feng 

The helper and timeout strings are from user-space, we need to make
sure they are null terminated. If not, evil user could make kernel
read the unexpected memory, even print it when fail to find by the
following codes.

pr_info_ratelimited("No such helper \"%s\"\n", helper_name);

Signed-off-by: Gao Feng 
---
 v2: reject the non-null terminated string directly, per Pablo
 v1: initial version

 net/netfilter/xt_CT.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 8790190..03b9a50 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -245,12 +245,22 @@ static int xt_ct_tg_check(const struct xt_tgchk_param 
*par,
}
 
if (info->helper[0]) {
+   if (strnlen(info->helper, sizeof(info->helper)) == 
sizeof(info->helper)) {
+   ret = -ENAMETOOLONG;
+   goto err3;
+   }
+
ret = xt_ct_set_helper(ct, info->helper, par);
if (ret < 0)
goto err3;
}
 
if (info->timeout[0]) {
+   if (strnlen(info->timeout, sizeof(info->timeout)) == 
sizeof(info->timeout)) {
+   ret = -ENAMETOOLONG;
+   goto err4;
+   }
+
ret = xt_ct_set_timeout(ct, par, info->timeout);
if (ret < 0)
goto err4;
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf] netfilter: xt_CT: Force user-space strings as null terminated

2018-05-28 Thread gfree . wind
From: Gao Feng 

The helper and timeout strings are from user-space, we need to make
sure they are null terminated. If not, evil user could make kernel
read the unexpected memory, even print it when fail to find by the
following codes.

pr_info_ratelimited("No such helper \"%s\"\n", helper_name);

Signed-off-by: Gao Feng 
---
 net/netfilter/xt_CT.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 8790190..f4b7d31 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -245,12 +245,14 @@ static int xt_ct_tg_check(const struct xt_tgchk_param 
*par,
}
 
if (info->helper[0]) {
+   info->helper[sizeof(info->helper) - 1] = '\0';
ret = xt_ct_set_helper(ct, info->helper, par);
if (ret < 0)
goto err3;
}
 
if (info->timeout[0]) {
+   info->timeout[sizeof(info->timeout) - 1] = '\0';
ret = xt_ct_set_timeout(ct, par, info->timeout);
if (ret < 0)
goto err4;
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next] netfilter: ipvs: Remove useless ipvsh param of frag_safe_skb_hp

2017-11-13 Thread gfree . wind
From: Gao Feng 

The param of frag_safe_skb_hp, ipvsh, isn't used now. So remove it and
update the callers' codes too.

Signed-off-by: Gao Feng 
---
 Simon advise me send the patch to netfilter group

 include/net/ip_vs.h |  3 +--
 net/netfilter/ipvs/ip_vs_conn.c |  2 +-
 net/netfilter/ipvs/ip_vs_core.c | 12 ++--
 3 files changed, 8 insertions(+), 9 deletions(-)

diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 5d08c19..acbc09d 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -69,8 +69,7 @@ struct ip_vs_iphdr {
 };
 
 static inline void *frag_safe_skb_hp(const struct sk_buff *skb, int offset,
- int len, void *buffer,
- const struct ip_vs_iphdr *ipvsh)
+ int len, void *buffer)
 {
return skb_header_pointer(skb, offset, len, buffer);
 }
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index f73561c..a35fade 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -322,7 +322,7 @@ struct ip_vs_conn *ip_vs_conn_in_get(const struct 
ip_vs_conn_param *p)
 {
__be16 _ports[2], *pptr;
 
-   pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
+   pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports);
if (pptr == NULL)
return 1;
 
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 5cb7cac..5f6f73c 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -433,7 +433,7 @@ struct ip_vs_conn *
/*
 * IPv6 frags, only the first hit here.
 */
-   pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
+   pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports);
if (pptr == NULL)
return NULL;
 
@@ -566,7 +566,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff 
*skb,
struct netns_ipvs *ipvs = svc->ipvs;
struct net *net = ipvs->net;
 
-   pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports, iph);
+   pptr = frag_safe_skb_hp(skb, iph->len, sizeof(_ports), _ports);
if (!pptr)
return NF_DROP;
dport = likely(!ip_vs_iph_inverse(iph)) ? pptr[1] : pptr[0];
@@ -982,7 +982,7 @@ static int ip_vs_out_icmp_v6(struct netns_ipvs *ipvs, 
struct sk_buff *skb,
unsigned int offset;
 
*related = 1;
-   ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph, ipvsh);
+   ic = frag_safe_skb_hp(skb, ipvsh->len, sizeof(_icmph), &_icmph);
if (ic == NULL)
return NF_DROP;
 
@@ -1214,7 +1214,7 @@ static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned 
int hooknum,
return NULL;
 
pptr = frag_safe_skb_hp(skb, iph->len,
-   sizeof(_ports), _ports, iph);
+   sizeof(_ports), _ports);
if (!pptr)
return NULL;
 
@@ -1407,7 +1407,7 @@ static struct ip_vs_conn *__ip_vs_rs_conn_out(unsigned 
int hooknum,
__be16 _ports[2], *pptr;
 
pptr = frag_safe_skb_hp(skb, iph.len,
-sizeof(_ports), _ports, );
+sizeof(_ports), _ports);
if (pptr == NULL)
return NF_ACCEPT;   /* Not for me */
if (ip_vs_has_real_service(ipvs, af, iph.protocol, ,
@@ -1741,7 +1741,7 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, 
struct sk_buff *skb,
 
*related = 1;
 
-   ic = frag_safe_skb_hp(skb, iph->len, sizeof(_icmph), &_icmph, iph);
+   ic = frag_safe_skb_hp(skb, iph->len, sizeof(_icmph), &_icmph);
if (ic == NULL)
return NF_DROP;
 
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 nf-next] netfilter: ebt: Use new helper ebt_invalid_target to check target

2017-05-31 Thread gfree . wind
From: Gao Feng 

Use the new helper function ebt_invalid_target instead of the old
macro INVALID_TARGET and other duplicated codes to enhance the readability.

Signed-off-by: Gao Feng 
---
 v2: Replace the target check of ebt_mark/snat, per Pablo
 v1: Initial version

 include/linux/netfilter_bridge/ebtables.h | 2 --
 net/bridge/netfilter/ebt_dnat.c   | 2 +-
 net/bridge/netfilter/ebt_mark.c   | 2 +-
 net/bridge/netfilter/ebt_redirect.c   | 2 +-
 net/bridge/netfilter/ebt_snat.c   | 2 +-
 5 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/include/linux/netfilter_bridge/ebtables.h 
b/include/linux/netfilter_bridge/ebtables.h
index e0cbf17..2c2a551 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -122,8 +122,6 @@ extern unsigned int ebt_do_table(struct sk_buff *skb,
 #define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS))
 /* Clear the bit in the hook mask that tells if the rule is on a base chain */
 #define CLEAR_BASE_CHAIN_BIT (par->hook_mask &= ~(1 << NF_BR_NUMHOOKS))
-/* True if the target is not a standard target */
-#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target 
>= 0)
 
 static inline bool ebt_invalid_target(int target)
 {
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index e0bb624..dfc86a0 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -61,7 +61,7 @@ static int ebt_dnat_tg_check(const struct xt_tgchk_param *par)
(strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING)))
return -EINVAL;
-   if (INVALID_TARGET)
+   if (ebt_invalid_target(info->target))
return -EINVAL;
return 0;
 }
diff --git a/net/bridge/netfilter/ebt_mark.c b/net/bridge/netfilter/ebt_mark.c
index 66697cb..19f0f95 100644
--- a/net/bridge/netfilter/ebt_mark.c
+++ b/net/bridge/netfilter/ebt_mark.c
@@ -44,7 +44,7 @@ static int ebt_mark_tg_check(const struct xt_tgchk_param *par)
tmp = info->target | ~EBT_VERDICT_BITS;
if (BASE_CHAIN && tmp == EBT_RETURN)
return -EINVAL;
-   if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
+   if (ebt_invalid_target(tmp))
return -EINVAL;
tmp = info->target & ~EBT_VERDICT_BITS;
if (tmp != MARK_SET_VALUE && tmp != MARK_OR_VALUE &&
diff --git a/net/bridge/netfilter/ebt_redirect.c 
b/net/bridge/netfilter/ebt_redirect.c
index 8d2a85e..a7223ea 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -47,7 +47,7 @@ static int ebt_redirect_tg_check(const struct xt_tgchk_param 
*par)
(strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING)))
return -EINVAL;
-   if (INVALID_TARGET)
+   if (ebt_invalid_target(info->target))
return -EINVAL;
return 0;
 }
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c
index e56ccd0..11cf9e9 100644
--- a/net/bridge/netfilter/ebt_snat.c
+++ b/net/bridge/netfilter/ebt_snat.c
@@ -51,7 +51,7 @@ static int ebt_snat_tg_check(const struct xt_tgchk_param *par)
if (BASE_CHAIN && tmp == EBT_RETURN)
return -EINVAL;
 
-   if (tmp < -NUM_STANDARD_TARGETS || tmp >= 0)
+   if (ebt_invalid_target(tmp))
return -EINVAL;
tmp = info->target | EBT_VERDICT_BITS;
if ((tmp & ~NAT_ARP_BIT) != ~NAT_ARP_BIT)
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next] netfilter: ebt: Use ebt_invalid_target instead of INVALID_TARGET

2017-05-30 Thread gfree . wind
From: Gao Feng 

Use the new helper function ebt_invalid_target instead of the old
macro INVALID_TARGET to enhance the readability.

Signed-off-by: Gao Feng 
---
 include/linux/netfilter_bridge/ebtables.h | 2 --
 net/bridge/netfilter/ebt_dnat.c   | 2 +-
 net/bridge/netfilter/ebt_redirect.c   | 2 +-
 3 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/include/linux/netfilter_bridge/ebtables.h 
b/include/linux/netfilter_bridge/ebtables.h
index e0cbf17..2c2a551 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -122,8 +122,6 @@ extern unsigned int ebt_do_table(struct sk_buff *skb,
 #define BASE_CHAIN (par->hook_mask & (1 << NF_BR_NUMHOOKS))
 /* Clear the bit in the hook mask that tells if the rule is on a base chain */
 #define CLEAR_BASE_CHAIN_BIT (par->hook_mask &= ~(1 << NF_BR_NUMHOOKS))
-/* True if the target is not a standard target */
-#define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target 
>= 0)
 
 static inline bool ebt_invalid_target(int target)
 {
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c
index e0bb624..dfc86a0 100644
--- a/net/bridge/netfilter/ebt_dnat.c
+++ b/net/bridge/netfilter/ebt_dnat.c
@@ -61,7 +61,7 @@ static int ebt_dnat_tg_check(const struct xt_tgchk_param *par)
(strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING)))
return -EINVAL;
-   if (INVALID_TARGET)
+   if (ebt_invalid_target(info->target))
return -EINVAL;
return 0;
 }
diff --git a/net/bridge/netfilter/ebt_redirect.c 
b/net/bridge/netfilter/ebt_redirect.c
index 8d2a85e..a7223ea 100644
--- a/net/bridge/netfilter/ebt_redirect.c
+++ b/net/bridge/netfilter/ebt_redirect.c
@@ -47,7 +47,7 @@ static int ebt_redirect_tg_check(const struct xt_tgchk_param 
*par)
(strcmp(par->table, "broute") != 0 ||
hook_mask & ~(1 << NF_BR_BROUTING)))
return -EINVAL;
-   if (INVALID_TARGET)
+   if (ebt_invalid_target(info->target))
return -EINVAL;
return 0;
 }
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v2] ebtables: arpreply: Add the standard target sanity check

2017-05-15 Thread gfree . wind
From: Gao Feng 

The info->target is from userspace and it would be used directly.
So we need to add the sanity check to make sure it is a valid standard
target, although the ebtables tool has already checked it. Kernel need
to check anything from userspace.

If the target was set as an evil value, it would break the ebtables
and cause a panic. Because the non-standard target is treated as one
offset.

Now add one helper function ebt_invalid_target, and we would replace
the macro INVALID_TARGET later.

Signed-off-by: Gao Feng 
---
 v2: Add one helper function ebt_invalid_target instead of INVALID_TARGET, per 
Pablo
 v1: initial version

 include/linux/netfilter_bridge/ebtables.h | 5 +
 net/bridge/netfilter/ebt_arpreply.c   | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/include/linux/netfilter_bridge/ebtables.h 
b/include/linux/netfilter_bridge/ebtables.h
index a30efb4..e0cbf17 100644
--- a/include/linux/netfilter_bridge/ebtables.h
+++ b/include/linux/netfilter_bridge/ebtables.h
@@ -125,4 +125,9 @@ extern unsigned int ebt_do_table(struct sk_buff *skb,
 /* True if the target is not a standard target */
 #define INVALID_TARGET (info->target < -NUM_STANDARD_TARGETS || info->target 
>= 0)
 
+static inline bool ebt_invalid_target(int target)
+{
+   return (target < -NUM_STANDARD_TARGETS || target >= 0);
+}
+
 #endif
diff --git a/net/bridge/netfilter/ebt_arpreply.c 
b/net/bridge/netfilter/ebt_arpreply.c
index 5929309..db85230 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -68,6 +68,9 @@ static int ebt_arpreply_tg_check(const struct xt_tgchk_param 
*par)
if (e->ethproto != htons(ETH_P_ARP) ||
e->invflags & EBT_IPROTO)
return -EINVAL;
+   if (ebt_invalid_target(info->target))
+   return -EINVAL;
+
return 0;
 }
 
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf] ebtables: arpreply: Add the standard target sanity check

2017-05-12 Thread gfree . wind
From: Gao Feng 

The info->target is from userspace and it would be used directly.
So we need to add the sanity check to make sure it is a valid standard
target, although the ebtables tool has already checked it. Kernel need
to check anything from userspace.

If the target was set as an evil value, it would break the ebtables
and cause a panic. Because the non-standard target is treated as one
offset.

Signed-off-by: Gao Feng 
---
 net/bridge/netfilter/ebt_arpreply.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/net/bridge/netfilter/ebt_arpreply.c 
b/net/bridge/netfilter/ebt_arpreply.c
index 5929309..c4886d9 100644
--- a/net/bridge/netfilter/ebt_arpreply.c
+++ b/net/bridge/netfilter/ebt_arpreply.c
@@ -68,6 +68,9 @@ static int ebt_arpreply_tg_check(const struct xt_tgchk_param 
*par)
if (e->ethproto != htons(ETH_P_ARP) ||
e->invflags & EBT_IPROTO)
return -EINVAL;
+   if (INVALID_TARGET)
+   return -EINVAL;
+
return 0;
 }
 
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v6 1/3] netfilter: helper: Rename struct nf_ct_helper_expectfn to nf_ct_nat_helper

2017-05-04 Thread gfree . wind
From: Gao Feng 

Rename struct nf_ct_helper_expectfn to nf_ct_nat_helper, and rename
other functions or variables which refer to it.
The new name is better than the old one.

Signed-off-by: Gao Feng 
---
 v6: Rename the helper name of ftp, tftp.. to ftp-nat-follow-master, per Pablo
 v5: Register one nat_helper for every nat module, per Pablo
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_helper.h | 14 ++---
 net/ipv4/netfilter/nf_nat_h323.c| 12 +--
 net/netfilter/nf_conntrack_helper.c | 32 ++---
 net/netfilter/nf_conntrack_netlink.c| 16 +++
 net/netfilter/nf_nat_core.c |  6 +++---
 net/netfilter/nf_nat_sip.c  |  6 +++---
 6 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index 1eaac1f..d14fe493 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -111,7 +111,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, 
unsigned int protoff,
enum ip_conntrack_info ctinfo,
unsigned int timeout);
 
-struct nf_ct_helper_expectfn {
+struct nf_ct_nat_helper {
struct list_head head;
const char *name;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
@@ -121,12 +121,12 @@ struct nf_ct_helper_expectfn {
 void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
  const char *fmt, ...);
 
-void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
-void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
-struct nf_ct_helper_expectfn *
-nf_ct_helper_expectfn_find_by_name(const char *name);
-struct nf_ct_helper_expectfn *
-nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
+void nf_ct_nat_helper_register(struct nf_ct_nat_helper *n);
+void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n);
+struct nf_ct_nat_helper *
+nf_ct_nat_helper_find_by_name(const char *name);
+struct nf_ct_nat_helper *
+nf_ct_nat_helper_find_by_symbol(const void *symbol);
 
 extern struct hlist_head *nf_ct_helper_hash;
 extern unsigned int nf_ct_helper_hsize;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 574f7eb..346e764 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -567,12 +567,12 @@ static int nat_callforwarding(struct sk_buff *skb, struct 
nf_conn *ct,
return 0;
 }
 
-static struct nf_ct_helper_expectfn q931_nat = {
+static struct nf_ct_nat_helper q931_nat = {
.name   = "Q.931",
.expectfn   = ip_nat_q931_expect,
 };
 
-static struct nf_ct_helper_expectfn callforwarding_nat = {
+static struct nf_ct_nat_helper callforwarding_nat = {
.name   = "callforwarding",
.expectfn   = ip_nat_callforwarding_expect,
 };
@@ -599,8 +599,8 @@ static int __init init(void)
RCU_INIT_POINTER(nat_h245_hook, nat_h245);
RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
RCU_INIT_POINTER(nat_q931_hook, nat_q931);
-   nf_ct_helper_expectfn_register(_nat);
-   nf_ct_helper_expectfn_register(_nat);
+   nf_ct_nat_helper_register(_nat);
+   nf_ct_nat_helper_register(_nat);
return 0;
 }
 
@@ -616,8 +616,8 @@ static void __exit fini(void)
RCU_INIT_POINTER(nat_h245_hook, NULL);
RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
RCU_INIT_POINTER(nat_q931_hook, NULL);
-   nf_ct_helper_expectfn_unregister(_nat);
-   nf_ct_helper_expectfn_unregister(_nat);
+   nf_ct_nat_helper_unregister(_nat);
+   nf_ct_nat_helper_unregister(_nat);
synchronize_rcu();
 }
 
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 99bcd44..1fd739c 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -302,32 +302,32 @@ void nf_ct_helper_destroy(struct nf_conn *ct)
}
 }
 
-static LIST_HEAD(nf_ct_helper_expectfn_list);
+static LIST_HEAD(nf_ct_nat_helper_list);
 
-void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n)
+void nf_ct_nat_helper_register(struct nf_ct_nat_helper *n)
 {
spin_lock_bh(_conntrack_expect_lock);
-   list_add_rcu(>head, _ct_helper_expectfn_list);
+   list_add_rcu(>head, _ct_nat_helper_list);
spin_unlock_bh(_conntrack_expect_lock);
 }
-EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register);
+EXPORT_SYMBOL_GPL(nf_ct_nat_helper_register);
 
-void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
+void 

[PATCH nf v6 3/3] netfilter: nat_helper: Remove the expectations when its module is unloaded

2017-05-04 Thread gfree . wind
From: Gao Feng 

Because the conntrack NAT module could be rmmod anytime, so we should
really leave things in clean state if such thing happens and make sure
we don't leave any packet running over code that will be gone after the
removal.

We only removed the expectations when unregister conntrack helper before.
Actually it is necessary too when remove the nat helper.

Now add one new struct module member "me" in the nf_ct_nat_helper to
represent which module it belongs to.

Signed-off-by: Gao Feng 
---
 v6: Rename the helper name of ftp, tftp.. to ftp-nat-follow-master, per Pablo
 v5: Register one nat_helper for every nat module, per Pablo
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_helper.h |  1 +
 net/ipv4/netfilter/nf_nat_h323.c|  3 ++
 net/netfilter/ipvs/ip_vs_nfct.c |  1 +
 net/netfilter/nf_conntrack_helper.c | 62 +++--
 net/netfilter/nf_conntrack_pptp.c   |  1 +
 net/netfilter/nf_nat_amanda.c   |  1 +
 net/netfilter/nf_nat_core.c |  1 +
 net/netfilter/nf_nat_ftp.c  |  1 +
 net/netfilter/nf_nat_irc.c  |  1 +
 net/netfilter/nf_nat_sip.c  |  1 +
 net/netfilter/nf_nat_tftp.c |  1 +
 11 files changed, 52 insertions(+), 22 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index e8d31ca..d70c5be 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -114,6 +114,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, 
unsigned int protoff,
 struct nf_ct_nat_helper {
struct list_head head;
const char *name;
+   struct module *me;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
 };
 
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index ce2095c..d7b40ac 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -28,16 +28,19 @@ static void ip_nat_callforwarding_expect(struct nf_conn 
*new,
 
 static struct nf_ct_nat_helper q931_nat = {
.name   = "Q.931",
+   .me = THIS_MODULE,
.expectfn   = ip_nat_q931_expect,
 };
 
 static struct nf_ct_nat_helper callforwarding_nat = {
.name   = "callforwarding",
+   .me = THIS_MODULE,
.expectfn   = ip_nat_callforwarding_expect,
 };
 
 static struct nf_ct_nat_helper follow_master_nat = {
.name   = "h323-nat-follow-master",
+   .me = THIS_MODULE,
.expectfn   = nf_nat_follow_master,
 };
 
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
index fc5af4f..d61c236 100644
--- a/net/netfilter/ipvs/ip_vs_nfct.c
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -222,6 +222,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
 
 static struct nf_ct_nat_helper ip_vs_nat = {
.name = "ip-vs-nat",
+   .me = THIS_MODULE,
.expectfn = ip_vs_nfct_expect_callback,
 };
 
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 1fd739c..c12de31 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -130,6 +130,37 @@ static unsigned int helper_hash(const struct 
nf_conntrack_tuple *tuple)
return NULL;
 }
 
+static void
+nf_ct_flush_expect(const struct module *me)
+{
+   struct nf_conntrack_expect *exp;
+   const struct hlist_node *next;
+   u32 i;
+
+   if (!me)
+   return;
+
+   /* Get rid of expectations */
+   spin_lock_bh(_conntrack_expect_lock);
+   for (i = 0; i < nf_ct_expect_hsize; i++) {
+   hlist_for_each_entry_safe(exp, next,
+ _ct_expect_hash[i], hnode) {
+   struct nf_conn_help *master_help = 
nfct_help(exp->master);
+
+   if ((master_help->helper && master_help->helper->me == 
me) ||
+   (exp->helper && exp->helper->me == me) ||
+   (exp->nat_helper && exp->nat_helper->me == me)) {
+   /* This expect belongs to the dying module */
+   if (del_timer(>timeout)) {
+   nf_ct_unlink_expect(exp);
+   nf_ct_expect_put(exp);
+   }
+   }
+   }
+   }
+   spin_unlock_bh(_conntrack_expect_lock);
+}
+
 struct nf_conntrack_helper *
 __nf_conntrack_helper_find(const char *name, u16 l3num, u8 protonum)
 {
@@ -317,6 +348,12 @@ void 

[PATCH nf v6 2/3] netfilter: nat_helper: Register one nf_ct_nat_helper each proto nat module

2017-05-04 Thread gfree . wind
From: Gao Feng 

There are multiple proto nat modules which depend on the follow_master_nat
in the nf_nat_core. When this module is gone, all modules which refers to
it could not work well.

Now register one struct nf_ct_nat_helper in every proto nat module, it makes
sure every nat module could not effect each other, and it is helpful to
maintain the codes. The new nf_ct_nat_helper could be found by ctlink with
its name too, while the original "nat-follow-master" helper is not effected.
ctlink still could specify the "nat-follow-master" for ftp, but recommend
use the ftp's nat_helper "ftp-nat-follow-master" as the ftp nat_helper.

The following are all modifications.
1. Every proto nat module registers one nat_helper at least;
2. Replace the expectfn with nat_helper in the nf_conntrack_expect;
It is used to the latter commit which add the nat_helper module check.
3. Remove nf_ct_nat_helper_find_by_symbol, it is useless now.

Signed-off-by: Gao Feng 
---
 v6: Rename the helper name of ftp, tftp.. to ftp-nat-follow-master, per Pablo
 v5: Register one nat_helper for every nat module, per Pablo
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_expect.h |  5 ++--
 include/net/netfilter/nf_conntrack_helper.h |  2 --
 net/ipv4/netfilter/nf_nat_h323.c| 44 ++---
 net/netfilter/ipvs/ip_vs_nfct.c |  7 -
 net/netfilter/nf_conntrack_broadcast.c  |  2 +-
 net/netfilter/nf_conntrack_core.c   |  4 +--
 net/netfilter/nf_conntrack_expect.c |  2 +-
 net/netfilter/nf_conntrack_netlink.c| 14 -
 net/netfilter/nf_conntrack_pptp.c   | 14 +++--
 net/netfilter/nf_nat_amanda.c   |  9 +-
 net/netfilter/nf_nat_ftp.c  |  9 +-
 net/netfilter/nf_nat_irc.c  |  9 +-
 net/netfilter/nf_nat_sip.c  | 18 ++--
 net/netfilter/nf_nat_tftp.c |  9 +-
 14 files changed, 101 insertions(+), 47 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_expect.h 
b/include/net/netfilter/nf_conntrack_expect.h
index 5ed33ea..f665a6b 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -23,9 +23,8 @@ struct nf_conntrack_expect {
struct nf_conntrack_tuple tuple;
struct nf_conntrack_tuple_mask mask;
 
-   /* Function to call after setup and insertion */
-   void (*expectfn)(struct nf_conn *new,
-struct nf_conntrack_expect *this);
+   /* Expectation function owner */
+   struct nf_ct_nat_helper *nat_helper;
 
/* Helper to assign to new connection */
struct nf_conntrack_helper *helper;
diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index d14fe493..e8d31ca 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -125,8 +125,6 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct 
nf_conn *ct,
 void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n);
 struct nf_ct_nat_helper *
 nf_ct_nat_helper_find_by_name(const char *name);
-struct nf_ct_nat_helper *
-nf_ct_nat_helper_find_by_symbol(const void *symbol);
 
 extern struct hlist_head *nf_ct_helper_hash;
 extern unsigned int nf_ct_helper_hsize;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 346e764..ce2095c 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -21,6 +21,26 @@
 #include 
 
 //
+static void ip_nat_q931_expect(struct nf_conn *new,
+  struct nf_conntrack_expect *this);
+static void ip_nat_callforwarding_expect(struct nf_conn *new,
+struct nf_conntrack_expect *this);
+
+static struct nf_ct_nat_helper q931_nat = {
+   .name   = "Q.931",
+   .expectfn   = ip_nat_q931_expect,
+};
+
+static struct nf_ct_nat_helper callforwarding_nat = {
+   .name   = "callforwarding",
+   .expectfn   = ip_nat_callforwarding_expect,
+};
+
+static struct nf_ct_nat_helper follow_master_nat = {
+   .name   = "h323-nat-follow-master",
+   .expectfn   = nf_nat_follow_master,
+};
+
 static int set_addr(struct sk_buff *skb, unsigned int protoff,
unsigned char **data, int dataoff,
unsigned int addroff, __be32 ip, __be16 port)
@@ -187,10 +207,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct 
nf_conn *ct,
 
/* Set expectations for NAT */
rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
-   

[PATCH nf-next v3] netfilter: SYNPROXY: Return NF_STOLEN instead of NF_DROP during handshaking

2017-04-20 Thread gfree . wind
From: Gao Feng 

Current SYNPROXY codes return NF_DROP during normal TCP handshaking,
it is not friendly to caller. Because the nf_hook_slow would treat
the NF_DROP as an error, and return -EPERM.
As a result, it may cause the top caller think it meets one error.

For example, the following codes are from cfv_rx_poll()
err = netif_receive_skb(skb);
if (unlikely(err)) {
++cfv->ndev->stats.rx_dropped;
} else {
++cfv->ndev->stats.rx_packets;
cfv->ndev->stats.rx_bytes += skb_len;
}
When SYNPROXY returns NF_DROP, then netif_receive_skb returns -EPERM.
As a result, the cfv driver would treat it as an error, and increase
the rx_dropped counter.

So use NF_STOLEN instead of NF_DROP now because there is no error
happened indeed, and free the skb directly.

Signed-off-by: Gao Feng 
---
 v2: Add more comments
 v2: Add the check for synproxy_recv_client_ack, per Gao Feng,
 v1: initial version

 net/ipv4/netfilter/ipt_SYNPROXY.c  | 21 ++---
 net/ipv6/netfilter/ip6t_SYNPROXY.c | 20 ++--
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c 
b/net/ipv4/netfilter/ipt_SYNPROXY.c
index 3240a26..ab0f576 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -293,12 +293,16 @@
  XT_SYNPROXY_OPT_ECN);
 
synproxy_send_client_synack(net, skb, th, );
-   return NF_DROP;
-
+   consume_skb(skb);
+   return NF_STOLEN;
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
-   synproxy_recv_client_ack(net, skb, th, , ntohl(th->seq));
-   return NF_DROP;
+   if (synproxy_recv_client_ack(net, skb, th, , 
ntohl(th->seq))) {
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
return XT_CONTINUE;
@@ -367,10 +371,13 @@ static unsigned int ipv4_synproxy_hook(void *priv,
 * number match the one of first SYN.
 */
if (synproxy_recv_client_ack(net, skb, th, ,
-ntohl(th->seq) + 1))
+ntohl(th->seq) + 1)) {
this_cpu_inc(snet->stats->cookie_retrans);
-
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
synproxy->isn = ntohl(th->ack_seq);
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c 
b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 4ef1ddd..6a4f49e 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -307,12 +307,17 @@
  XT_SYNPROXY_OPT_ECN);
 
synproxy_send_client_synack(net, skb, th, );
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
 
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
-   synproxy_recv_client_ack(net, skb, th, , ntohl(th->seq));
-   return NF_DROP;
+   if (synproxy_recv_client_ack(net, skb, th, , 
ntohl(th->seq))) {
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
return XT_CONTINUE;
@@ -388,10 +393,13 @@ static unsigned int ipv6_synproxy_hook(void *priv,
 * number match the one of first SYN.
 */
if (synproxy_recv_client_ack(net, skb, th, ,
-ntohl(th->seq) + 1))
+ntohl(th->seq) + 1)) {
this_cpu_inc(snet->stats->cookie_retrans);
-
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
synproxy->isn = ntohl(th->ack_seq);
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next] netfilter: tcp: Use TCP_MAX_WSCALE instead of literal 14

2017-04-18 Thread gfree . wind
From: Gao Feng 

The window scale may be enlarged from 14 to 15 according to the itef
draft https://tools.ietf.org/html/draft-nishida-tcpm-maxwin-03.

Use the macro TCP_MAX_WSCALE to support it easily with TCP stack in
the future.

Signed-off-by: Gao Feng 
---
 net/netfilter/nf_conntrack_proto_tcp.c | 7 +++
 net/netfilter/nf_synproxy_core.c   | 4 ++--
 2 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nf_conntrack_proto_tcp.c 
b/net/netfilter/nf_conntrack_proto_tcp.c
index b122e9d..741acdc 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -419,10 +419,9 @@ static void tcp_options(const struct sk_buff *skb,
 && opsize == TCPOLEN_WINDOW) {
state->td_scale = *(u_int8_t *)ptr;
 
-   if (state->td_scale > 14) {
-   /* See RFC1323 */
-   state->td_scale = 14;
-   }
+   if (state->td_scale > TCP_MAX_WSCALE)
+   state->td_scale = TCP_MAX_WSCALE;
+
state->flags |=
IP_CT_TCP_FLAG_WINDOW_SCALE;
}
diff --git a/net/netfilter/nf_synproxy_core.c b/net/netfilter/nf_synproxy_core.c
index abe03e8..a504e87 100644
--- a/net/netfilter/nf_synproxy_core.c
+++ b/net/netfilter/nf_synproxy_core.c
@@ -66,8 +66,8 @@
case TCPOPT_WINDOW:
if (opsize == TCPOLEN_WINDOW) {
opts->wscale = *ptr;
-   if (opts->wscale > 14)
-   opts->wscale = 14;
+   if (opts->wscale > TCP_MAX_WSCALE)
+   opts->wscale = TCP_MAX_WSCALE;
opts->options |= XT_SYNPROXY_OPT_WSCALE;
}
break;
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v3] netfilter: xt_CT: fix refcnt leak on error path

2017-04-13 Thread gfree . wind
From: Gao Feng 

There are two cases which causes refcnt leak.

1. When nf_ct_timeout_ext_add failed in xt_ct_set_timeout, it should
free the timeout refcnt.
Now goto the err_put_timeout error handler instead of going ahead.

2. When the time policy is not found, we should call module_put.
Otherwise, the related cthelper module cannot be removed anymore.
It is easy to reproduce by typing the following command:
  # iptables -t raw -A OUTPUT -p tcp -j CT --helper ftp --timeout xxx

Signed-off-by: Gao Feng 
Signed-off-by: Liping Zhang 
---
 v3: Merge the patch of Liping together
 v2: enhance the patch
 v1: initial version

 net/netfilter/xt_CT.c | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index b008db0..81fdcdc 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -167,8 +167,10 @@ static void __xt_ct_tg_timeout_put(struct ctnl_timeout 
*timeout)
goto err_put_timeout;
}
timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
-   if (timeout_ext == NULL)
+   if (!timeout_ext) {
ret = -ENOMEM;
+   goto err_put_timeout;
+   }
 
rcu_read_unlock();
return ret;
@@ -200,6 +202,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
  struct xt_ct_target_info_v1 *info)
 {
struct nf_conntrack_zone zone;
+   struct nf_conn_help *help;
struct nf_conn *ct;
int ret = -EOPNOTSUPP;
 
@@ -248,7 +251,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
if (info->timeout[0]) {
ret = xt_ct_set_timeout(ct, par, info->timeout);
if (ret < 0)
-   goto err3;
+   goto err4;
}
__set_bit(IPS_CONFIRMED_BIT, >status);
nf_conntrack_get(>ct_general);
@@ -256,6 +259,10 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
info->ct = ct;
return 0;
 
+err4:
+   help = nfct_help(ct);
+   if (help)
+   module_put(help->helper->me);
 err3:
nf_ct_tmpl_free(ct);
 err2:
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v2] netfilter: cttimeout: Fix one possible use-after-free issue

2017-04-13 Thread gfree . wind
From: Gao Feng 

The function ctnl_untimeout is used to untimeout every conntrack
which is using the timeout. But it is necessary to add one barrier
synchronize_rcu because of racing. Maybe one conntrack has already
owned this timeout, but it is not inserted into unconfirmed list or
the hash list, when ctnl_untimeout untimeout the conntracks

Let me describe it with a call path
CPU1CPU2
alloc new conn
add timeout ext
ctnl_timeout_try_del
untimeout all conns in list
kfree_rcu.
conn is confirmed.

As the show above, when cpu2 untimeout all conns in list and the new
conn of cpu1 is not confirmed, the new conn still owns the timeout
pointer. After the timeout mem is freed really, it points to one
invalid mem.

Signed-off-by: Gao Feng 
---
 v2: Add the call path in the comment
 v1: initial version

 net/netfilter/nfnetlink_cttimeout.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nfnetlink_cttimeout.c 
b/net/netfilter/nfnetlink_cttimeout.c
index 47d6656..af0cc87 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -304,6 +304,11 @@ static void ctnl_untimeout(struct net *net, struct 
ctnl_timeout *timeout)
spinlock_t *lock;
int i, cpu;
 
+   /* Make sure the conntrack using the timeout already in the unconfirmed
+* list or in the hash table.
+*/
+   synchronize_rcu();
+
for_each_possible_cpu(cpu) {
struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
 
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf 1/1] netfilter: nf_nat: Fix return NF_DROP in nfnetlink_parse_nat_setup

2017-04-12 Thread gfree . wind
From: Gao Feng 

The __nf_nat_alloc_null_binding invokes nf_nat_setup_info which may
return NF_DROP when memory is exhausted, so convert NF_DROP to -ENOMEM
to make ctnetlink happy. Or ctnetlink_setup_nat treats it as a success
when one error NF_DROP happens actully.

Signed-off-by: Gao Feng 
---
 net/netfilter/nf_nat_core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 82802e4..55746cd 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -819,7 +819,7 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr,
 
/* No NAT information has been passed, allocate the null-binding */
if (attr == NULL)
-   return __nf_nat_alloc_null_binding(ct, manip);
+   return __nf_nat_alloc_null_binding(ct, manip) == NF_DROP ? 
-ENOMEM : 0;
 
err = nfnetlink_parse_nat(attr, ct, , l3proto);
if (err < 0)
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next v2 1/1] netfilter: SYNPROXY: Return NF_STOLEN instead of NF_DROP during handshaking

2017-04-11 Thread gfree . wind
From: Gao Feng 

Current SYNPROXY codes return NF_DROP during normal TCP handshaking,
it is not friendly to caller. Because the nf_hook_slow would treat
the NF_DROP as an error, and return -EPERM.
As a result, it may cause the top caller think it meets one error.

So use NF_STOLEN instead of NF_DROP now because there is no error
happened indeed, and free the skb directly.

Signed-off-by: Gao Feng 
---
 v2: Add the check for synproxy_recv_client_ack, per Gao Feng,
 v1: initial version

 net/ipv4/netfilter/ipt_SYNPROXY.c  | 21 ++---
 net/ipv6/netfilter/ip6t_SYNPROXY.c | 20 ++--
 2 files changed, 28 insertions(+), 13 deletions(-)

diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c 
b/net/ipv4/netfilter/ipt_SYNPROXY.c
index 3240a26..ab0f576 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -293,12 +293,16 @@
  XT_SYNPROXY_OPT_ECN);
 
synproxy_send_client_synack(net, skb, th, );
-   return NF_DROP;
-
+   consume_skb(skb);
+   return NF_STOLEN;
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
-   synproxy_recv_client_ack(net, skb, th, , ntohl(th->seq));
-   return NF_DROP;
+   if (synproxy_recv_client_ack(net, skb, th, , 
ntohl(th->seq))) {
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
return XT_CONTINUE;
@@ -367,10 +371,13 @@ static unsigned int ipv4_synproxy_hook(void *priv,
 * number match the one of first SYN.
 */
if (synproxy_recv_client_ack(net, skb, th, ,
-ntohl(th->seq) + 1))
+ntohl(th->seq) + 1)) {
this_cpu_inc(snet->stats->cookie_retrans);
-
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
synproxy->isn = ntohl(th->ack_seq);
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c 
b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 4ef1ddd..6a4f49e 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -307,12 +307,17 @@
  XT_SYNPROXY_OPT_ECN);
 
synproxy_send_client_synack(net, skb, th, );
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
 
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
-   synproxy_recv_client_ack(net, skb, th, , ntohl(th->seq));
-   return NF_DROP;
+   if (synproxy_recv_client_ack(net, skb, th, , 
ntohl(th->seq))) {
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
return XT_CONTINUE;
@@ -388,10 +393,13 @@ static unsigned int ipv6_synproxy_hook(void *priv,
 * number match the one of first SYN.
 */
if (synproxy_recv_client_ack(net, skb, th, ,
-ntohl(th->seq) + 1))
+ntohl(th->seq) + 1)) {
this_cpu_inc(snet->stats->cookie_retrans);
-
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
+   } else {
+   return NF_DROP;
+   }
}
 
synproxy->isn = ntohl(th->ack_seq);
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next 1/1] netfilter: SYNPROXY: Return NF_STOLEN instead of NF_DROP during handshaking

2017-04-10 Thread gfree . wind
From: Gao Feng 

Current SYNPROXY codes return NF_DROP during normal TCP handshaking,
it is not friendly to caller. Because the nf_hook_slow would treat
the NF_DROP as an error, and return -EPERM.
As a result, it may cause the top caller think it meets one error.

So use NF_STOLEN instead of NF_DROP now because there is no error
happened indeed, and free the skb directly.

Signed-off-by: Gao Feng 
---
 net/ipv4/netfilter/ipt_SYNPROXY.c  | 7 ---
 net/ipv6/netfilter/ip6t_SYNPROXY.c | 6 --
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/netfilter/ipt_SYNPROXY.c 
b/net/ipv4/netfilter/ipt_SYNPROXY.c
index 3240a26..9ed80d4 100644
--- a/net/ipv4/netfilter/ipt_SYNPROXY.c
+++ b/net/ipv4/netfilter/ipt_SYNPROXY.c
@@ -293,12 +293,13 @@
  XT_SYNPROXY_OPT_ECN);
 
synproxy_send_client_synack(net, skb, th, );
-   return NF_DROP;
-
+   consume_skb(skb);
+   return NF_STOLEN;
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
synproxy_recv_client_ack(net, skb, th, , ntohl(th->seq));
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
}
 
return XT_CONTINUE;
diff --git a/net/ipv6/netfilter/ip6t_SYNPROXY.c 
b/net/ipv6/netfilter/ip6t_SYNPROXY.c
index 4ef1ddd..d5d5725 100644
--- a/net/ipv6/netfilter/ip6t_SYNPROXY.c
+++ b/net/ipv6/netfilter/ip6t_SYNPROXY.c
@@ -307,12 +307,14 @@
  XT_SYNPROXY_OPT_ECN);
 
synproxy_send_client_synack(net, skb, th, );
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
 
} else if (th->ack && !(th->fin || th->rst || th->syn)) {
/* ACK from client */
synproxy_recv_client_ack(net, skb, th, , ntohl(th->seq));
-   return NF_DROP;
+   consume_skb(skb);
+   return NF_STOLEN;
}
 
return XT_CONTINUE;
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf 1/1] netfilter: seqadj: Fix possible non-linear data access for TCP header

2017-04-10 Thread gfree . wind
From: Gao Feng 

The current call path of nf_ct_tcp_seqadj_set is the following.

nfqnl_recv_verdict->ctnetlink_glue_hook->ctnetlink_glue_seqadj
->nf_ct_tcp_seqadj_set.

It couldn't make sure the TCP header is in the linear data part.
So use the skb_header_pointer instead of the current codes.

BTW, the nf_ct_tcp_seqadj_set is one external function of netfilter
which works in the network layer, it should not assume the transport
header is in the linear data.

Signed-off-by: Gao Feng 
---
 net/netfilter/nf_conntrack_seqadj.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/nf_conntrack_seqadj.c 
b/net/netfilter/nf_conntrack_seqadj.c
index ef7063e..80394ab 100644
--- a/net/netfilter/nf_conntrack_seqadj.c
+++ b/net/netfilter/nf_conntrack_seqadj.c
@@ -61,11 +61,14 @@ void nf_ct_tcp_seqadj_set(struct sk_buff *skb,
  s32 off)
 {
const struct tcphdr *th;
+   struct tcphdr tcph;
 
if (nf_ct_protonum(ct) != IPPROTO_TCP)
return;
 
-   th = (struct tcphdr *)(skb_network_header(skb) + ip_hdrlen(skb));
+   th = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(tcph), );
+   if (!th)
+   return;
nf_ct_seqadj_set(ct, ctinfo, th->seq, off);
 }
 EXPORT_SYMBOL_GPL(nf_ct_tcp_seqadj_set);
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next 1/1] netfilter: cttimeout: Refine cttimeout_del_timeout

2017-04-07 Thread gfree . wind
From: Gao Feng 

1. Return one error when try to delete all timeouts and meet one erorr;
2. Delete the condition block when fail to delete specified timeout.
It is more clear that it would stop the loop when find one matched timeout.

Signed-off-by: Gao Feng 
---
 net/netfilter/nfnetlink_cttimeout.c | 15 +--
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/net/netfilter/nfnetlink_cttimeout.c 
b/net/netfilter/nfnetlink_cttimeout.c
index baa75f3..220847a 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -361,11 +361,17 @@ static int cttimeout_del_timeout(struct net *net, struct 
sock *ctnl,
char *name;
 
if (!cda[CTA_TIMEOUT_NAME]) {
+   int cur_ret;
+
+   ret = 0;
list_for_each_entry_safe(cur, tmp, >nfct_timeout_list,
-head)
-   ctnl_timeout_try_del(net, cur);
+head) {
+   cur_ret = ctnl_timeout_try_del(net, cur);
+   if (cur_ret && !ret)
+   ret = cur_ret;
+   }
 
-   return 0;
+   return ret;
}
name = nla_data(cda[CTA_TIMEOUT_NAME]);
 
@@ -374,9 +380,6 @@ static int cttimeout_del_timeout(struct net *net, struct 
sock *ctnl,
continue;
 
ret = ctnl_timeout_try_del(net, cur);
-   if (ret < 0)
-   return ret;
-
break;
}
return ret;
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v2 1/1] netfilter: xt_CT: Fix one possible memleak of timeout

2017-04-06 Thread gfree . wind
From: Gao Feng 

When nf_ct_timeout_ext_add failed in xt_ct_set_timeout, it should
free the timeout refcnt.

Now goto the err_put_timeout error handler instead of going ahead.

Signed-off-by: Gao Feng 
---
 v2: Keep the ret = -ENOMEM, per Gao Feng
 v1: initial version

 net/netfilter/xt_CT.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index b008db0..a1783b6 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -167,8 +167,10 @@ static void __xt_ct_tg_timeout_put(struct ctnl_timeout 
*timeout)
goto err_put_timeout;
}
timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
-   if (timeout_ext == NULL)
+   if (!timeout_ext) {
ret = -ENOMEM;
+   goto err_put_timeout;
+   }
 
rcu_read_unlock();
return ret;
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next 1/1] netfilter: cttimeout: Return -EOPNOTSUPP if l4proto doesn't support

2017-04-06 Thread gfree . wind
From: Gao Feng 

Return -EOPNOTSUPP instead of success when l4proto doesn't support
set the timeout attribute.

It is better to return error when fail to set timeout.

Signed-off-by: Gao Feng 
---
 net/netfilter/nfnetlink_cttimeout.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/nfnetlink_cttimeout.c 
b/net/netfilter/nfnetlink_cttimeout.c
index baa75f3..0b12e8c6 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -50,7 +50,7 @@
 ctnl_timeout_parse_policy(void *timeouts, struct nf_conntrack_l4proto *l4proto,
  struct net *net, const struct nlattr *attr)
 {
-   int ret = 0;
+   int ret = -EOPNOTSUPP;
 
if (likely(l4proto->ctnl_timeout.nlattr_to_obj)) {
struct nlattr *tb[l4proto->ctnl_timeout.nlattr_max+1];
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf 1/1] netfilter: cttimeout: Fix one possible use-after-free issue

2017-04-06 Thread gfree . wind
From: Gao Feng 

The function ctnl_untimeout is used to untimeout every conntrack
which is using the timeout. But it is necessary to add one barrier
synchronize_rcu because of racing. Maybe one conntrack has already
owned this timeout, but it is not inserted into unconfirmed list or
the hash list, when ctnl_untimeout untimeout the conntracks

Signed-off-by: Gao Feng 
---
 net/netfilter/nfnetlink_cttimeout.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/net/netfilter/nfnetlink_cttimeout.c 
b/net/netfilter/nfnetlink_cttimeout.c
index 47d6656..af0cc87 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -304,6 +304,11 @@ static void ctnl_untimeout(struct net *net, struct 
ctnl_timeout *timeout)
spinlock_t *lock;
int i, cpu;
 
+   /* Make sure the conntrack using the timeout already in the unconfirmed
+* list or in the hash table.
+*/
+   synchronize_rcu();
+
for_each_possible_cpu(cpu) {
struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu);
 
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf 1/1] netfilter: xt_CT: Fix one possible memleak of timeout

2017-04-06 Thread gfree . wind
From: Gao Feng 

When nf_ct_timeout_ext_add failed in xt_ct_set_timeout, it should
free the timeout refcnt.

Now goto the err_put_timeout error handler instead of going ahead.

Signed-off-by: Gao Feng 
---
 net/netfilter/xt_CT.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index b008db0..3cd812c 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -168,7 +168,7 @@ static void __xt_ct_tg_timeout_put(struct ctnl_timeout 
*timeout)
}
timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC);
if (timeout_ext == NULL)
-   ret = -ENOMEM;
+   goto err_put_timeout;
 
rcu_read_unlock();
return ret;
-- 
1.9.1


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf 1/1] netfilter: CLUSTERIP: Fix one wrong refcnt usage

2017-04-05 Thread gfree . wind
From: Gao Feng 

Current codes invoke wrongly nf_ct_netns_get in the destroy routine,
it should use nf_ct_netns_put, not nf_ct_netns_get.
It could cause some modules could not be unloaded.

Signed-off-by: Gao Feng 
---
 net/ipv4/netfilter/ipt_CLUSTERIP.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/netfilter/ipt_CLUSTERIP.c 
b/net/ipv4/netfilter/ipt_CLUSTERIP.c
index 52f2645..9b88413 100644
--- a/net/ipv4/netfilter/ipt_CLUSTERIP.c
+++ b/net/ipv4/netfilter/ipt_CLUSTERIP.c
@@ -461,7 +461,7 @@ static void clusterip_tg_destroy(const struct 
xt_tgdtor_param *par)
 
clusterip_config_put(cipinfo->config);
 
-   nf_ct_netns_get(par->net, par->family);
+   nf_ct_netns_put(par->net, par->family);
 }
 
 #ifdef CONFIG_COMPAT
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next 1/1] netfilter: Remove useless variable timeouts in init_conntrack

2017-04-04 Thread gfree . wind
From: Gao Feng 

All l4_proto->new callbacks don't use the param timeouts currently,
so remove it from param list. Then the variable timeouts isn't used
as right value in init_conntrack, so remove it too.

Signed-off-by: Gao Feng 
---
 include/net/netfilter/nf_conntrack_l4proto.h |  2 +-
 net/ipv4/netfilter/nf_conntrack_proto_icmp.c |  2 +-
 net/netfilter/nf_conntrack_core.c| 13 ++---
 net/netfilter/nf_conntrack_proto_dccp.c  |  2 +-
 net/netfilter/nf_conntrack_proto_sctp.c  |  2 +-
 net/netfilter/nf_conntrack_proto_tcp.c   |  2 +-
 net/netfilter/nf_conntrack_proto_udp.c   |  2 +-
 7 files changed, 8 insertions(+), 17 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_l4proto.h 
b/include/net/netfilter/nf_conntrack_l4proto.h
index 85e993e..fafe65a 100644
--- a/include/net/netfilter/nf_conntrack_l4proto.h
+++ b/include/net/netfilter/nf_conntrack_l4proto.h
@@ -49,7 +49,7 @@ struct nf_conntrack_l4proto {
/* Called when a new connection for this protocol found;
 * returns TRUE if it's OK.  If so, packet() called next. */
bool (*new)(struct nf_conn *ct, const struct sk_buff *skb,
-   unsigned int dataoff, unsigned int *timeouts);
+   unsigned int dataoff);
 
/* Called when a conntrack entry is destroyed */
void (*destroy)(struct nf_conn *ct);
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c 
b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
index 73c591d..5bb8c12 100644
--- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
+++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c
@@ -105,7 +105,7 @@ static int icmp_packet(struct nf_conn *ct,
 
 /* Called when a new connection for this protocol found. */
 static bool icmp_new(struct nf_conn *ct, const struct sk_buff *skb,
-unsigned int dataoff, unsigned int *timeouts)
+unsigned int dataoff)
 {
static const u_int8_t valid_new[] = {
[ICMP_ECHO] = 1,
diff --git a/net/netfilter/nf_conntrack_core.c 
b/net/netfilter/nf_conntrack_core.c
index b0f2e8e..1fac417 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1145,7 +1145,6 @@ void nf_conntrack_free(struct nf_conn *ct)
const struct nf_conntrack_zone *zone;
struct nf_conn_timeout *timeout_ext;
struct nf_conntrack_zone tmp;
-   unsigned int *timeouts;
 
if (!nf_ct_invert_tuple(_tuple, tuple, l3proto, l4proto)) {
pr_debug("Can't invert tuple.\n");
@@ -1163,21 +1162,13 @@ void nf_conntrack_free(struct nf_conn *ct)
return ERR_PTR(-ENOMEM);
}
 
-   timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL;
-   if (timeout_ext) {
-   timeouts = nf_ct_timeout_data(timeout_ext);
-   if (unlikely(!timeouts))
-   timeouts = l4proto->get_timeouts(net);
-   } else {
-   timeouts = l4proto->get_timeouts(net);
-   }
-
-   if (!l4proto->new(ct, skb, dataoff, timeouts)) {
+   if (!l4proto->new(ct, skb, dataoff)) {
nf_conntrack_free(ct);
pr_debug("can't track with proto module\n");
return NULL;
}
 
+   timeout_ext = tmpl ? nf_ct_timeout_find(tmpl) : NULL;
if (timeout_ext)
nf_ct_timeout_ext_add(ct, rcu_dereference(timeout_ext->timeout),
  GFP_ATOMIC);
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c 
b/net/netfilter/nf_conntrack_proto_dccp.c
index 93dd1c5..52f2ce4 100644
--- a/net/netfilter/nf_conntrack_proto_dccp.c
+++ b/net/netfilter/nf_conntrack_proto_dccp.c
@@ -412,7 +412,7 @@ static bool dccp_invert_tuple(struct nf_conntrack_tuple 
*inv,
 }
 
 static bool dccp_new(struct nf_conn *ct, const struct sk_buff *skb,
-unsigned int dataoff, unsigned int *timeouts)
+unsigned int dataoff)
 {
struct net *net = nf_ct_net(ct);
struct nf_dccp_net *dn;
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c 
b/net/netfilter/nf_conntrack_proto_sctp.c
index 33279aa..102ab80 100644
--- a/net/netfilter/nf_conntrack_proto_sctp.c
+++ b/net/netfilter/nf_conntrack_proto_sctp.c
@@ -432,7 +432,7 @@ static int sctp_packet(struct nf_conn *ct,
 
 /* Called when a new connection for this protocol found. */
 static bool sctp_new(struct nf_conn *ct, const struct sk_buff *skb,
-unsigned int dataoff, unsigned int *timeouts)
+unsigned int dataoff)
 {
enum sctp_conntrack new_state;
const struct sctphdr *sh;
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c 
b/net/netfilter/nf_conntrack_proto_tcp.c
index b122e9d..aebaf7d 100644
--- a/net/netfilter/nf_conntrack_proto_tcp.c
+++ b/net/netfilter/nf_conntrack_proto_tcp.c
@@ -1098,7 +1098,7 @@ static int tcp_packet(struct nf_conn *ct,
 
 /* Called when a new connection for this protocol found. */

[PATCH nf-next 1/1] netfilter: udplite4: Remove duplicated udplite4 declaration

2017-04-04 Thread gfree . wind
From: Gao Feng 

There are two nf_conntrack_l4proto_udp4 declarations in the head file
nf_conntrack_ipv4.h. Now remove one which is not enbraced by the macro
CONFIG_NF_CT_PROTO_UDPLITE.

Signed-off-by: Gao Feng 
---
 include/net/netfilter/ipv4/nf_conntrack_ipv4.h | 1 -
 1 file changed, 1 deletion(-)

diff --git a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h 
b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
index 6ff3281..919e4e8 100644
--- a/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
+++ b/include/net/netfilter/ipv4/nf_conntrack_ipv4.h
@@ -14,7 +14,6 @@
 
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_tcp4;
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udp4;
-extern struct nf_conntrack_l4proto nf_conntrack_l4proto_udplite4;
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp;
 #ifdef CONFIG_NF_CT_PROTO_DCCP
 extern struct nf_conntrack_l4proto nf_conntrack_l4proto_dccp4;
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v5 2/3] netfilter: nat_helper: Make sure every proto nat module uses its nat_helper

2017-03-31 Thread gfree . wind
From: Gao Feng 

Make sure every proto nat module owns one struct nat_helper at least,
and it only uses its nat_helper.

1. Every proto nat module registers one nat_helper at least;
2. Replace the expectfn with nat_helper in the nf_conntrack_expect;
It is helpful to maintain the nat_helper codes
3. Make sure the nat module only uses its nat_helper;
4. Remove nf_ct_nat_helper_find_by_symbol, it is useless now.

Signed-off-by: Gao Feng 
---
 v5: Register one nat_helper for every nat module, per Pablo
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_expect.h |  5 ++--
 include/net/netfilter/nf_conntrack_helper.h |  2 --
 net/ipv4/netfilter/nf_nat_h323.c| 44 ++---
 net/netfilter/ipvs/ip_vs_nfct.c |  7 -
 net/netfilter/nf_conntrack_broadcast.c  |  2 +-
 net/netfilter/nf_conntrack_core.c   |  4 +--
 net/netfilter/nf_conntrack_expect.c |  2 +-
 net/netfilter/nf_conntrack_netlink.c| 14 -
 net/netfilter/nf_conntrack_pptp.c   | 14 +++--
 net/netfilter/nf_nat_amanda.c   |  9 +-
 net/netfilter/nf_nat_ftp.c  |  9 +-
 net/netfilter/nf_nat_irc.c  |  9 +-
 net/netfilter/nf_nat_sip.c  | 18 ++--
 net/netfilter/nf_nat_tftp.c |  9 +-
 14 files changed, 101 insertions(+), 47 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_expect.h 
b/include/net/netfilter/nf_conntrack_expect.h
index 5ed33ea..f665a6b 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -23,9 +23,8 @@ struct nf_conntrack_expect {
struct nf_conntrack_tuple tuple;
struct nf_conntrack_tuple_mask mask;
 
-   /* Function to call after setup and insertion */
-   void (*expectfn)(struct nf_conn *new,
-struct nf_conntrack_expect *this);
+   /* Expectation function owner */
+   struct nf_ct_nat_helper *nat_helper;
 
/* Helper to assign to new connection */
struct nf_conntrack_helper *helper;
diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index d14fe493..e8d31ca 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -125,8 +125,6 @@ void nf_ct_helper_log(struct sk_buff *skb, const struct 
nf_conn *ct,
 void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n);
 struct nf_ct_nat_helper *
 nf_ct_nat_helper_find_by_name(const char *name);
-struct nf_ct_nat_helper *
-nf_ct_nat_helper_find_by_symbol(const void *symbol);
 
 extern struct hlist_head *nf_ct_helper_hash;
 extern unsigned int nf_ct_helper_hsize;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 346e764..9101c48 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -21,6 +21,26 @@
 #include 
 
 //
+static void ip_nat_q931_expect(struct nf_conn *new,
+  struct nf_conntrack_expect *this);
+static void ip_nat_callforwarding_expect(struct nf_conn *new,
+struct nf_conntrack_expect *this);
+
+static struct nf_ct_nat_helper q931_nat = {
+   .name   = "Q.931",
+   .expectfn   = ip_nat_q931_expect,
+};
+
+static struct nf_ct_nat_helper callforwarding_nat = {
+   .name   = "callforwarding",
+   .expectfn   = ip_nat_callforwarding_expect,
+};
+
+static struct nf_ct_nat_helper follow_master_nat = {
+   .name   = "h323_follow_master",
+   .expectfn   = nf_nat_follow_master,
+};
+
 static int set_addr(struct sk_buff *skb, unsigned int protoff,
unsigned char **data, int dataoff,
unsigned int addroff, __be32 ip, __be16 port)
@@ -187,10 +207,10 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct 
nf_conn *ct,
 
/* Set expectations for NAT */
rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
-   rtp_exp->expectfn = nf_nat_follow_master;
+   rtp_exp->nat_helper = _master_nat;
rtp_exp->dir = !dir;
rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
-   rtcp_exp->expectfn = nf_nat_follow_master;
+   rtcp_exp->nat_helper = _master_nat;
rtcp_exp->dir = !dir;
 
/* Lookup existing expects */
@@ -289,7 +309,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
 
/* Set expectations for NAT */
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
-   exp->expectfn = nf_nat_follow_master;
+   exp->nat_helper = _master_nat;

[PATCH nf v5 1/3] netfilter: helper: Rename struct nf_ct_helper_expectfn to nf_ct_nat_helper

2017-03-31 Thread gfree . wind
From: Gao Feng 

Rename struct nf_ct_helper_expectfn to nf_ct_nat_helper, and rename
other functions or variables which refer to it.
The new name is better than the old one.

Signed-off-by: Gao Feng 
---
 v5: Register one nat_helper for every nat module, per Pablo
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_helper.h | 14 ++---
 net/ipv4/netfilter/nf_nat_h323.c| 12 +--
 net/netfilter/nf_conntrack_helper.c | 32 ++---
 net/netfilter/nf_conntrack_netlink.c| 16 +++
 net/netfilter/nf_nat_core.c |  6 +++---
 net/netfilter/nf_nat_sip.c  |  6 +++---
 6 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index 1eaac1f..d14fe493 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -111,7 +111,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, 
unsigned int protoff,
enum ip_conntrack_info ctinfo,
unsigned int timeout);
 
-struct nf_ct_helper_expectfn {
+struct nf_ct_nat_helper {
struct list_head head;
const char *name;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
@@ -121,12 +121,12 @@ struct nf_ct_helper_expectfn {
 void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
  const char *fmt, ...);
 
-void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
-void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
-struct nf_ct_helper_expectfn *
-nf_ct_helper_expectfn_find_by_name(const char *name);
-struct nf_ct_helper_expectfn *
-nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
+void nf_ct_nat_helper_register(struct nf_ct_nat_helper *n);
+void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n);
+struct nf_ct_nat_helper *
+nf_ct_nat_helper_find_by_name(const char *name);
+struct nf_ct_nat_helper *
+nf_ct_nat_helper_find_by_symbol(const void *symbol);
 
 extern struct hlist_head *nf_ct_helper_hash;
 extern unsigned int nf_ct_helper_hsize;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 574f7eb..346e764 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -567,12 +567,12 @@ static int nat_callforwarding(struct sk_buff *skb, struct 
nf_conn *ct,
return 0;
 }
 
-static struct nf_ct_helper_expectfn q931_nat = {
+static struct nf_ct_nat_helper q931_nat = {
.name   = "Q.931",
.expectfn   = ip_nat_q931_expect,
 };
 
-static struct nf_ct_helper_expectfn callforwarding_nat = {
+static struct nf_ct_nat_helper callforwarding_nat = {
.name   = "callforwarding",
.expectfn   = ip_nat_callforwarding_expect,
 };
@@ -599,8 +599,8 @@ static int __init init(void)
RCU_INIT_POINTER(nat_h245_hook, nat_h245);
RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
RCU_INIT_POINTER(nat_q931_hook, nat_q931);
-   nf_ct_helper_expectfn_register(_nat);
-   nf_ct_helper_expectfn_register(_nat);
+   nf_ct_nat_helper_register(_nat);
+   nf_ct_nat_helper_register(_nat);
return 0;
 }
 
@@ -616,8 +616,8 @@ static void __exit fini(void)
RCU_INIT_POINTER(nat_h245_hook, NULL);
RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
RCU_INIT_POINTER(nat_q931_hook, NULL);
-   nf_ct_helper_expectfn_unregister(_nat);
-   nf_ct_helper_expectfn_unregister(_nat);
+   nf_ct_nat_helper_unregister(_nat);
+   nf_ct_nat_helper_unregister(_nat);
synchronize_rcu();
 }
 
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..0eaa01e 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -293,32 +293,32 @@ void nf_ct_helper_destroy(struct nf_conn *ct)
}
 }
 
-static LIST_HEAD(nf_ct_helper_expectfn_list);
+static LIST_HEAD(nf_ct_nat_helper_list);
 
-void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n)
+void nf_ct_nat_helper_register(struct nf_ct_nat_helper *n)
 {
spin_lock_bh(_conntrack_expect_lock);
-   list_add_rcu(>head, _ct_helper_expectfn_list);
+   list_add_rcu(>head, _ct_nat_helper_list);
spin_unlock_bh(_conntrack_expect_lock);
 }
-EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register);
+EXPORT_SYMBOL_GPL(nf_ct_nat_helper_register);
 
-void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
+void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n)
 {
spin_lock_bh(_conntrack_expect_lock);

[PATCH nf v5 3/3] netfilter: nat_helper: Remove the expectations when its module is unloaded

2017-03-31 Thread gfree . wind
From: Gao Feng 

Because the conntrack NAT module could be rmmod anytime, so we should
really leave things in clean state if such thing happens and make sure
we don't leave any packet running over code that will be gone after the
removal.

We only removed the expectations when unregister conntrack helper before.
Actually it is necessary too when remove the nat helper.

Now add one new struct module member "me" in the nf_ct_nat_helper to
represent which module it belongs to.

Signed-off-by: Gao Feng 
---
 v5: Register one nat_helper for every nat module, per Pablo
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_helper.h |  1 +
 net/ipv4/netfilter/nf_nat_h323.c|  3 ++
 net/netfilter/ipvs/ip_vs_nfct.c |  1 +
 net/netfilter/nf_conntrack_expect.c |  8 
 net/netfilter/nf_conntrack_helper.c | 62 +++--
 net/netfilter/nf_conntrack_pptp.c   |  1 +
 net/netfilter/nf_nat_amanda.c   |  1 +
 net/netfilter/nf_nat_core.c |  1 +
 net/netfilter/nf_nat_ftp.c  |  1 +
 net/netfilter/nf_nat_irc.c  |  1 +
 net/netfilter/nf_nat_sip.c  |  1 +
 net/netfilter/nf_nat_tftp.c |  1 +
 12 files changed, 60 insertions(+), 22 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index e8d31ca..d70c5be 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -114,6 +114,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, 
unsigned int protoff,
 struct nf_ct_nat_helper {
struct list_head head;
const char *name;
+   struct module *me;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
 };
 
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 9101c48..c75583f 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -28,16 +28,19 @@ static void ip_nat_callforwarding_expect(struct nf_conn 
*new,
 
 static struct nf_ct_nat_helper q931_nat = {
.name   = "Q.931",
+   .me = THIS_MODULE,
.expectfn   = ip_nat_q931_expect,
 };
 
 static struct nf_ct_nat_helper callforwarding_nat = {
.name   = "callforwarding",
+   .me = THIS_MODULE,
.expectfn   = ip_nat_callforwarding_expect,
 };
 
 static struct nf_ct_nat_helper follow_master_nat = {
.name   = "h323_follow_master",
+   .me = THIS_MODULE,
.expectfn   = nf_nat_follow_master,
 };
 
diff --git a/net/netfilter/ipvs/ip_vs_nfct.c b/net/netfilter/ipvs/ip_vs_nfct.c
index 83ad79f..44cd98e 100644
--- a/net/netfilter/ipvs/ip_vs_nfct.c
+++ b/net/netfilter/ipvs/ip_vs_nfct.c
@@ -222,6 +222,7 @@ static void ip_vs_nfct_expect_callback(struct nf_conn *ct,
 
 static struct nf_ct_nat_helper ip_vs_nat = {
.name = "ip_vs_nat",
+   .me = THIS_MODULE,
.expectfn = ip_vs_nfct_expect_callback,
 };
 
diff --git a/net/netfilter/nf_conntrack_expect.c 
b/net/netfilter/nf_conntrack_expect.c
index ba5a55e..9653847 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -416,6 +416,14 @@ static inline int __nf_ct_expect_check(struct 
nf_conntrack_expect *expect)
ret = -ESHUTDOWN;
goto out;
}
+
+   /* Make sure the helper and nat_helper belong to the same module */
+   if (expect->helper && expect->nat_helper &&
+   expect->helper->me != expect->nat_helper->me) {
+   ret = -EINVAL;
+   goto out;
+   }
+
h = nf_ct_expect_dst_hash(net, >tuple);
hlist_for_each_entry_safe(i, next, _ct_expect_hash[h], hnode) {
if (expect_matches(i, expect)) {
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 0eaa01e..1a161a6 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -130,6 +130,37 @@ static unsigned int helper_hash(const struct 
nf_conntrack_tuple *tuple)
return NULL;
 }
 
+static void
+nf_ct_flush_expect(const struct module *me)
+{
+   struct nf_conntrack_expect *exp;
+   const struct hlist_node *next;
+   u32 i;
+
+   if (!me)
+   return;
+
+   /* Get rid of expectations */
+   spin_lock_bh(_conntrack_expect_lock);
+   for (i = 0; i < nf_ct_expect_hsize; i++) {
+   hlist_for_each_entry_safe(exp, next,
+ _ct_expect_hash[i], hnode) {
+   struct nf_conn_help *master_help = 
nfct_help(exp->master);
+
+   

[PATCH nf v5 0/3] Refine the robust of helper expectfn

2017-03-31 Thread gfree . wind
From: Gao Feng 

These patches are used to refine the codes of helper expectfn, and
enhance its robust, including fixing possible panic bug.

Gao Feng (3):
  netfilter: helper: Rename struct nf_ct_helper_expectfn to
nf_ct_nat_helper
  netfilter: nat_helper: Make sure every proto nat module uses its
nat_helper
  netfilter: nat_helper: Remove the expectations when its module is
unloaded

 include/net/netfilter/nf_conntrack_expect.h |  5 +-
 include/net/netfilter/nf_conntrack_helper.h | 13 ++--
 net/ipv4/netfilter/nf_nat_h323.c| 55 +++--
 net/netfilter/ipvs/ip_vs_nfct.c |  8 ++-
 net/netfilter/nf_conntrack_broadcast.c  |  2 +-
 net/netfilter/nf_conntrack_core.c   |  4 +-
 net/netfilter/nf_conntrack_expect.c | 10 ++-
 net/netfilter/nf_conntrack_helper.c | 94 +
 net/netfilter/nf_conntrack_netlink.c| 20 +++---
 net/netfilter/nf_conntrack_pptp.c   | 15 -
 net/netfilter/nf_nat_amanda.c   | 10 ++-
 net/netfilter/nf_nat_core.c |  7 ++-
 net/netfilter/nf_nat_ftp.c  | 10 ++-
 net/netfilter/nf_nat_irc.c  | 10 ++-
 net/netfilter/nf_nat_sip.c  | 23 ---
 net/netfilter/nf_nat_tftp.c | 10 ++-
 16 files changed, 194 insertions(+), 102 deletions(-)

-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v3 1/1] netfilter: helper: Add the rcu lock when call __nf_conntrack_helper_find

2017-03-29 Thread gfree . wind
From: Gao Feng 

When invoke __nf_conntrack_helper_find, it needs the rcu lock to
protect the helper module which would not be unloaded.

Now there are two caller nf_conntrack_helper_try_module_get and
ctnetlink_create_expect which don't hold rcu lock. And the other
callers left like ctnetlink_change_helper, ctnetlink_create_conntrack,
and ctnetlink_glue_attach_expect, they already hold the rcu lock
or spin_lock_bh.

Remove the rcu lock in functions nf_ct_helper_expectfn_find_by_name
and nf_ct_helper_expectfn_find_by_symbol. Because they return one pointer
which needs rcu lock, so their caller should hold the rcu lock, not in
these two functions.

Signed-off-by: Gao Feng 
---
 v3: Merge another refine patch, remove useless rcu lock, per Pablo
 v2: add the rcu lock in nf_conntrack_helper_try_module_get
 v1: initial version

 net/netfilter/nf_conntrack_helper.c  | 17 -
 net/netfilter/nf_conntrack_netlink.c | 10 --
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..4eeb341 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -158,16 +158,25 @@ struct nf_conntrack_helper *
 {
struct nf_conntrack_helper *h;
 
+   rcu_read_lock();
+
h = __nf_conntrack_helper_find(name, l3num, protonum);
 #ifdef CONFIG_MODULES
if (h == NULL) {
-   if (request_module("nfct-helper-%s", name) == 0)
+   rcu_read_unlock();
+   if (request_module("nfct-helper-%s", name) == 0) {
+   rcu_read_lock();
h = __nf_conntrack_helper_find(name, l3num, protonum);
+   } else {
+   return h;
+   }
}
 #endif
if (h != NULL && !try_module_get(h->me))
h = NULL;
 
+   rcu_read_unlock();
+
return h;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
@@ -311,38 +320,36 @@ void nf_ct_helper_expectfn_unregister(struct 
nf_ct_helper_expectfn *n)
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister);
 
+/* Caller should hold the rcu lock */
 struct nf_ct_helper_expectfn *
 nf_ct_helper_expectfn_find_by_name(const char *name)
 {
struct nf_ct_helper_expectfn *cur;
bool found = false;
 
-   rcu_read_lock();
list_for_each_entry_rcu(cur, _ct_helper_expectfn_list, head) {
if (!strcmp(cur->name, name)) {
found = true;
break;
}
}
-   rcu_read_unlock();
return found ? cur : NULL;
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name);
 
+/* Caller should hold the rcu lock */
 struct nf_ct_helper_expectfn *
 nf_ct_helper_expectfn_find_by_symbol(const void *symbol)
 {
struct nf_ct_helper_expectfn *cur;
bool found = false;
 
-   rcu_read_lock();
list_for_each_entry_rcu(cur, _ct_helper_expectfn_list, head) {
if (cur->expectfn == symbol) {
found = true;
break;
}
}
-   rcu_read_unlock();
return found ? cur : NULL;
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 6806b5e..f6d1d63 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3133,23 +3133,27 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
return -ENOENT;
ct = nf_ct_tuplehash_to_ctrack(h);
 
+   rcu_read_lock();
if (cda[CTA_EXPECT_HELP_NAME]) {
const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
 
helper = __nf_conntrack_helper_find(helpname, u3,
nf_ct_protonum(ct));
if (helper == NULL) {
+   rcu_read_unlock();
 #ifdef CONFIG_MODULES
if (request_module("nfct-helper-%s", helpname) < 0) {
err = -EOPNOTSUPP;
goto err_ct;
}
+   rcu_read_lock();
helper = __nf_conntrack_helper_find(helpname, u3,
nf_ct_protonum(ct));
if (helper) {
err = -EAGAIN;
-   goto err_ct;
+   goto err_rcu;
}
+   rcu_read_unlock();
 #endif
err = -EOPNOTSUPP;
goto err_ct;
@@ -3159,11 +3163,13 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
exp = ctnetlink_alloc_expect(cda, ct, helper, , );
if (IS_ERR(exp)) {
  

[PATCH nf-next 1/1] netfilter: ctlink: Return error directly when create expect without help

2017-03-27 Thread gfree . wind
From: Gao Feng 

The expect check func "__nf_ct_expect_check" asks the master_help is
necessary. So it is unnecessary to go ahead in ctnetlink_alloc_expect
when there is no help.

Actually the commit bc01befdcf3e ("netfilter: ctnetlink: add support
for user-space expectation helpers") permits ctlink create one expect
even though there is no master help. But the latter commit 3d058d7bc2c5
("netfilter: rework user-space expectation helper support") disables
it again.

Signed-off-by: Gao Feng 
---
 net/netfilter/nf_conntrack_netlink.c | 14 ++
 1 file changed, 2 insertions(+), 12 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index d49cc1e..c9af545 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3049,18 +3049,8 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
 
help = nfct_help(ct);
if (!help) {
-   if (!cda[CTA_EXPECT_TIMEOUT]) {
-   err = -EINVAL;
-   goto err_out;
-   }
-   exp->timeout.expires =
- jiffies + ntohl(nla_get_be32(cda[CTA_EXPECT_TIMEOUT])) * HZ;
-
-   exp->flags = NF_CT_EXPECT_USERSPACE;
-   if (cda[CTA_EXPECT_FLAGS]) {
-   exp->flags |=
-   ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
-   }
+   err = -EOPNOTSUPP;
+   goto err_out;
} else {
if (cda[CTA_EXPECT_FLAGS]) {
exp->flags = ntohl(nla_get_be32(cda[CTA_EXPECT_FLAGS]));
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next v2 1/1] netfilter: nat: Correct the return value check for nat mangled packet

2017-03-27 Thread gfree . wind
From: Gao Feng 

The return value type of function nf_nat_mangle_tcp/udp_packet is
int, but actually it is used as bool type. And most codes follow
this rule, for example, the sip, h323, and ftp. But some codes treat
the return value as NF_ACCEPT and NF_DROP, like amanda and irc.

Now use the bool type instead of the int to make it clear.

Signed-off-by: Gao Feng 
---
 v2: Merge two patches into one, and enhance the subject, per Pablo
 v1: init version

 include/net/netfilter/nf_nat_helper.h | 14 ++--
 net/ipv4/netfilter/nf_nat_pptp.c  | 20 +-
 net/netfilter/nf_nat_amanda.c | 11 +-
 net/netfilter/nf_nat_helper.c | 40 +--
 net/netfilter/nf_nat_irc.c|  9 
 5 files changed, 46 insertions(+), 48 deletions(-)

diff --git a/include/net/netfilter/nf_nat_helper.h 
b/include/net/netfilter/nf_nat_helper.h
index 01bcc6b..b27c391 100644
--- a/include/net/netfilter/nf_nat_helper.h
+++ b/include/net/netfilter/nf_nat_helper.h
@@ -7,13 +7,13 @@
 struct sk_buff;
 
 /* These return true or false. */
-int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct,
+bool __nf_nat_mangle_tcp_packet(struct sk_buff *skb, struct nf_conn *ct,
   enum ip_conntrack_info ctinfo,
   unsigned int protoff, unsigned int match_offset,
   unsigned int match_len, const char *rep_buffer,
   unsigned int rep_len, bool adjust);
 
-static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
+static inline bool nf_nat_mangle_tcp_packet(struct sk_buff *skb,
   struct nf_conn *ct,
   enum ip_conntrack_info ctinfo,
   unsigned int protoff,
@@ -27,11 +27,11 @@ static inline int nf_nat_mangle_tcp_packet(struct sk_buff 
*skb,
  rep_buffer, rep_len, true);
 }
 
-int nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
-enum ip_conntrack_info ctinfo,
-unsigned int protoff, unsigned int match_offset,
-unsigned int match_len, const char *rep_buffer,
-unsigned int rep_len);
+bool nf_nat_mangle_udp_packet(struct sk_buff *skb, struct nf_conn *ct,
+ enum ip_conntrack_info ctinfo,
+ unsigned int protoff, unsigned int match_offset,
+ unsigned int match_len, const char *rep_buffer,
+ unsigned int rep_len);
 
 /* Setup NAT on this expected conntrack so it follows master, but goes
  * to port ct->master->saved_proto. */
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c
index b3ca21b..211fee5 100644
--- a/net/ipv4/netfilter/nf_nat_pptp.c
+++ b/net/ipv4/netfilter/nf_nat_pptp.c
@@ -177,11 +177,11 @@ pptp_outbound_pkt(struct sk_buff *skb,
 ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
 
/* mangle packet */
-   if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
-cid_off + sizeof(struct pptp_pkt_hdr) +
-sizeof(struct PptpControlHeader),
-sizeof(new_callid), (char *)_callid,
-sizeof(new_callid)) == 0)
+   if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
+ cid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_callid), (char *)_callid,
+ sizeof(new_callid)))
return NF_DROP;
return NF_ACCEPT;
 }
@@ -271,11 +271,11 @@ pptp_inbound_pkt(struct sk_buff *skb,
pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
 ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
 
-   if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
-pcid_off + sizeof(struct pptp_pkt_hdr) +
-sizeof(struct PptpControlHeader),
-sizeof(new_pcid), (char *)_pcid,
-sizeof(new_pcid)) == 0)
+   if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
+ pcid_off + sizeof(struct pptp_pkt_hdr) +
+ sizeof(struct PptpControlHeader),
+ sizeof(new_pcid), (char *)_pcid,
+ sizeof(new_pcid)))
return NF_DROP;
return NF_ACCEPT;
 }
diff --git a/net/netfilter/nf_nat_amanda.c b/net/netfilter/nf_nat_amanda.c
index 

[PATCH nf v5 1/1] netfilter: snmp: Fix one possible panic when snmp_trap_helper fail to register

2017-03-25 Thread gfree . wind
From: Gao Feng 

In the commit 93557f53e1fb ("netfilter: nf_conntrack: nf_conntrack snmp
helper"), the snmp_helper is replaced by nf_nat_snmp_hook. So the
snmp_helper is never registered. But it still tries to unregister the
snmp_helper, it could cause the panic.

Now remove the useless snmp_helper and the unregister call in the
error handler.

Fixes: 93557f53e1fb ("netfilter: nf_conntrack: nf_conntrack snmp helper")
Signed-off-by: Gao Feng 
---
 v5: Remove useless variable, per Liping
 v4: Simplify the codes, per Pablo
 v3: Remove the angle brackets in description, per Sergei
 v2: Add the SHA1 ID in the description, per Sergei
 v1: Initial version

 net/ipv4/netfilter/nf_nat_snmp_basic.c | 19 +--
 1 file changed, 1 insertion(+), 18 deletions(-)

diff --git a/net/ipv4/netfilter/nf_nat_snmp_basic.c 
b/net/ipv4/netfilter/nf_nat_snmp_basic.c
index c9b52c3..6309c40 100644
--- a/net/ipv4/netfilter/nf_nat_snmp_basic.c
+++ b/net/ipv4/netfilter/nf_nat_snmp_basic.c
@@ -1260,16 +1260,6 @@ static int help(struct sk_buff *skb, unsigned int 
protoff,
.timeout= 180,
 };
 
-static struct nf_conntrack_helper snmp_helper __read_mostly = {
-   .me = THIS_MODULE,
-   .help   = help,
-   .expect_policy  = _exp_policy,
-   .name   = "snmp",
-   .tuple.src.l3num= AF_INET,
-   .tuple.src.u.udp.port   = cpu_to_be16(SNMP_PORT),
-   .tuple.dst.protonum = IPPROTO_UDP,
-};
-
 static struct nf_conntrack_helper snmp_trap_helper __read_mostly = {
.me = THIS_MODULE,
.help   = help,
@@ -1288,17 +1278,10 @@ static int help(struct sk_buff *skb, unsigned int 
protoff,
 
 static int __init nf_nat_snmp_basic_init(void)
 {
-   int ret = 0;
-
BUG_ON(nf_nat_snmp_hook != NULL);
RCU_INIT_POINTER(nf_nat_snmp_hook, help);
 
-   ret = nf_conntrack_helper_register(_trap_helper);
-   if (ret < 0) {
-   nf_conntrack_helper_unregister(_helper);
-   return ret;
-   }
-   return ret;
+   return nf_conntrack_helper_register(_trap_helper);
 }
 
 static void __exit nf_nat_snmp_basic_fini(void)
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v2 1/1] netfilter: expect: Make sure the max_expected limit is effective

2017-03-24 Thread gfree . wind
From: Gao Feng 

Because the type of expecting, the member of nf_conn_help, is u8, it
would overflow after reach U8_MAX(255). So it doesn't work when we
configure the max_expected exceeds 255 with expect policy.

Now add the check for max_expected. Return the -EINVAL when it exceeds
the limit.

Signed-off-by: Gao Feng 
---
 v2: Check the modparam of irc, per Pablo
 v1: initial version

 include/net/netfilter/nf_conntrack_expect.h | 1 +
 net/netfilter/nf_conntrack_helper.c | 3 +++
 net/netfilter/nf_conntrack_irc.c| 6 ++
 net/netfilter/nfnetlink_cthelper.c  | 6 ++
 4 files changed, 16 insertions(+)

diff --git a/include/net/netfilter/nf_conntrack_expect.h 
b/include/net/netfilter/nf_conntrack_expect.h
index 5ed33ea..80f2ff6 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -71,6 +71,7 @@ struct nf_conntrack_expect_policy {
 };
 
 #define NF_CT_EXPECT_CLASS_DEFAULT 0
+#define NF_CT_EXPECT_MAX_CNT   255
 
 int nf_conntrack_expect_pernet_init(struct net *net);
 void nf_conntrack_expect_pernet_fini(struct net *net);
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..752a977 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -385,6 +385,9 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper 
*me)
BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1);
 
+   if (me->expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
+   return -EINVAL;
+
mutex_lock(_ct_helper_mutex);
hlist_for_each_entry(cur, _ct_helper_hash[h], hnode) {
if (nf_ct_tuple_src_mask_cmp(>tuple, >tuple, )) {
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c
index 1972a14..1a5af4d 100644
--- a/net/netfilter/nf_conntrack_irc.c
+++ b/net/netfilter/nf_conntrack_irc.c
@@ -243,6 +243,12 @@ static int __init nf_conntrack_irc_init(void)
return -EINVAL;
}
 
+   if (max_dcc_channels > NF_CT_EXPECT_MAX_CNT) {
+   pr_err("max_dcc_channels must not be more than %u\n",
+  NF_CT_EXPECT_MAX_CNT);
+   return -EINVAL;
+   }
+
irc_exp_policy.max_expected = max_dcc_channels;
irc_exp_policy.timeout = dcc_timeout;
 
diff --git a/net/netfilter/nfnetlink_cthelper.c 
b/net/netfilter/nfnetlink_cthelper.c
index 2b987d2..d150679 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -143,6 +143,9 @@
nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN);
expect_policy->max_expected =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
+   if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
+   return -EINVAL;
+
expect_policy->timeout =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
 
@@ -280,6 +283,9 @@
 
new_policy->max_expected =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
+   if (new_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
+   return -EINVAL;
+
new_policy->timeout =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
 
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf 1/1] netfilter: expect: Make sure the max_expected limit is effective

2017-03-23 Thread gfree . wind
From: Gao Feng 

Because the type of expecting, the member of nf_conn_help, is u8, it
would overflow after reach U8_MAX(255). So it doesn't work when we
configure the max_expected exceeds 255 with expect policy.

Now add the check for max_expected. Return the -EINVAL when it exceeds
the limit.

Signed-off-by: Gao Feng 
---
 include/net/netfilter/nf_conntrack_expect.h | 1 +
 net/netfilter/nf_conntrack_helper.c | 3 +++
 net/netfilter/nfnetlink_cthelper.c  | 4 
 3 files changed, 8 insertions(+)

diff --git a/include/net/netfilter/nf_conntrack_expect.h 
b/include/net/netfilter/nf_conntrack_expect.h
index 5ed33ea..aa36a31 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -71,6 +71,7 @@ struct nf_conntrack_expect_policy {
 };
 
 #define NF_CT_EXPECT_CLASS_DEFAULT 0
+#define NF_CT_EXPECT_MAX_CNT   U8_MAX
 
 int nf_conntrack_expect_pernet_init(struct net *net);
 void nf_conntrack_expect_pernet_fini(struct net *net);
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..752a977 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -385,6 +385,9 @@ int nf_conntrack_helper_register(struct nf_conntrack_helper 
*me)
BUG_ON(me->expect_class_max >= NF_CT_MAX_EXPECT_CLASSES);
BUG_ON(strlen(me->name) > NF_CT_HELPER_NAME_LEN - 1);
 
+   if (me->expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
+   return -EINVAL;
+
mutex_lock(_ct_helper_mutex);
hlist_for_each_entry(cur, _ct_helper_hash[h], hnode) {
if (nf_ct_tuple_src_mask_cmp(>tuple, >tuple, )) {
diff --git a/net/netfilter/nfnetlink_cthelper.c 
b/net/netfilter/nfnetlink_cthelper.c
index 2b987d2..de841b3 100644
--- a/net/netfilter/nfnetlink_cthelper.c
+++ b/net/netfilter/nfnetlink_cthelper.c
@@ -143,6 +143,8 @@
nla_data(tb[NFCTH_POLICY_NAME]), NF_CT_HELPER_NAME_LEN);
expect_policy->max_expected =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
+   if (expect_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
+   return -EINVAL;
expect_policy->timeout =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
 
@@ -280,6 +282,8 @@
 
new_policy->max_expected =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_MAX]));
+   if (new_policy->max_expected > NF_CT_EXPECT_MAX_CNT)
+   return -EINVAL;
new_policy->timeout =
ntohl(nla_get_be32(tb[NFCTH_POLICY_EXPECT_TIMEOUT]));
 
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v2 1/1] netfilter: helper: Add the rcu lock when call __nf_conntrack_helper_find

2017-03-21 Thread gfree . wind
From: Gao Feng 

When invoke __nf_conntrack_helper_find, it needs the rcu lock to
protect the helper module which would not be unloaded.

Now there are two caller nf_conntrack_helper_try_module_get and
ctnetlink_create_expect which don't hold rcu lock. And the other
callers left like ctnetlink_change_helper, ctnetlink_create_conntrack,
and ctnetlink_glue_attach_expect, they already hold the rcu lock
or spin_lock_bh.

Signed-off-by: Gao Feng 
---
 v2: add the rcu lock in nf_conntrack_helper_try_module_get
 v1: initial version

 net/netfilter/nf_conntrack_helper.c  | 11 ++-
 net/netfilter/nf_conntrack_netlink.c | 10 --
 2 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..023af78 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -158,16 +158,25 @@ struct nf_conntrack_helper *
 {
struct nf_conntrack_helper *h;
 
+   rcu_read_lock();
+
h = __nf_conntrack_helper_find(name, l3num, protonum);
 #ifdef CONFIG_MODULES
if (h == NULL) {
-   if (request_module("nfct-helper-%s", name) == 0)
+   rcu_read_unlock();
+   if (request_module("nfct-helper-%s", name) == 0) {
+   rcu_read_lock();
h = __nf_conntrack_helper_find(name, l3num, protonum);
+   } else {
+   return h;
+   }
}
 #endif
if (h != NULL && !try_module_get(h->me))
h = NULL;
 
+   rcu_read_unlock();
+
return h;
 }
 EXPORT_SYMBOL_GPL(nf_conntrack_helper_try_module_get);
diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 6806b5e..f6d1d63 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3133,23 +3133,27 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
return -ENOENT;
ct = nf_ct_tuplehash_to_ctrack(h);
 
+   rcu_read_lock();
if (cda[CTA_EXPECT_HELP_NAME]) {
const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
 
helper = __nf_conntrack_helper_find(helpname, u3,
nf_ct_protonum(ct));
if (helper == NULL) {
+   rcu_read_unlock();
 #ifdef CONFIG_MODULES
if (request_module("nfct-helper-%s", helpname) < 0) {
err = -EOPNOTSUPP;
goto err_ct;
}
+   rcu_read_lock();
helper = __nf_conntrack_helper_find(helpname, u3,
nf_ct_protonum(ct));
if (helper) {
err = -EAGAIN;
-   goto err_ct;
+   goto err_rcu;
}
+   rcu_read_unlock();
 #endif
err = -EOPNOTSUPP;
goto err_ct;
@@ -3159,11 +3163,13 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
exp = ctnetlink_alloc_expect(cda, ct, helper, , );
if (IS_ERR(exp)) {
err = PTR_ERR(exp);
-   goto err_ct;
+   goto err_rcu;
}
 
err = nf_ct_expect_related_report(exp, portid, report);
nf_ct_expect_put(exp);
+err_rcu:
+   rcu_read_unlock();
 err_ct:
nf_ct_put(ct);
return err;
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf-next v2 1/1] netfilter: helper: Remove useless rcu lock when get expectfn

2017-03-21 Thread gfree . wind
From: Gao Feng 

Because these two functions return the nf_ct_helper_expectfn pointer
which should be protected by rcu lock. So it should makes sure the
caller should hold the rcu lock, not inside these functions.

Signed-off-by: Gao Feng 
---
 v2: Shorter subject, per Pablo
 v1: Initial version

 net/netfilter/nf_conntrack_helper.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..bce3d1f 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -311,38 +311,36 @@ void nf_ct_helper_expectfn_unregister(struct 
nf_ct_helper_expectfn *n)
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister);
 
+/* Caller should hold the rcu lock */
 struct nf_ct_helper_expectfn *
 nf_ct_helper_expectfn_find_by_name(const char *name)
 {
struct nf_ct_helper_expectfn *cur;
bool found = false;
 
-   rcu_read_lock();
list_for_each_entry_rcu(cur, _ct_helper_expectfn_list, head) {
if (!strcmp(cur->name, name)) {
found = true;
break;
}
}
-   rcu_read_unlock();
return found ? cur : NULL;
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_name);
 
+/* Caller should hold the rcu lock */
 struct nf_ct_helper_expectfn *
 nf_ct_helper_expectfn_find_by_symbol(const void *symbol)
 {
struct nf_ct_helper_expectfn *cur;
bool found = false;
 
-   rcu_read_lock();
list_for_each_entry_rcu(cur, _ct_helper_expectfn_list, head) {
if (cur->expectfn == symbol) {
found = true;
break;
}
}
-   rcu_read_unlock();
return found ? cur : NULL;
 }
 EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_find_by_symbol);
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH RESENT nf 1/1] netfilter: ctlink: Fix one possible use-after-free in ctnetlink_create_expect

2017-03-21 Thread gfree . wind
From: Gao Feng 

There is no rcu_read_lock during ctlink gets the helper and inserts the
expectation. So there is one possible use-after-free issue when unload
the helper module.

For example:

CPU1CPU2
ctlink gets the helper
helper module unload and remove all expectations
insert the expectation

Now there is one expectation which references one helper whose module is
unloaded.

Signed-off-by: Gao Feng 
---
 net/netfilter/nf_conntrack_netlink.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/net/netfilter/nf_conntrack_netlink.c 
b/net/netfilter/nf_conntrack_netlink.c
index 6806b5e..f6d1d63 100644
--- a/net/netfilter/nf_conntrack_netlink.c
+++ b/net/netfilter/nf_conntrack_netlink.c
@@ -3133,23 +3133,27 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
return -ENOENT;
ct = nf_ct_tuplehash_to_ctrack(h);
 
+   rcu_read_lock();
if (cda[CTA_EXPECT_HELP_NAME]) {
const char *helpname = nla_data(cda[CTA_EXPECT_HELP_NAME]);
 
helper = __nf_conntrack_helper_find(helpname, u3,
nf_ct_protonum(ct));
if (helper == NULL) {
+   rcu_read_unlock();
 #ifdef CONFIG_MODULES
if (request_module("nfct-helper-%s", helpname) < 0) {
err = -EOPNOTSUPP;
goto err_ct;
}
+   rcu_read_lock();
helper = __nf_conntrack_helper_find(helpname, u3,
nf_ct_protonum(ct));
if (helper) {
err = -EAGAIN;
-   goto err_ct;
+   goto err_rcu;
}
+   rcu_read_unlock();
 #endif
err = -EOPNOTSUPP;
goto err_ct;
@@ -3159,11 +3163,13 @@ static int ctnetlink_del_expect(struct net *net, struct 
sock *ctnl,
exp = ctnetlink_alloc_expect(cda, ct, helper, , );
if (IS_ERR(exp)) {
err = PTR_ERR(exp);
-   goto err_ct;
+   goto err_rcu;
}
 
err = nf_ct_expect_related_report(exp, portid, report);
nf_ct_expect_put(exp);
+err_rcu:
+   rcu_read_unlock();
 err_ct:
nf_ct_put(ct);
return err;
-- 
1.9.1




--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH nf v4 1/2] netfilter: helper: Rename struct nf_ct_helper_expectfn to nf_ct_nat_helper

2017-03-21 Thread gfree . wind
From: Gao Feng 

Rename struct nf_ct_helper_expectfn to nf_ct_nat_helper, and rename
other functions or variables which refer to it.
The new name is better than the old one.

Signed-off-by: Gao Feng 
---
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo,
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_helper.h | 14 ++---
 net/ipv4/netfilter/nf_nat_h323.c| 12 +--
 net/netfilter/nf_conntrack_helper.c | 32 ++---
 net/netfilter/nf_conntrack_netlink.c| 16 +++
 net/netfilter/nf_nat_core.c |  6 +++---
 net/netfilter/nf_nat_sip.c  |  6 +++---
 6 files changed, 43 insertions(+), 43 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index 1eaac1f..d14fe493 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -111,7 +111,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, 
unsigned int protoff,
enum ip_conntrack_info ctinfo,
unsigned int timeout);
 
-struct nf_ct_helper_expectfn {
+struct nf_ct_nat_helper {
struct list_head head;
const char *name;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
@@ -121,12 +121,12 @@ struct nf_ct_helper_expectfn {
 void nf_ct_helper_log(struct sk_buff *skb, const struct nf_conn *ct,
  const char *fmt, ...);
 
-void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n);
-void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n);
-struct nf_ct_helper_expectfn *
-nf_ct_helper_expectfn_find_by_name(const char *name);
-struct nf_ct_helper_expectfn *
-nf_ct_helper_expectfn_find_by_symbol(const void *symbol);
+void nf_ct_nat_helper_register(struct nf_ct_nat_helper *n);
+void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n);
+struct nf_ct_nat_helper *
+nf_ct_nat_helper_find_by_name(const char *name);
+struct nf_ct_nat_helper *
+nf_ct_nat_helper_find_by_symbol(const void *symbol);
 
 extern struct hlist_head *nf_ct_helper_hash;
 extern unsigned int nf_ct_helper_hsize;
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 574f7eb..346e764 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -567,12 +567,12 @@ static int nat_callforwarding(struct sk_buff *skb, struct 
nf_conn *ct,
return 0;
 }
 
-static struct nf_ct_helper_expectfn q931_nat = {
+static struct nf_ct_nat_helper q931_nat = {
.name   = "Q.931",
.expectfn   = ip_nat_q931_expect,
 };
 
-static struct nf_ct_helper_expectfn callforwarding_nat = {
+static struct nf_ct_nat_helper callforwarding_nat = {
.name   = "callforwarding",
.expectfn   = ip_nat_callforwarding_expect,
 };
@@ -599,8 +599,8 @@ static int __init init(void)
RCU_INIT_POINTER(nat_h245_hook, nat_h245);
RCU_INIT_POINTER(nat_callforwarding_hook, nat_callforwarding);
RCU_INIT_POINTER(nat_q931_hook, nat_q931);
-   nf_ct_helper_expectfn_register(_nat);
-   nf_ct_helper_expectfn_register(_nat);
+   nf_ct_nat_helper_register(_nat);
+   nf_ct_nat_helper_register(_nat);
return 0;
 }
 
@@ -616,8 +616,8 @@ static void __exit fini(void)
RCU_INIT_POINTER(nat_h245_hook, NULL);
RCU_INIT_POINTER(nat_callforwarding_hook, NULL);
RCU_INIT_POINTER(nat_q931_hook, NULL);
-   nf_ct_helper_expectfn_unregister(_nat);
-   nf_ct_helper_expectfn_unregister(_nat);
+   nf_ct_nat_helper_unregister(_nat);
+   nf_ct_nat_helper_unregister(_nat);
synchronize_rcu();
 }
 
diff --git a/net/netfilter/nf_conntrack_helper.c 
b/net/netfilter/nf_conntrack_helper.c
index 6dc44d9..0eaa01e 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -293,32 +293,32 @@ void nf_ct_helper_destroy(struct nf_conn *ct)
}
 }
 
-static LIST_HEAD(nf_ct_helper_expectfn_list);
+static LIST_HEAD(nf_ct_nat_helper_list);
 
-void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n)
+void nf_ct_nat_helper_register(struct nf_ct_nat_helper *n)
 {
spin_lock_bh(_conntrack_expect_lock);
-   list_add_rcu(>head, _ct_helper_expectfn_list);
+   list_add_rcu(>head, _ct_nat_helper_list);
spin_unlock_bh(_conntrack_expect_lock);
 }
-EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register);
+EXPORT_SYMBOL_GPL(nf_ct_nat_helper_register);
 
-void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n)
+void nf_ct_nat_helper_unregister(struct nf_ct_nat_helper *n)
 {
spin_lock_bh(_conntrack_expect_lock);
list_del_rcu(>head);
spin_unlock_bh(_conntrack_expect_lock);
 }

[PATCH nf v4 2/2] netfilter: helper: Fix possible panic caused by invoking expectfn unloaded

2017-03-21 Thread gfree . wind
From: Gao Feng 

Because the conntrack NAT module could be rmmod anytime, so we should
really leave things in clean state if such thing happens and make sure
we don't leave any packet running over code that will be gone after
the removal.

We only removed the expectations when unregister conntrack helper before.
Actually it is necessary too when remove the nat helper.

Signed-off-by: Gao Feng 
---
 v4: Cover the nat_module assignment in dataplane, per Pablo
 v3: Rename the nf_ct_helper_expectfn, func, and member, per Pablo
 v2: Use the module as the identifier when flush expect
 v1: initial version

 include/net/netfilter/nf_conntrack_expect.h |  2 +
 include/net/netfilter/nf_conntrack_helper.h |  1 +
 net/ipv4/netfilter/nf_nat_h323.c|  8 
 net/netfilter/nf_conntrack_broadcast.c  |  1 +
 net/netfilter/nf_conntrack_expect.c |  1 +
 net/netfilter/nf_conntrack_helper.c | 63 ++---
 net/netfilter/nf_conntrack_netlink.c|  5 ++-
 net/netfilter/nf_conntrack_pptp.c   |  2 +
 net/netfilter/nf_nat_amanda.c   |  1 +
 net/netfilter/nf_nat_core.c |  1 +
 net/netfilter/nf_nat_ftp.c  |  1 +
 net/netfilter/nf_nat_irc.c  |  1 +
 net/netfilter/nf_nat_sip.c  |  4 ++
 net/netfilter/nf_nat_tftp.c |  1 +
 14 files changed, 67 insertions(+), 25 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack_expect.h 
b/include/net/netfilter/nf_conntrack_expect.h
index 5ed33ea..f2bc64e 100644
--- a/include/net/netfilter/nf_conntrack_expect.h
+++ b/include/net/netfilter/nf_conntrack_expect.h
@@ -26,6 +26,8 @@ struct nf_conntrack_expect {
/* Function to call after setup and insertion */
void (*expectfn)(struct nf_conn *new,
 struct nf_conntrack_expect *this);
+   /* The module which expectfn belongs to */
+   struct module *nat_module;
 
/* Helper to assign to new connection */
struct nf_conntrack_helper *helper;
diff --git a/include/net/netfilter/nf_conntrack_helper.h 
b/include/net/netfilter/nf_conntrack_helper.h
index d14fe493..dd1a687 100644
--- a/include/net/netfilter/nf_conntrack_helper.h
+++ b/include/net/netfilter/nf_conntrack_helper.h
@@ -113,6 +113,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, 
unsigned int protoff,
 
 struct nf_ct_nat_helper {
struct list_head head;
+   struct module *me;
const char *name;
void (*expectfn)(struct nf_conn *ct, struct nf_conntrack_expect *exp);
 };
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c
index 346e764..df57219 100644
--- a/net/ipv4/netfilter/nf_nat_h323.c
+++ b/net/ipv4/netfilter/nf_nat_h323.c
@@ -188,9 +188,11 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct 
nf_conn *ct,
/* Set expectations for NAT */
rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port;
rtp_exp->expectfn = nf_nat_follow_master;
+   rtp_exp->nat_module = THIS_MODULE;
rtp_exp->dir = !dir;
rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port;
rtcp_exp->expectfn = nf_nat_follow_master;
+   rtcp_exp->nat_module = THIS_MODULE;
rtcp_exp->dir = !dir;
 
/* Lookup existing expects */
@@ -290,6 +292,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
/* Set expectations for NAT */
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
exp->expectfn = nf_nat_follow_master;
+   exp->nat_module = THIS_MODULE;
exp->dir = !dir;
 
/* Try to get same port: if not, try to change it. */
@@ -342,6 +345,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
/* Set expectations for NAT */
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
exp->expectfn = nf_nat_follow_master;
+   exp->nat_module = THIS_MODULE;
exp->dir = !dir;
 
/* Check existing expects */
@@ -434,6 +438,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
/* Set expectations for NAT */
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
exp->expectfn = ip_nat_q931_expect;
+   exp->nat_module = THIS_MODULE;
exp->dir = !dir;
 
/* Check existing expects */
@@ -528,6 +533,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct 
nf_conn *ct,
exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
exp->expectfn = ip_nat_callforwarding_expect;
+   exp->nat_module = THIS_MODULE;
exp->dir = !dir;
 
/* Try to get same port: if not, try to change it. */
@@ -569,11 +575,13 @@ static int nat_callforwarding(struct sk_buff *skb, struct 
nf_conn *ct,
 
 static struct nf_ct_nat_helper q931_nat = {
.name   = "Q.931",
+   .me = THIS_MODULE,