[NETFILTER]: ctnetlink: Fix expectaction mask dumping
The expectation mask has some particularities that requires a different handling. The protocol number fields can be set to non-valid protocols, ie. l3num is set to 0xFFFF. Since that protocol does not exist, the mask tuple will not be dumped. Moreover, this results in a kernel panic when nf_conntrack accesses the array of protocol handlers, that is PF_MAX (0x1F) long. This patch introduces the function ctnetlink_exp_dump_mask, that correctly dumps the expectation mask. Such function uses the l3num value from the expectation tuple that is a valid layer 3 protocol number. The value of the l3num mask isn't dumped since it is meaningless from the userspace side. Thanks to Yasuyuki Kozakai and Patrick McHardy for the feedback. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> Signed-off-by: Patrick McHardy <kaber@trash.net> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
50b521aa54
commit
1cde64365b
2 changed files with 120 additions and 42 deletions
|
@ -4,7 +4,7 @@
|
||||||
* (C) 2001 by Jay Schulist <jschlst@samba.org>
|
* (C) 2001 by Jay Schulist <jschlst@samba.org>
|
||||||
* (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
|
* (C) 2002-2005 by Harald Welte <laforge@gnumonks.org>
|
||||||
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
|
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
|
||||||
* (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
|
* (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
|
||||||
*
|
*
|
||||||
* I've reworked this stuff to use attributes instead of conntrack
|
* I've reworked this stuff to use attributes instead of conntrack
|
||||||
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
|
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
|
||||||
|
@ -53,20 +53,18 @@ static char __initdata version[] = "0.90";
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
|
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
|
||||||
const struct ip_conntrack_tuple *tuple)
|
const struct ip_conntrack_tuple *tuple,
|
||||||
|
struct ip_conntrack_protocol *proto)
|
||||||
{
|
{
|
||||||
struct ip_conntrack_protocol *proto;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
|
||||||
|
|
||||||
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
|
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
|
||||||
|
|
||||||
/* If no protocol helper is found, this function will return the
|
|
||||||
* generic protocol helper, so proto won't *ever* be NULL */
|
|
||||||
proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
|
|
||||||
if (likely(proto->tuple_to_nfattr))
|
if (likely(proto->tuple_to_nfattr))
|
||||||
ret = proto->tuple_to_nfattr(skb, tuple);
|
ret = proto->tuple_to_nfattr(skb, tuple);
|
||||||
|
|
||||||
ip_conntrack_proto_put(proto);
|
NFA_NEST_END(skb, nest_parms);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -75,27 +73,40 @@ nfattr_failure:
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_dump_tuples(struct sk_buff *skb,
|
ctnetlink_dump_tuples_ip(struct sk_buff *skb,
|
||||||
const struct ip_conntrack_tuple *tuple)
|
const struct ip_conntrack_tuple *tuple)
|
||||||
{
|
{
|
||||||
struct nfattr *nest_parms;
|
struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
|
||||||
int ret;
|
|
||||||
|
|
||||||
nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
|
|
||||||
NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
|
NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip);
|
||||||
NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
|
NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip);
|
||||||
|
|
||||||
NFA_NEST_END(skb, nest_parms);
|
NFA_NEST_END(skb, nest_parms);
|
||||||
|
|
||||||
nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
|
return 0;
|
||||||
ret = ctnetlink_dump_tuples_proto(skb, tuple);
|
|
||||||
NFA_NEST_END(skb, nest_parms);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
nfattr_failure:
|
nfattr_failure:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ctnetlink_dump_tuples(struct sk_buff *skb,
|
||||||
|
const struct ip_conntrack_tuple *tuple)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ip_conntrack_protocol *proto;
|
||||||
|
|
||||||
|
ret = ctnetlink_dump_tuples_ip(skb, tuple);
|
||||||
|
if (unlikely(ret < 0))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
|
||||||
|
ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
|
||||||
|
ip_conntrack_proto_put(proto);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
|
ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct)
|
||||||
{
|
{
|
||||||
|
@ -1134,6 +1145,33 @@ nfattr_failure:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ctnetlink_exp_dump_mask(struct sk_buff *skb,
|
||||||
|
const struct ip_conntrack_tuple *tuple,
|
||||||
|
const struct ip_conntrack_tuple *mask)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct ip_conntrack_protocol *proto;
|
||||||
|
struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
|
||||||
|
|
||||||
|
ret = ctnetlink_dump_tuples_ip(skb, mask);
|
||||||
|
if (unlikely(ret < 0))
|
||||||
|
goto nfattr_failure;
|
||||||
|
|
||||||
|
proto = ip_conntrack_proto_find_get(tuple->dst.protonum);
|
||||||
|
ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
|
||||||
|
ip_conntrack_proto_put(proto);
|
||||||
|
if (unlikely(ret < 0))
|
||||||
|
goto nfattr_failure;
|
||||||
|
|
||||||
|
NFA_NEST_END(skb, nest_parms);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nfattr_failure:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||||
const struct ip_conntrack_expect *exp)
|
const struct ip_conntrack_expect *exp)
|
||||||
|
@ -1144,7 +1182,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||||
|
|
||||||
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
|
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
|
||||||
goto nfattr_failure;
|
goto nfattr_failure;
|
||||||
if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
|
if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
|
||||||
goto nfattr_failure;
|
goto nfattr_failure;
|
||||||
if (ctnetlink_exp_dump_tuple(skb,
|
if (ctnetlink_exp_dump_tuple(skb,
|
||||||
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
|
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* (C) 2001 by Jay Schulist <jschlst@samba.org>
|
* (C) 2001 by Jay Schulist <jschlst@samba.org>
|
||||||
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
|
* (C) 2002-2006 by Harald Welte <laforge@gnumonks.org>
|
||||||
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
|
* (C) 2003 by Patrick Mchardy <kaber@trash.net>
|
||||||
* (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net>
|
* (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net>
|
||||||
*
|
*
|
||||||
* I've reworked this stuff to use attributes instead of conntrack
|
* I've reworked this stuff to use attributes instead of conntrack
|
||||||
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
|
* structures. 5.44 am. I need more tea. --pablo 05/07/11.
|
||||||
|
@ -55,20 +55,18 @@ static char __initdata version[] = "0.93";
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
|
ctnetlink_dump_tuples_proto(struct sk_buff *skb,
|
||||||
const struct nf_conntrack_tuple *tuple)
|
const struct nf_conntrack_tuple *tuple,
|
||||||
|
struct nf_conntrack_protocol *proto)
|
||||||
{
|
{
|
||||||
struct nf_conntrack_protocol *proto;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
|
||||||
|
|
||||||
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
|
NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum);
|
||||||
|
|
||||||
/* If no protocol helper is found, this function will return the
|
|
||||||
* generic protocol helper, so proto won't *ever* be NULL */
|
|
||||||
proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
|
|
||||||
if (likely(proto->tuple_to_nfattr))
|
if (likely(proto->tuple_to_nfattr))
|
||||||
ret = proto->tuple_to_nfattr(skb, tuple);
|
ret = proto->tuple_to_nfattr(skb, tuple);
|
||||||
|
|
||||||
nf_ct_proto_put(proto);
|
NFA_NEST_END(skb, nest_parms);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
@ -77,27 +75,16 @@ nfattr_failure:
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_dump_tuples(struct sk_buff *skb,
|
ctnetlink_dump_tuples_ip(struct sk_buff *skb,
|
||||||
const struct nf_conntrack_tuple *tuple)
|
const struct nf_conntrack_tuple *tuple,
|
||||||
|
struct nf_conntrack_l3proto *l3proto)
|
||||||
{
|
{
|
||||||
struct nfattr *nest_parms;
|
|
||||||
struct nf_conntrack_l3proto *l3proto;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
|
||||||
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
|
|
||||||
|
|
||||||
nest_parms = NFA_NEST(skb, CTA_TUPLE_IP);
|
|
||||||
if (likely(l3proto->tuple_to_nfattr))
|
if (likely(l3proto->tuple_to_nfattr))
|
||||||
ret = l3proto->tuple_to_nfattr(skb, tuple);
|
ret = l3proto->tuple_to_nfattr(skb, tuple);
|
||||||
NFA_NEST_END(skb, nest_parms);
|
|
||||||
|
|
||||||
nf_ct_l3proto_put(l3proto);
|
|
||||||
|
|
||||||
if (unlikely(ret < 0))
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO);
|
|
||||||
ret = ctnetlink_dump_tuples_proto(skb, tuple);
|
|
||||||
NFA_NEST_END(skb, nest_parms);
|
NFA_NEST_END(skb, nest_parms);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -106,6 +93,28 @@ nfattr_failure:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ctnetlink_dump_tuples(struct sk_buff *skb,
|
||||||
|
const struct nf_conntrack_tuple *tuple)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct nf_conntrack_l3proto *l3proto;
|
||||||
|
struct nf_conntrack_protocol *proto;
|
||||||
|
|
||||||
|
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
|
||||||
|
ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto);
|
||||||
|
nf_ct_l3proto_put(l3proto);
|
||||||
|
|
||||||
|
if (unlikely(ret < 0))
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
|
||||||
|
ret = ctnetlink_dump_tuples_proto(skb, tuple, proto);
|
||||||
|
nf_ct_proto_put(proto);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
|
ctnetlink_dump_status(struct sk_buff *skb, const struct nf_conn *ct)
|
||||||
{
|
{
|
||||||
|
@ -1152,6 +1161,37 @@ nfattr_failure:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
ctnetlink_exp_dump_mask(struct sk_buff *skb,
|
||||||
|
const struct nf_conntrack_tuple *tuple,
|
||||||
|
const struct nf_conntrack_tuple *mask)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct nf_conntrack_l3proto *l3proto;
|
||||||
|
struct nf_conntrack_protocol *proto;
|
||||||
|
struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK);
|
||||||
|
|
||||||
|
l3proto = nf_ct_l3proto_find_get(tuple->src.l3num);
|
||||||
|
ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto);
|
||||||
|
nf_ct_l3proto_put(l3proto);
|
||||||
|
|
||||||
|
if (unlikely(ret < 0))
|
||||||
|
goto nfattr_failure;
|
||||||
|
|
||||||
|
proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum);
|
||||||
|
ret = ctnetlink_dump_tuples_proto(skb, mask, proto);
|
||||||
|
nf_ct_proto_put(proto);
|
||||||
|
if (unlikely(ret < 0))
|
||||||
|
goto nfattr_failure;
|
||||||
|
|
||||||
|
NFA_NEST_END(skb, nest_parms);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
nfattr_failure:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||||
const struct nf_conntrack_expect *exp)
|
const struct nf_conntrack_expect *exp)
|
||||||
|
@ -1162,7 +1202,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||||
|
|
||||||
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
|
if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0)
|
||||||
goto nfattr_failure;
|
goto nfattr_failure;
|
||||||
if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0)
|
if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0)
|
||||||
goto nfattr_failure;
|
goto nfattr_failure;
|
||||||
if (ctnetlink_exp_dump_tuple(skb,
|
if (ctnetlink_exp_dump_tuple(skb,
|
||||||
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
|
&master->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
|
||||||
|
|
Loading…
Add table
Reference in a new issue