diff options
author | Pablo Neira Ayuso <pablo@netfilter.org> | 2006-03-22 16:54:15 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-22 16:54:15 -0500 |
commit | 1cde64365b0c4f576f8f45b834e6a6de081b5914 (patch) | |
tree | 86f35fc9f292365c87b7ff90e0933e9d38db2863 /net | |
parent | 50b521aa54f415a626bfd63d1a9b72120e9fbe88 (diff) |
[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>
Diffstat (limited to 'net')
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 72 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_netlink.c | 84 |
2 files changed, 117 insertions, 39 deletions
diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 5ce2e3fc2c7f..9b6e19bae90f 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> | 4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> |
5 | * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> | 5 | * (C) 2002-2005 by Harald Welte <laforge@gnumonks.org> |
6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> | 6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> |
7 | * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net> | 7 | * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net> |
8 | * | 8 | * |
9 | * I've reworked this stuff to use attributes instead of conntrack | 9 | * I've reworked this stuff to use attributes instead of conntrack |
10 | * structures. 5.44 am. I need more tea. --pablo 05/07/11. | 10 | * structures. 5.44 am. I need more tea. --pablo 05/07/11. |
@@ -53,20 +53,18 @@ static char __initdata version[] = "0.90"; | |||
53 | 53 | ||
54 | static inline int | 54 | static inline int |
55 | ctnetlink_dump_tuples_proto(struct sk_buff *skb, | 55 | ctnetlink_dump_tuples_proto(struct sk_buff *skb, |
56 | const struct ip_conntrack_tuple *tuple) | 56 | const struct ip_conntrack_tuple *tuple, |
57 | struct ip_conntrack_protocol *proto) | ||
57 | { | 58 | { |
58 | struct ip_conntrack_protocol *proto; | ||
59 | int ret = 0; | 59 | int ret = 0; |
60 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); | ||
60 | 61 | ||
61 | NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); | 62 | NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); |
62 | 63 | ||
63 | /* If no protocol helper is found, this function will return the | ||
64 | * generic protocol helper, so proto won't *ever* be NULL */ | ||
65 | proto = ip_conntrack_proto_find_get(tuple->dst.protonum); | ||
66 | if (likely(proto->tuple_to_nfattr)) | 64 | if (likely(proto->tuple_to_nfattr)) |
67 | ret = proto->tuple_to_nfattr(skb, tuple); | 65 | ret = proto->tuple_to_nfattr(skb, tuple); |
68 | 66 | ||
69 | ip_conntrack_proto_put(proto); | 67 | NFA_NEST_END(skb, nest_parms); |
70 | 68 | ||
71 | return ret; | 69 | return ret; |
72 | 70 | ||
@@ -75,28 +73,41 @@ nfattr_failure: | |||
75 | } | 73 | } |
76 | 74 | ||
77 | static inline int | 75 | static inline int |
78 | ctnetlink_dump_tuples(struct sk_buff *skb, | 76 | ctnetlink_dump_tuples_ip(struct sk_buff *skb, |
79 | const struct ip_conntrack_tuple *tuple) | 77 | const struct ip_conntrack_tuple *tuple) |
80 | { | 78 | { |
81 | struct nfattr *nest_parms; | 79 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP); |
82 | int ret; | ||
83 | 80 | ||
84 | nest_parms = NFA_NEST(skb, CTA_TUPLE_IP); | ||
85 | NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip); | 81 | NFA_PUT(skb, CTA_IP_V4_SRC, sizeof(u_int32_t), &tuple->src.ip); |
86 | NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip); | 82 | NFA_PUT(skb, CTA_IP_V4_DST, sizeof(u_int32_t), &tuple->dst.ip); |
87 | NFA_NEST_END(skb, nest_parms); | ||
88 | 83 | ||
89 | nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); | ||
90 | ret = ctnetlink_dump_tuples_proto(skb, tuple); | ||
91 | NFA_NEST_END(skb, nest_parms); | 84 | NFA_NEST_END(skb, nest_parms); |
92 | 85 | ||
93 | return ret; | 86 | return 0; |
94 | 87 | ||
95 | nfattr_failure: | 88 | nfattr_failure: |
96 | return -1; | 89 | return -1; |
97 | } | 90 | } |
98 | 91 | ||
99 | static inline int | 92 | static inline int |
93 | ctnetlink_dump_tuples(struct sk_buff *skb, | ||
94 | const struct ip_conntrack_tuple *tuple) | ||
95 | { | ||
96 | int ret; | ||
97 | struct ip_conntrack_protocol *proto; | ||
98 | |||
99 | ret = ctnetlink_dump_tuples_ip(skb, tuple); | ||
100 | if (unlikely(ret < 0)) | ||
101 | return ret; | ||
102 | |||
103 | proto = ip_conntrack_proto_find_get(tuple->dst.protonum); | ||
104 | ret = ctnetlink_dump_tuples_proto(skb, tuple, proto); | ||
105 | ip_conntrack_proto_put(proto); | ||
106 | |||
107 | return ret; | ||
108 | } | ||
109 | |||
110 | static inline int | ||
100 | ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct) | 111 | ctnetlink_dump_status(struct sk_buff *skb, const struct ip_conntrack *ct) |
101 | { | 112 | { |
102 | u_int32_t status = htonl((u_int32_t) ct->status); | 113 | u_int32_t status = htonl((u_int32_t) ct->status); |
@@ -1135,6 +1146,33 @@ nfattr_failure: | |||
1135 | } | 1146 | } |
1136 | 1147 | ||
1137 | static inline int | 1148 | static inline int |
1149 | ctnetlink_exp_dump_mask(struct sk_buff *skb, | ||
1150 | const struct ip_conntrack_tuple *tuple, | ||
1151 | const struct ip_conntrack_tuple *mask) | ||
1152 | { | ||
1153 | int ret; | ||
1154 | struct ip_conntrack_protocol *proto; | ||
1155 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); | ||
1156 | |||
1157 | ret = ctnetlink_dump_tuples_ip(skb, mask); | ||
1158 | if (unlikely(ret < 0)) | ||
1159 | goto nfattr_failure; | ||
1160 | |||
1161 | proto = ip_conntrack_proto_find_get(tuple->dst.protonum); | ||
1162 | ret = ctnetlink_dump_tuples_proto(skb, mask, proto); | ||
1163 | ip_conntrack_proto_put(proto); | ||
1164 | if (unlikely(ret < 0)) | ||
1165 | goto nfattr_failure; | ||
1166 | |||
1167 | NFA_NEST_END(skb, nest_parms); | ||
1168 | |||
1169 | return 0; | ||
1170 | |||
1171 | nfattr_failure: | ||
1172 | return -1; | ||
1173 | } | ||
1174 | |||
1175 | static inline int | ||
1138 | ctnetlink_exp_dump_expect(struct sk_buff *skb, | 1176 | ctnetlink_exp_dump_expect(struct sk_buff *skb, |
1139 | const struct ip_conntrack_expect *exp) | 1177 | const struct ip_conntrack_expect *exp) |
1140 | { | 1178 | { |
@@ -1144,7 +1182,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, | |||
1144 | 1182 | ||
1145 | if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) | 1183 | if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) |
1146 | goto nfattr_failure; | 1184 | goto nfattr_failure; |
1147 | if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) | 1185 | if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0) |
1148 | goto nfattr_failure; | 1186 | goto nfattr_failure; |
1149 | if (ctnetlink_exp_dump_tuple(skb, | 1187 | if (ctnetlink_exp_dump_tuple(skb, |
1150 | &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 1188 | &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 5eadf009bb15..0e0e9d7b34c8 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -4,7 +4,7 @@ | |||
4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> | 4 | * (C) 2001 by Jay Schulist <jschlst@samba.org> |
5 | * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> | 5 | * (C) 2002-2006 by Harald Welte <laforge@gnumonks.org> |
6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> | 6 | * (C) 2003 by Patrick Mchardy <kaber@trash.net> |
7 | * (C) 2005 by Pablo Neira Ayuso <pablo@eurodev.net> | 7 | * (C) 2005-2006 by Pablo Neira Ayuso <pablo@eurodev.net> |
8 | * | 8 | * |
9 | * I've reworked this stuff to use attributes instead of conntrack | 9 | * I've reworked this stuff to use attributes instead of conntrack |
10 | * structures. 5.44 am. I need more tea. --pablo 05/07/11. | 10 | * structures. 5.44 am. I need more tea. --pablo 05/07/11. |
@@ -55,20 +55,18 @@ static char __initdata version[] = "0.93"; | |||
55 | 55 | ||
56 | static inline int | 56 | static inline int |
57 | ctnetlink_dump_tuples_proto(struct sk_buff *skb, | 57 | ctnetlink_dump_tuples_proto(struct sk_buff *skb, |
58 | const struct nf_conntrack_tuple *tuple) | 58 | const struct nf_conntrack_tuple *tuple, |
59 | struct nf_conntrack_protocol *proto) | ||
59 | { | 60 | { |
60 | struct nf_conntrack_protocol *proto; | ||
61 | int ret = 0; | 61 | int ret = 0; |
62 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); | ||
62 | 63 | ||
63 | NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); | 64 | NFA_PUT(skb, CTA_PROTO_NUM, sizeof(u_int8_t), &tuple->dst.protonum); |
64 | 65 | ||
65 | /* If no protocol helper is found, this function will return the | ||
66 | * generic protocol helper, so proto won't *ever* be NULL */ | ||
67 | proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum); | ||
68 | if (likely(proto->tuple_to_nfattr)) | 66 | if (likely(proto->tuple_to_nfattr)) |
69 | ret = proto->tuple_to_nfattr(skb, tuple); | 67 | ret = proto->tuple_to_nfattr(skb, tuple); |
70 | 68 | ||
71 | nf_ct_proto_put(proto); | 69 | NFA_NEST_END(skb, nest_parms); |
72 | 70 | ||
73 | return ret; | 71 | return ret; |
74 | 72 | ||
@@ -77,33 +75,44 @@ nfattr_failure: | |||
77 | } | 75 | } |
78 | 76 | ||
79 | static inline int | 77 | static inline int |
80 | ctnetlink_dump_tuples(struct sk_buff *skb, | 78 | ctnetlink_dump_tuples_ip(struct sk_buff *skb, |
81 | const struct nf_conntrack_tuple *tuple) | 79 | const struct nf_conntrack_tuple *tuple, |
80 | struct nf_conntrack_l3proto *l3proto) | ||
82 | { | 81 | { |
83 | struct nfattr *nest_parms; | ||
84 | struct nf_conntrack_l3proto *l3proto; | ||
85 | int ret = 0; | 82 | int ret = 0; |
86 | 83 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_TUPLE_IP); | |
87 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); | 84 | |
88 | |||
89 | nest_parms = NFA_NEST(skb, CTA_TUPLE_IP); | ||
90 | if (likely(l3proto->tuple_to_nfattr)) | 85 | if (likely(l3proto->tuple_to_nfattr)) |
91 | ret = l3proto->tuple_to_nfattr(skb, tuple); | 86 | ret = l3proto->tuple_to_nfattr(skb, tuple); |
87 | |||
92 | NFA_NEST_END(skb, nest_parms); | 88 | NFA_NEST_END(skb, nest_parms); |
93 | 89 | ||
90 | return ret; | ||
91 | |||
92 | nfattr_failure: | ||
93 | return -1; | ||
94 | } | ||
95 | |||
96 | static inline int | ||
97 | ctnetlink_dump_tuples(struct sk_buff *skb, | ||
98 | const struct nf_conntrack_tuple *tuple) | ||
99 | { | ||
100 | int ret; | ||
101 | struct nf_conntrack_l3proto *l3proto; | ||
102 | struct nf_conntrack_protocol *proto; | ||
103 | |||
104 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); | ||
105 | ret = ctnetlink_dump_tuples_ip(skb, tuple, l3proto); | ||
94 | nf_ct_l3proto_put(l3proto); | 106 | nf_ct_l3proto_put(l3proto); |
95 | 107 | ||
96 | if (unlikely(ret < 0)) | 108 | if (unlikely(ret < 0)) |
97 | return ret; | 109 | return ret; |
98 | 110 | ||
99 | nest_parms = NFA_NEST(skb, CTA_TUPLE_PROTO); | 111 | proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum); |
100 | ret = ctnetlink_dump_tuples_proto(skb, tuple); | 112 | ret = ctnetlink_dump_tuples_proto(skb, tuple, proto); |
101 | NFA_NEST_END(skb, nest_parms); | 113 | nf_ct_proto_put(proto); |
102 | 114 | ||
103 | return ret; | 115 | return ret; |
104 | |||
105 | nfattr_failure: | ||
106 | return -1; | ||
107 | } | 116 | } |
108 | 117 | ||
109 | static inline int | 118 | static inline int |
@@ -1153,6 +1162,37 @@ nfattr_failure: | |||
1153 | } | 1162 | } |
1154 | 1163 | ||
1155 | static inline int | 1164 | static inline int |
1165 | ctnetlink_exp_dump_mask(struct sk_buff *skb, | ||
1166 | const struct nf_conntrack_tuple *tuple, | ||
1167 | const struct nf_conntrack_tuple *mask) | ||
1168 | { | ||
1169 | int ret; | ||
1170 | struct nf_conntrack_l3proto *l3proto; | ||
1171 | struct nf_conntrack_protocol *proto; | ||
1172 | struct nfattr *nest_parms = NFA_NEST(skb, CTA_EXPECT_MASK); | ||
1173 | |||
1174 | l3proto = nf_ct_l3proto_find_get(tuple->src.l3num); | ||
1175 | ret = ctnetlink_dump_tuples_ip(skb, mask, l3proto); | ||
1176 | nf_ct_l3proto_put(l3proto); | ||
1177 | |||
1178 | if (unlikely(ret < 0)) | ||
1179 | goto nfattr_failure; | ||
1180 | |||
1181 | proto = nf_ct_proto_find_get(tuple->src.l3num, tuple->dst.protonum); | ||
1182 | ret = ctnetlink_dump_tuples_proto(skb, mask, proto); | ||
1183 | nf_ct_proto_put(proto); | ||
1184 | if (unlikely(ret < 0)) | ||
1185 | goto nfattr_failure; | ||
1186 | |||
1187 | NFA_NEST_END(skb, nest_parms); | ||
1188 | |||
1189 | return 0; | ||
1190 | |||
1191 | nfattr_failure: | ||
1192 | return -1; | ||
1193 | } | ||
1194 | |||
1195 | static inline int | ||
1156 | ctnetlink_exp_dump_expect(struct sk_buff *skb, | 1196 | ctnetlink_exp_dump_expect(struct sk_buff *skb, |
1157 | const struct nf_conntrack_expect *exp) | 1197 | const struct nf_conntrack_expect *exp) |
1158 | { | 1198 | { |
@@ -1162,7 +1202,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, | |||
1162 | 1202 | ||
1163 | if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) | 1203 | if (ctnetlink_exp_dump_tuple(skb, &exp->tuple, CTA_EXPECT_TUPLE) < 0) |
1164 | goto nfattr_failure; | 1204 | goto nfattr_failure; |
1165 | if (ctnetlink_exp_dump_tuple(skb, &exp->mask, CTA_EXPECT_MASK) < 0) | 1205 | if (ctnetlink_exp_dump_mask(skb, &exp->tuple, &exp->mask) < 0) |
1166 | goto nfattr_failure; | 1206 | goto nfattr_failure; |
1167 | if (ctnetlink_exp_dump_tuple(skb, | 1207 | if (ctnetlink_exp_dump_tuple(skb, |
1168 | &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, | 1208 | &master->tuplehash[IP_CT_DIR_ORIGINAL].tuple, |