aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-06-06 04:03:06 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-06 04:03:06 -0400
commit143554ace8919d5ef3cc8424c0b06dbd3d671b4e (patch)
treeab1c540cf8086c513aa7c0f831fb556263bf72d7 /net/netfilter
parent6bc19fb82d4c05a9eee19d6d2aab2ce26e499ec2 (diff)
parent7f87712c0152511a1842698ad8dca425fee2dc4f (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
Conflicts: net/netfilter/nf_log.c The conflict in nf_log.c is that in 'net' we added CONFIG_PROC_FS protection around foo_proc_entry() calls to fix a build failure, whereas in Pablo's tree a guard if() test around a call is remove_proc_entry() was removed. Trivially resolved. Pablo Neira Ayuso says: ==================== The following patchset contains the first batch of Netfilter/IPVS updates for your net-next tree, they are: * Three patches with improvements and code refactorization for nfnetlink_queue, from Florian Westphal. * FTP helper now parses replies without brackets, as RFC1123 recommends, from Jeff Mahoney. * Rise a warning to tell everyone about ULOG deprecation, NFLOG has been already in the kernel tree for long time and supersedes the old logging over netlink stub, from myself. * Don't panic if we fail to load netfilter core framework, just bail out instead, from myself. * Add cond_resched_rcu, used by IPVS to allow rescheduling while walking over big hashtables, from Simon Horman. * Change type of IPVS sysctl_sync_qlen_max sysctl to avoid possible overflow, from Zhang Yanfei. * Use strlcpy instead of strncpy to skip zeroing of already initialized area to write the extension names in ebtables, from Chen Gang. * Use already existing per-cpu notrack object from xt_CT, from Eric Dumazet. * Save explicit socket lookup in xt_socket now that we have early demux, also from Eric Dumazet. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netfilter')
-rw-r--r--net/netfilter/core.c21
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c23
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c4
-rw-r--r--net/netfilter/nf_conntrack_ftp.c73
-rw-r--r--net/netfilter/nf_log.c4
-rw-r--r--net/netfilter/nfnetlink_queue_core.c29
-rw-r--r--net/netfilter/xt_CT.c10
-rw-r--r--net/netfilter/xt_socket.c26
8 files changed, 116 insertions, 74 deletions
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 857ca9f35177..2217363ab422 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -304,17 +304,26 @@ static struct pernet_operations netfilter_net_ops = {
304 .exit = netfilter_net_exit, 304 .exit = netfilter_net_exit,
305}; 305};
306 306
307void __init netfilter_init(void) 307int __init netfilter_init(void)
308{ 308{
309 int i, h; 309 int i, h, ret;
310
310 for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) { 311 for (i = 0; i < ARRAY_SIZE(nf_hooks); i++) {
311 for (h = 0; h < NF_MAX_HOOKS; h++) 312 for (h = 0; h < NF_MAX_HOOKS; h++)
312 INIT_LIST_HEAD(&nf_hooks[i][h]); 313 INIT_LIST_HEAD(&nf_hooks[i][h]);
313 } 314 }
314 315
315 if (register_pernet_subsys(&netfilter_net_ops) < 0) 316 ret = register_pernet_subsys(&netfilter_net_ops);
316 panic("cannot create netfilter proc entry"); 317 if (ret < 0)
318 goto err;
319
320 ret = netfilter_log_init();
321 if (ret < 0)
322 goto err_pernet;
317 323
318 if (netfilter_log_init() < 0) 324 return 0;
319 panic("cannot initialize nf_log"); 325err_pernet:
326 unregister_pernet_subsys(&netfilter_net_ops);
327err:
328 return ret;
320} 329}
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index a083bda322b6..c8c52a98590b 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -975,8 +975,7 @@ static void *ip_vs_conn_array(struct seq_file *seq, loff_t pos)
975 return cp; 975 return cp;
976 } 976 }
977 } 977 }
978 rcu_read_unlock(); 978 cond_resched_rcu();
979 rcu_read_lock();
980 } 979 }
981 980
982 return NULL; 981 return NULL;
@@ -1015,8 +1014,7 @@ static void *ip_vs_conn_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1015 iter->l = &ip_vs_conn_tab[idx]; 1014 iter->l = &ip_vs_conn_tab[idx];
1016 return cp; 1015 return cp;
1017 } 1016 }
1018 rcu_read_unlock(); 1017 cond_resched_rcu();
1019 rcu_read_lock();
1020 } 1018 }
1021 iter->l = NULL; 1019 iter->l = NULL;
1022 return NULL; 1020 return NULL;
@@ -1206,17 +1204,13 @@ void ip_vs_random_dropentry(struct net *net)
1206 int idx; 1204 int idx;
1207 struct ip_vs_conn *cp, *cp_c; 1205 struct ip_vs_conn *cp, *cp_c;
1208 1206
1207 rcu_read_lock();
1209 /* 1208 /*
1210 * Randomly scan 1/32 of the whole table every second 1209 * Randomly scan 1/32 of the whole table every second
1211 */ 1210 */
1212 for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) { 1211 for (idx = 0; idx < (ip_vs_conn_tab_size>>5); idx++) {
1213 unsigned int hash = net_random() & ip_vs_conn_tab_mask; 1212 unsigned int hash = net_random() & ip_vs_conn_tab_mask;
1214 1213
1215 /*
1216 * Lock is actually needed in this loop.
1217 */
1218 rcu_read_lock();
1219
1220 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) { 1214 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[hash], c_list) {
1221 if (cp->flags & IP_VS_CONN_F_TEMPLATE) 1215 if (cp->flags & IP_VS_CONN_F_TEMPLATE)
1222 /* connection template */ 1216 /* connection template */
@@ -1252,8 +1246,9 @@ void ip_vs_random_dropentry(struct net *net)
1252 __ip_vs_conn_put(cp); 1246 __ip_vs_conn_put(cp);
1253 } 1247 }
1254 } 1248 }
1255 rcu_read_unlock(); 1249 cond_resched_rcu();
1256 } 1250 }
1251 rcu_read_unlock();
1257} 1252}
1258 1253
1259 1254
@@ -1267,11 +1262,8 @@ static void ip_vs_conn_flush(struct net *net)
1267 struct netns_ipvs *ipvs = net_ipvs(net); 1262 struct netns_ipvs *ipvs = net_ipvs(net);
1268 1263
1269flush_again: 1264flush_again:
1265 rcu_read_lock();
1270 for (idx = 0; idx < ip_vs_conn_tab_size; idx++) { 1266 for (idx = 0; idx < ip_vs_conn_tab_size; idx++) {
1271 /*
1272 * Lock is actually needed in this loop.
1273 */
1274 rcu_read_lock();
1275 1267
1276 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) { 1268 hlist_for_each_entry_rcu(cp, &ip_vs_conn_tab[idx], c_list) {
1277 if (!ip_vs_conn_net_eq(cp, net)) 1269 if (!ip_vs_conn_net_eq(cp, net))
@@ -1286,8 +1278,9 @@ flush_again:
1286 __ip_vs_conn_put(cp); 1278 __ip_vs_conn_put(cp);
1287 } 1279 }
1288 } 1280 }
1289 rcu_read_unlock(); 1281 cond_resched_rcu();
1290 } 1282 }
1283 rcu_read_unlock();
1291 1284
1292 /* the counter may be not NULL, because maybe some conn entries 1285 /* the counter may be not NULL, because maybe some conn entries
1293 are run by slow timer handler or unhashed but still referred */ 1286 are run by slow timer handler or unhashed but still referred */
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index 7c3ed429789e..df05c1c276f0 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -1716,9 +1716,9 @@ static struct ctl_table vs_vars[] = {
1716 }, 1716 },
1717 { 1717 {
1718 .procname = "sync_qlen_max", 1718 .procname = "sync_qlen_max",
1719 .maxlen = sizeof(int), 1719 .maxlen = sizeof(unsigned long),
1720 .mode = 0644, 1720 .mode = 0644,
1721 .proc_handler = proc_dointvec, 1721 .proc_handler = proc_doulongvec_minmax,
1722 }, 1722 },
1723 { 1723 {
1724 .procname = "sync_sock_size", 1724 .procname = "sync_sock_size",
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c
index 6b217074237b..b8a0924064ef 100644
--- a/net/netfilter/nf_conntrack_ftp.c
+++ b/net/netfilter/nf_conntrack_ftp.c
@@ -55,10 +55,14 @@ unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
55 struct nf_conntrack_expect *exp); 55 struct nf_conntrack_expect *exp);
56EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); 56EXPORT_SYMBOL_GPL(nf_nat_ftp_hook);
57 57
58static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); 58static int try_rfc959(const char *, size_t, struct nf_conntrack_man *,
59static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); 59 char, unsigned int *);
60static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *,
61 char, unsigned int *);
62static int try_eprt(const char *, size_t, struct nf_conntrack_man *,
63 char, unsigned int *);
60static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, 64static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *,
61 char); 65 char, unsigned int *);
62 66
63static struct ftp_search { 67static struct ftp_search {
64 const char *pattern; 68 const char *pattern;
@@ -66,7 +70,7 @@ static struct ftp_search {
66 char skip; 70 char skip;
67 char term; 71 char term;
68 enum nf_ct_ftp_type ftptype; 72 enum nf_ct_ftp_type ftptype;
69 int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char); 73 int (*getnum)(const char *, size_t, struct nf_conntrack_man *, char, unsigned int *);
70} search[IP_CT_DIR_MAX][2] = { 74} search[IP_CT_DIR_MAX][2] = {
71 [IP_CT_DIR_ORIGINAL] = { 75 [IP_CT_DIR_ORIGINAL] = {
72 { 76 {
@@ -90,10 +94,8 @@ static struct ftp_search {
90 { 94 {
91 .pattern = "227 ", 95 .pattern = "227 ",
92 .plen = sizeof("227 ") - 1, 96 .plen = sizeof("227 ") - 1,
93 .skip = '(',
94 .term = ')',
95 .ftptype = NF_CT_FTP_PASV, 97 .ftptype = NF_CT_FTP_PASV,
96 .getnum = try_rfc959, 98 .getnum = try_rfc1123,
97 }, 99 },
98 { 100 {
99 .pattern = "229 ", 101 .pattern = "229 ",
@@ -132,8 +134,9 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[],
132 i++; 134 i++;
133 else { 135 else {
134 /* Unexpected character; true if it's the 136 /* Unexpected character; true if it's the
135 terminator and we're finished. */ 137 terminator (or we don't care about one)
136 if (*data == term && i == array_size - 1) 138 and we're finished. */
139 if ((*data == term || !term) && i == array_size - 1)
137 return len; 140 return len;
138 141
139 pr_debug("Char %u (got %u nums) `%u' unexpected\n", 142 pr_debug("Char %u (got %u nums) `%u' unexpected\n",
@@ -148,7 +151,8 @@ static int try_number(const char *data, size_t dlen, u_int32_t array[],
148 151
149/* Returns 0, or length of numbers: 192,168,1,1,5,6 */ 152/* Returns 0, or length of numbers: 192,168,1,1,5,6 */
150static int try_rfc959(const char *data, size_t dlen, 153static int try_rfc959(const char *data, size_t dlen,
151 struct nf_conntrack_man *cmd, char term) 154 struct nf_conntrack_man *cmd, char term,
155 unsigned int *offset)
152{ 156{
153 int length; 157 int length;
154 u_int32_t array[6]; 158 u_int32_t array[6];
@@ -163,6 +167,33 @@ static int try_rfc959(const char *data, size_t dlen,
163 return length; 167 return length;
164} 168}
165 169
170/*
171 * From RFC 1123:
172 * The format of the 227 reply to a PASV command is not
173 * well standardized. In particular, an FTP client cannot
174 * assume that the parentheses shown on page 40 of RFC-959
175 * will be present (and in fact, Figure 3 on page 43 omits
176 * them). Therefore, a User-FTP program that interprets
177 * the PASV reply must scan the reply for the first digit
178 * of the host and port numbers.
179 */
180static int try_rfc1123(const char *data, size_t dlen,
181 struct nf_conntrack_man *cmd, char term,
182 unsigned int *offset)
183{
184 int i;
185 for (i = 0; i < dlen; i++)
186 if (isdigit(data[i]))
187 break;
188
189 if (i == dlen)
190 return 0;
191
192 *offset += i;
193
194 return try_rfc959(data + i, dlen - i, cmd, 0, offset);
195}
196
166/* Grab port: number up to delimiter */ 197/* Grab port: number up to delimiter */
167static int get_port(const char *data, int start, size_t dlen, char delim, 198static int get_port(const char *data, int start, size_t dlen, char delim,
168 __be16 *port) 199 __be16 *port)
@@ -191,7 +222,7 @@ static int get_port(const char *data, int start, size_t dlen, char delim,
191 222
192/* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */ 223/* Returns 0, or length of numbers: |1|132.235.1.2|6275| or |2|3ffe::1|6275| */
193static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, 224static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
194 char term) 225 char term, unsigned int *offset)
195{ 226{
196 char delim; 227 char delim;
197 int length; 228 int length;
@@ -239,7 +270,8 @@ static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd,
239 270
240/* Returns 0, or length of numbers: |||6446| */ 271/* Returns 0, or length of numbers: |||6446| */
241static int try_epsv_response(const char *data, size_t dlen, 272static int try_epsv_response(const char *data, size_t dlen,
242 struct nf_conntrack_man *cmd, char term) 273 struct nf_conntrack_man *cmd, char term,
274 unsigned int *offset)
243{ 275{
244 char delim; 276 char delim;
245 277
@@ -261,9 +293,10 @@ static int find_pattern(const char *data, size_t dlen,
261 unsigned int *numlen, 293 unsigned int *numlen,
262 struct nf_conntrack_man *cmd, 294 struct nf_conntrack_man *cmd,
263 int (*getnum)(const char *, size_t, 295 int (*getnum)(const char *, size_t,
264 struct nf_conntrack_man *, char)) 296 struct nf_conntrack_man *, char,
297 unsigned int *))
265{ 298{
266 size_t i; 299 size_t i = plen;
267 300
268 pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen); 301 pr_debug("find_pattern `%s': dlen = %Zu\n", pattern, dlen);
269 if (dlen == 0) 302 if (dlen == 0)
@@ -293,16 +326,18 @@ static int find_pattern(const char *data, size_t dlen,
293 pr_debug("Pattern matches!\n"); 326 pr_debug("Pattern matches!\n");
294 /* Now we've found the constant string, try to skip 327 /* Now we've found the constant string, try to skip
295 to the 'skip' character */ 328 to the 'skip' character */
296 for (i = plen; data[i] != skip; i++) 329 if (skip) {
297 if (i == dlen - 1) return -1; 330 for (i = plen; data[i] != skip; i++)
331 if (i == dlen - 1) return -1;
298 332
299 /* Skip over the last character */ 333 /* Skip over the last character */
300 i++; 334 i++;
335 }
301 336
302 pr_debug("Skipped up to `%c'!\n", skip); 337 pr_debug("Skipped up to `%c'!\n", skip);
303 338
304 *numoff = i; 339 *numoff = i;
305 *numlen = getnum(data + i, dlen - i, cmd, term); 340 *numlen = getnum(data + i, dlen - i, cmd, term, numoff);
306 if (!*numlen) 341 if (!*numlen)
307 return -1; 342 return -1;
308 343
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c
index 3b18dd1be7d9..4b60a87b7596 100644
--- a/net/netfilter/nf_log.c
+++ b/net/netfilter/nf_log.c
@@ -369,9 +369,7 @@ static int __net_init nf_log_net_init(struct net *net)
369 369
370out_sysctl: 370out_sysctl:
371#ifdef CONFIG_PROC_FS 371#ifdef CONFIG_PROC_FS
372 /* For init_net: errors will trigger panic, don't unroll on error. */ 372 remove_proc_entry("nf_log", net->nf.proc_netfilter);
373 if (!net_eq(net, &init_net))
374 remove_proc_entry("nf_log", net->nf.proc_netfilter);
375#endif 373#endif
376 return ret; 374 return ret;
377} 375}
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 0f2ac8f2e7b7..c011543bff5d 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -41,6 +41,14 @@
41 41
42#define NFQNL_QMAX_DEFAULT 1024 42#define NFQNL_QMAX_DEFAULT 1024
43 43
44/* We're using struct nlattr which has 16bit nla_len. Note that nla_len
45 * includes the header length. Thus, the maximum packet length that we
46 * support is 65531 bytes. We send truncated packets if the specified length
47 * is larger than that. Userspace can check for presence of NFQA_CAP_LEN
48 * attribute to detect truncation.
49 */
50#define NFQNL_MAX_COPY_RANGE (0xffff - NLA_HDRLEN)
51
44struct nfqnl_instance { 52struct nfqnl_instance {
45 struct hlist_node hlist; /* global list of queues */ 53 struct hlist_node hlist; /* global list of queues */
46 struct rcu_head rcu; 54 struct rcu_head rcu;
@@ -122,7 +130,7 @@ instance_create(struct nfnl_queue_net *q, u_int16_t queue_num,
122 inst->queue_num = queue_num; 130 inst->queue_num = queue_num;
123 inst->peer_portid = portid; 131 inst->peer_portid = portid;
124 inst->queue_maxlen = NFQNL_QMAX_DEFAULT; 132 inst->queue_maxlen = NFQNL_QMAX_DEFAULT;
125 inst->copy_range = 0xffff; 133 inst->copy_range = NFQNL_MAX_COPY_RANGE;
126 inst->copy_mode = NFQNL_COPY_NONE; 134 inst->copy_mode = NFQNL_COPY_NONE;
127 spin_lock_init(&inst->lock); 135 spin_lock_init(&inst->lock);
128 INIT_LIST_HEAD(&inst->queue_list); 136 INIT_LIST_HEAD(&inst->queue_list);
@@ -333,10 +341,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
333 return NULL; 341 return NULL;
334 342
335 data_len = ACCESS_ONCE(queue->copy_range); 343 data_len = ACCESS_ONCE(queue->copy_range);
336 if (data_len == 0 || data_len > entskb->len) 344 if (data_len > entskb->len)
337 data_len = entskb->len; 345 data_len = entskb->len;
338 346
339
340 if (!entskb->head_frag || 347 if (!entskb->head_frag ||
341 skb_headlen(entskb) < L1_CACHE_BYTES || 348 skb_headlen(entskb) < L1_CACHE_BYTES ||
342 skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS) 349 skb_shinfo(entskb)->nr_frags >= MAX_SKB_FRAGS)
@@ -465,7 +472,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
465 if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) 472 if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
466 goto nla_put_failure; 473 goto nla_put_failure;
467 474
468 if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len))) 475 if (cap_len > data_len &&
476 nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
469 goto nla_put_failure; 477 goto nla_put_failure;
470 478
471 if (nfqnl_put_packet_info(skb, entskb)) 479 if (nfqnl_put_packet_info(skb, entskb))
@@ -509,10 +517,6 @@ __nfqnl_enqueue_packet(struct net *net, struct nfqnl_instance *queue,
509 } 517 }
510 spin_lock_bh(&queue->lock); 518 spin_lock_bh(&queue->lock);
511 519
512 if (!queue->peer_portid) {
513 err = -EINVAL;
514 goto err_out_free_nskb;
515 }
516 if (queue->queue_total >= queue->queue_maxlen) { 520 if (queue->queue_total >= queue->queue_maxlen) {
517 if (queue->flags & NFQA_CFG_F_FAIL_OPEN) { 521 if (queue->flags & NFQA_CFG_F_FAIL_OPEN) {
518 failopen = 1; 522 failopen = 1;
@@ -731,13 +735,8 @@ nfqnl_set_mode(struct nfqnl_instance *queue,
731 735
732 case NFQNL_COPY_PACKET: 736 case NFQNL_COPY_PACKET:
733 queue->copy_mode = mode; 737 queue->copy_mode = mode;
734 /* We're using struct nlattr which has 16bit nla_len. Note that 738 if (range == 0 || range > NFQNL_MAX_COPY_RANGE)
735 * nla_len includes the header length. Thus, the maximum packet 739 queue->copy_range = NFQNL_MAX_COPY_RANGE;
736 * length that we support is 65531 bytes. We send truncated
737 * packets if the specified length is larger than that.
738 */
739 if (range > 0xffff - NLA_HDRLEN)
740 queue->copy_range = 0xffff - NLA_HDRLEN;
741 else 740 else
742 queue->copy_range = range; 741 queue->copy_range = range;
743 break; 742 break;
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index a60261cb0e80..da35ac06a975 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -26,6 +26,9 @@ static inline int xt_ct_target(struct sk_buff *skb, struct nf_conn *ct)
26 if (skb->nfct != NULL) 26 if (skb->nfct != NULL)
27 return XT_CONTINUE; 27 return XT_CONTINUE;
28 28
29 /* special case the untracked ct : we want the percpu object */
30 if (!ct)
31 ct = nf_ct_untracked_get();
29 atomic_inc(&ct->ct_general.use); 32 atomic_inc(&ct->ct_general.use);
30 skb->nfct = &ct->ct_general; 33 skb->nfct = &ct->ct_general;
31 skb->nfctinfo = IP_CT_NEW; 34 skb->nfctinfo = IP_CT_NEW;
@@ -186,8 +189,7 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par,
186 int ret = -EOPNOTSUPP; 189 int ret = -EOPNOTSUPP;
187 190
188 if (info->flags & XT_CT_NOTRACK) { 191 if (info->flags & XT_CT_NOTRACK) {
189 ct = nf_ct_untracked_get(); 192 ct = NULL;
190 atomic_inc(&ct->ct_general.use);
191 goto out; 193 goto out;
192 } 194 }
193 195
@@ -311,7 +313,7 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
311 struct nf_conn *ct = info->ct; 313 struct nf_conn *ct = info->ct;
312 struct nf_conn_help *help; 314 struct nf_conn_help *help;
313 315
314 if (!nf_ct_is_untracked(ct)) { 316 if (ct && !nf_ct_is_untracked(ct)) {
315 help = nfct_help(ct); 317 help = nfct_help(ct);
316 if (help) 318 if (help)
317 module_put(help->helper->me); 319 module_put(help->helper->me);
@@ -319,8 +321,8 @@ static void xt_ct_tg_destroy(const struct xt_tgdtor_param *par,
319 nf_ct_l3proto_module_put(par->family); 321 nf_ct_l3proto_module_put(par->family);
320 322
321 xt_ct_destroy_timeout(ct); 323 xt_ct_destroy_timeout(ct);
324 nf_ct_put(info->ct);
322 } 325 }
323 nf_ct_put(info->ct);
324} 326}
325 327
326static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) 328static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par)
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
index 63b2bdb59e95..02704245710e 100644
--- a/net/netfilter/xt_socket.c
+++ b/net/netfilter/xt_socket.c
@@ -107,7 +107,7 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
107{ 107{
108 const struct iphdr *iph = ip_hdr(skb); 108 const struct iphdr *iph = ip_hdr(skb);
109 struct udphdr _hdr, *hp = NULL; 109 struct udphdr _hdr, *hp = NULL;
110 struct sock *sk; 110 struct sock *sk = skb->sk;
111 __be32 uninitialized_var(daddr), uninitialized_var(saddr); 111 __be32 uninitialized_var(daddr), uninitialized_var(saddr);
112 __be16 uninitialized_var(dport), uninitialized_var(sport); 112 __be16 uninitialized_var(dport), uninitialized_var(sport);
113 u8 uninitialized_var(protocol); 113 u8 uninitialized_var(protocol);
@@ -155,9 +155,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
155 } 155 }
156#endif 156#endif
157 157
158 sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol, 158 if (!sk)
159 saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY); 159 sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
160 if (sk != NULL) { 160 saddr, daddr, sport, dport,
161 par->in, NFT_LOOKUP_ANY);
162 if (sk) {
161 bool wildcard; 163 bool wildcard;
162 bool transparent = true; 164 bool transparent = true;
163 165
@@ -173,7 +175,8 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
173 (sk->sk_state == TCP_TIME_WAIT && 175 (sk->sk_state == TCP_TIME_WAIT &&
174 inet_twsk(sk)->tw_transparent)); 176 inet_twsk(sk)->tw_transparent));
175 177
176 xt_socket_put_sk(sk); 178 if (sk != skb->sk)
179 xt_socket_put_sk(sk);
177 180
178 if (wildcard || !transparent) 181 if (wildcard || !transparent)
179 sk = NULL; 182 sk = NULL;
@@ -260,7 +263,7 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
260{ 263{
261 struct ipv6hdr *iph = ipv6_hdr(skb); 264 struct ipv6hdr *iph = ipv6_hdr(skb);
262 struct udphdr _hdr, *hp = NULL; 265 struct udphdr _hdr, *hp = NULL;
263 struct sock *sk; 266 struct sock *sk = skb->sk;
264 struct in6_addr *daddr = NULL, *saddr = NULL; 267 struct in6_addr *daddr = NULL, *saddr = NULL;
265 __be16 uninitialized_var(dport), uninitialized_var(sport); 268 __be16 uninitialized_var(dport), uninitialized_var(sport);
266 int thoff = 0, uninitialized_var(tproto); 269 int thoff = 0, uninitialized_var(tproto);
@@ -291,9 +294,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
291 return false; 294 return false;
292 } 295 }
293 296
294 sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto, 297 if (!sk)
295 saddr, daddr, sport, dport, par->in, NFT_LOOKUP_ANY); 298 sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
296 if (sk != NULL) { 299 saddr, daddr, sport, dport,
300 par->in, NFT_LOOKUP_ANY);
301 if (sk) {
297 bool wildcard; 302 bool wildcard;
298 bool transparent = true; 303 bool transparent = true;
299 304
@@ -309,7 +314,8 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
309 (sk->sk_state == TCP_TIME_WAIT && 314 (sk->sk_state == TCP_TIME_WAIT &&
310 inet_twsk(sk)->tw_transparent)); 315 inet_twsk(sk)->tw_transparent));
311 316
312 xt_socket_put_sk(sk); 317 if (sk != skb->sk)
318 xt_socket_put_sk(sk);
313 319
314 if (wildcard || !transparent) 320 if (wildcard || !transparent)
315 sk = NULL; 321 sk = NULL;