diff options
author | David S. Miller <davem@davemloft.net> | 2013-06-06 04:03:06 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-06 04:03:06 -0400 |
commit | 143554ace8919d5ef3cc8424c0b06dbd3d671b4e (patch) | |
tree | ab1c540cf8086c513aa7c0f831fb556263bf72d7 /net/netfilter | |
parent | 6bc19fb82d4c05a9eee19d6d2aab2ce26e499ec2 (diff) | |
parent | 7f87712c0152511a1842698ad8dca425fee2dc4f (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.c | 21 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_conn.c | 23 | ||||
-rw-r--r-- | net/netfilter/ipvs/ip_vs_ctl.c | 4 | ||||
-rw-r--r-- | net/netfilter/nf_conntrack_ftp.c | 73 | ||||
-rw-r--r-- | net/netfilter/nf_log.c | 4 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_queue_core.c | 29 | ||||
-rw-r--r-- | net/netfilter/xt_CT.c | 10 | ||||
-rw-r--r-- | net/netfilter/xt_socket.c | 26 |
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 | ||
307 | void __init netfilter_init(void) | 307 | int __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"); | 325 | err_pernet: |
326 | unregister_pernet_subsys(&netfilter_net_ops); | ||
327 | err: | ||
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 | ||
1269 | flush_again: | 1264 | flush_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); |
56 | EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); | 56 | EXPORT_SYMBOL_GPL(nf_nat_ftp_hook); |
57 | 57 | ||
58 | static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, char); | 58 | static int try_rfc959(const char *, size_t, struct nf_conntrack_man *, |
59 | static int try_eprt(const char *, size_t, struct nf_conntrack_man *, char); | 59 | char, unsigned int *); |
60 | static int try_rfc1123(const char *, size_t, struct nf_conntrack_man *, | ||
61 | char, unsigned int *); | ||
62 | static int try_eprt(const char *, size_t, struct nf_conntrack_man *, | ||
63 | char, unsigned int *); | ||
60 | static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, | 64 | static int try_epsv_response(const char *, size_t, struct nf_conntrack_man *, |
61 | char); | 65 | char, unsigned int *); |
62 | 66 | ||
63 | static struct ftp_search { | 67 | static 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 */ |
150 | static int try_rfc959(const char *data, size_t dlen, | 153 | static 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 | */ | ||
180 | static 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 */ |
167 | static int get_port(const char *data, int start, size_t dlen, char delim, | 198 | static 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| */ |
193 | static int try_eprt(const char *data, size_t dlen, struct nf_conntrack_man *cmd, | 224 | static 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| */ |
241 | static int try_epsv_response(const char *data, size_t dlen, | 272 | static 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 | ||
370 | out_sysctl: | 370 | out_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 | |||
44 | struct nfqnl_instance { | 52 | struct 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 | ||
326 | static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) | 328 | static 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; |