aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-03-22 18:40:01 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2012-03-22 19:52:01 -0400
commitc1ebd7dff700277e4d0a3da36833a406142e31d4 (patch)
treefbcfed48280d81744fe77efebb91900c7db1c776 /net
parenta0f65a267dd62aef4e003f833ea6290fd1e07b34 (diff)
netfilter: cttimeout: fix dependency with l4protocol conntrack module
This patch introduces nf_conntrack_l4proto_find_get() and nf_conntrack_l4proto_put() to fix module dependencies between timeout objects and l4-protocol conntrack modules. Thus, we make sure that the module cannot be removed if it is used by any of the cttimeout objects. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_proto.c21
-rw-r--r--net/netfilter/nfnetlink_cttimeout.c45
-rw-r--r--net/netfilter/xt_CT.c6
3 files changed, 48 insertions, 24 deletions
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c
index 5701c8dd783c..be3da2c8cdc5 100644
--- a/net/netfilter/nf_conntrack_proto.c
+++ b/net/netfilter/nf_conntrack_proto.c
@@ -127,6 +127,27 @@ void nf_ct_l3proto_module_put(unsigned short l3proto)
127} 127}
128EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put); 128EXPORT_SYMBOL_GPL(nf_ct_l3proto_module_put);
129 129
130struct nf_conntrack_l4proto *
131nf_ct_l4proto_find_get(u_int16_t l3num, u_int8_t l4num)
132{
133 struct nf_conntrack_l4proto *p;
134
135 rcu_read_lock();
136 p = __nf_ct_l4proto_find(l3num, l4num);
137 if (!try_module_get(p->me))
138 p = &nf_conntrack_l4proto_generic;
139 rcu_read_unlock();
140
141 return p;
142}
143EXPORT_SYMBOL_GPL(nf_ct_l4proto_find_get);
144
145void nf_ct_l4proto_put(struct nf_conntrack_l4proto *p)
146{
147 module_put(p->me);
148}
149EXPORT_SYMBOL_GPL(nf_ct_l4proto_put);
150
130static int kill_l3proto(struct nf_conn *i, void *data) 151static int kill_l3proto(struct nf_conn *i, void *data)
131{ 152{
132 return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto; 153 return nf_ct_l3num(i) == ((struct nf_conntrack_l3proto *)data)->l3proto;
diff --git a/net/netfilter/nfnetlink_cttimeout.c b/net/netfilter/nfnetlink_cttimeout.c
index fec29a43de4d..2b9e79f5ef05 100644
--- a/net/netfilter/nfnetlink_cttimeout.c
+++ b/net/netfilter/nfnetlink_cttimeout.c
@@ -98,11 +98,13 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
98 break; 98 break;
99 } 99 }
100 100
101 l4proto = __nf_ct_l4proto_find(l3num, l4num); 101 l4proto = nf_ct_l4proto_find_get(l3num, l4num);
102 102
103 /* This protocol is not supportted, skip. */ 103 /* This protocol is not supportted, skip. */
104 if (l4proto->l4proto != l4num) 104 if (l4proto->l4proto != l4num) {
105 return -EOPNOTSUPP; 105 ret = -EOPNOTSUPP;
106 goto err_proto_put;
107 }
106 108
107 if (matching) { 109 if (matching) {
108 if (nlh->nlmsg_flags & NLM_F_REPLACE) { 110 if (nlh->nlmsg_flags & NLM_F_REPLACE) {
@@ -110,20 +112,25 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
110 * different kind, sorry. 112 * different kind, sorry.
111 */ 113 */
112 if (matching->l3num != l3num || 114 if (matching->l3num != l3num ||
113 matching->l4num != l4num) 115 matching->l4proto->l4proto != l4num) {
114 return -EINVAL; 116 ret = -EINVAL;
117 goto err_proto_put;
118 }
115 119
116 ret = ctnl_timeout_parse_policy(matching, l4proto, 120 ret = ctnl_timeout_parse_policy(matching, l4proto,
117 cda[CTA_TIMEOUT_DATA]); 121 cda[CTA_TIMEOUT_DATA]);
118 return ret; 122 return ret;
119 } 123 }
120 return -EBUSY; 124 ret = -EBUSY;
125 goto err_proto_put;
121 } 126 }
122 127
123 timeout = kzalloc(sizeof(struct ctnl_timeout) + 128 timeout = kzalloc(sizeof(struct ctnl_timeout) +
124 l4proto->ctnl_timeout.obj_size, GFP_KERNEL); 129 l4proto->ctnl_timeout.obj_size, GFP_KERNEL);
125 if (timeout == NULL) 130 if (timeout == NULL) {
126 return -ENOMEM; 131 ret = -ENOMEM;
132 goto err_proto_put;
133 }
127 134
128 ret = ctnl_timeout_parse_policy(timeout, l4proto, 135 ret = ctnl_timeout_parse_policy(timeout, l4proto,
129 cda[CTA_TIMEOUT_DATA]); 136 cda[CTA_TIMEOUT_DATA]);
@@ -132,13 +139,15 @@ cttimeout_new_timeout(struct sock *ctnl, struct sk_buff *skb,
132 139
133 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME])); 140 strcpy(timeout->name, nla_data(cda[CTA_TIMEOUT_NAME]));
134 timeout->l3num = l3num; 141 timeout->l3num = l3num;
135 timeout->l4num = l4num; 142 timeout->l4proto = l4proto;
136 atomic_set(&timeout->refcnt, 1); 143 atomic_set(&timeout->refcnt, 1);
137 list_add_tail_rcu(&timeout->head, &cttimeout_list); 144 list_add_tail_rcu(&timeout->head, &cttimeout_list);
138 145
139 return 0; 146 return 0;
140err: 147err:
141 kfree(timeout); 148 kfree(timeout);
149err_proto_put:
150 nf_ct_l4proto_put(l4proto);
142 return ret; 151 return ret;
143} 152}
144 153
@@ -149,7 +158,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
149 struct nlmsghdr *nlh; 158 struct nlmsghdr *nlh;
150 struct nfgenmsg *nfmsg; 159 struct nfgenmsg *nfmsg;
151 unsigned int flags = pid ? NLM_F_MULTI : 0; 160 unsigned int flags = pid ? NLM_F_MULTI : 0;
152 struct nf_conntrack_l4proto *l4proto; 161 struct nf_conntrack_l4proto *l4proto = timeout->l4proto;
153 162
154 event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8; 163 event |= NFNL_SUBSYS_CTNETLINK_TIMEOUT << 8;
155 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); 164 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags);
@@ -163,20 +172,10 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
163 172
164 NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name); 173 NLA_PUT_STRING(skb, CTA_TIMEOUT_NAME, timeout->name);
165 NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num)); 174 NLA_PUT_BE16(skb, CTA_TIMEOUT_L3PROTO, htons(timeout->l3num));
166 NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4num); 175 NLA_PUT_U8(skb, CTA_TIMEOUT_L4PROTO, timeout->l4proto->l4proto);
167 NLA_PUT_BE32(skb, CTA_TIMEOUT_USE, 176 NLA_PUT_BE32(skb, CTA_TIMEOUT_USE,
168 htonl(atomic_read(&timeout->refcnt))); 177 htonl(atomic_read(&timeout->refcnt)));
169 178
170 l4proto = __nf_ct_l4proto_find(timeout->l3num, timeout->l4num);
171
172 /* If the timeout object does not match the layer 4 protocol tracker,
173 * then skip dumping the data part since we don't know how to
174 * interpret it. This may happen for UPDlite, SCTP and DCCP since
175 * you can unload the module.
176 */
177 if (timeout->l4num != l4proto->l4proto)
178 goto out;
179
180 if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) { 179 if (likely(l4proto->ctnl_timeout.obj_to_nlattr)) {
181 struct nlattr *nest_parms; 180 struct nlattr *nest_parms;
182 int ret; 181 int ret;
@@ -192,7 +191,7 @@ ctnl_timeout_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type,
192 191
193 nla_nest_end(skb, nest_parms); 192 nla_nest_end(skb, nest_parms);
194 } 193 }
195out: 194
196 nlmsg_end(skb, nlh); 195 nlmsg_end(skb, nlh);
197 return skb->len; 196 return skb->len;
198 197
@@ -293,6 +292,7 @@ static int ctnl_timeout_try_del(struct ctnl_timeout *timeout)
293 if (atomic_dec_and_test(&timeout->refcnt)) { 292 if (atomic_dec_and_test(&timeout->refcnt)) {
294 /* We are protected by nfnl mutex. */ 293 /* We are protected by nfnl mutex. */
295 list_del_rcu(&timeout->head); 294 list_del_rcu(&timeout->head);
295 nf_ct_l4proto_put(timeout->l4proto);
296 kfree_rcu(timeout, rcu_head); 296 kfree_rcu(timeout, rcu_head);
297 } else { 297 } else {
298 /* still in use, restore reference counter. */ 298 /* still in use, restore reference counter. */
@@ -417,6 +417,7 @@ static void __exit cttimeout_exit(void)
417 /* We are sure that our objects have no clients at this point, 417 /* We are sure that our objects have no clients at this point,
418 * it's safe to release them all without checking refcnt. 418 * it's safe to release them all without checking refcnt.
419 */ 419 */
420 nf_ct_l4proto_put(cur->l4proto);
420 kfree_rcu(cur, rcu_head); 421 kfree_rcu(cur, rcu_head);
421 } 422 }
422#ifdef CONFIG_NF_CONNTRACK_TIMEOUT 423#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index b873445df444..80c39f0f6e91 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -16,6 +16,7 @@
16#include <net/netfilter/nf_conntrack.h> 16#include <net/netfilter/nf_conntrack.h>
17#include <net/netfilter/nf_conntrack_helper.h> 17#include <net/netfilter/nf_conntrack_helper.h>
18#include <net/netfilter/nf_conntrack_ecache.h> 18#include <net/netfilter/nf_conntrack_ecache.h>
19#include <net/netfilter/nf_conntrack_l4proto.h>
19#include <net/netfilter/nf_conntrack_timeout.h> 20#include <net/netfilter/nf_conntrack_timeout.h>
20#include <net/netfilter/nf_conntrack_zones.h> 21#include <net/netfilter/nf_conntrack_zones.h>
21 22
@@ -243,11 +244,12 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par)
243 info->timeout, timeout->l3num); 244 info->timeout, timeout->l3num);
244 goto err3; 245 goto err3;
245 } 246 }
246 if (timeout->l4num != e->ip.proto) { 247 if (timeout->l4proto->l4proto != e->ip.proto) {
247 ret = -EINVAL; 248 ret = -EINVAL;
248 pr_info("Timeout policy `%s' can only be " 249 pr_info("Timeout policy `%s' can only be "
249 "used by L4 protocol number %d\n", 250 "used by L4 protocol number %d\n",
250 info->timeout, timeout->l4num); 251 info->timeout,
252 timeout->l4proto->l4proto);
251 goto err3; 253 goto err3;
252 } 254 }
253 timeout_ext = nf_ct_timeout_ext_add(ct, timeout, 255 timeout_ext = nf_ct_timeout_ext_add(ct, timeout,