aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@netfilter.org>2012-09-24 08:52:12 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2012-09-24 09:10:29 -0400
commit6ee584be3ee30f72dec8a8ca87bc10824e27a631 (patch)
tree23306d3404c684e05bf537c9d4df7df572663509
parentba8d3b0bf5900b9ee5354e7d73358867763a6766 (diff)
netfilter: nfnetlink_queue: add NFQA_CAP_LEN attribute
This patch adds the NFQA_CAP_LEN attribute that allows us to know what is the real packet size from user-space (even if we decided to retrieve just a few bytes from the packet instead of all of it). Security software that inspects packets should always check for this new attribute to make sure that it is inspecting the entire packet. This also helps to provide a workaround for the problem described in: http://marc.info/?l=netfilter-devel&m=134519473212536&w=2 Original idea from Florian Westphal. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
-rw-r--r--include/linux/netfilter/nfnetlink_queue.h1
-rw-r--r--net/netfilter/nfnetlink_queue_core.c9
2 files changed, 8 insertions, 2 deletions
diff --git a/include/linux/netfilter/nfnetlink_queue.h b/include/linux/netfilter/nfnetlink_queue.h
index 3b1c1360aedf..70ec8c2bc11a 100644
--- a/include/linux/netfilter/nfnetlink_queue.h
+++ b/include/linux/netfilter/nfnetlink_queue.h
@@ -44,6 +44,7 @@ enum nfqnl_attr_type {
44 NFQA_PAYLOAD, /* opaque data payload */ 44 NFQA_PAYLOAD, /* opaque data payload */
45 NFQA_CT, /* nf_conntrack_netlink.h */ 45 NFQA_CT, /* nf_conntrack_netlink.h */
46 NFQA_CT_INFO, /* enum ip_conntrack_info */ 46 NFQA_CT_INFO, /* enum ip_conntrack_info */
47 NFQA_CAP_LEN, /* __u32 length of captured packet */
47 48
48 __NFQA_MAX 49 __NFQA_MAX
49}; 50};
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index 3e4ddcb7e781..e12d44e75b21 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -225,7 +225,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
225{ 225{
226 sk_buff_data_t old_tail; 226 sk_buff_data_t old_tail;
227 size_t size; 227 size_t size;
228 size_t data_len = 0; 228 size_t data_len = 0, cap_len = 0;
229 struct sk_buff *skb; 229 struct sk_buff *skb;
230 struct nlattr *nla; 230 struct nlattr *nla;
231 struct nfqnl_msg_packet_hdr *pmsg; 231 struct nfqnl_msg_packet_hdr *pmsg;
@@ -247,7 +247,8 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
247#endif 247#endif
248 + nla_total_size(sizeof(u_int32_t)) /* mark */ 248 + nla_total_size(sizeof(u_int32_t)) /* mark */
249 + nla_total_size(sizeof(struct nfqnl_msg_packet_hw)) 249 + nla_total_size(sizeof(struct nfqnl_msg_packet_hw))
250 + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)); 250 + nla_total_size(sizeof(struct nfqnl_msg_packet_timestamp)
251 + nla_total_size(sizeof(u_int32_t))); /* cap_len */
251 252
252 outdev = entry->outdev; 253 outdev = entry->outdev;
253 254
@@ -266,6 +267,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
266 data_len = entskb->len; 267 data_len = entskb->len;
267 268
268 size += nla_total_size(data_len); 269 size += nla_total_size(data_len);
270 cap_len = entskb->len;
269 break; 271 break;
270 } 272 }
271 273
@@ -402,6 +404,9 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue,
402 if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0) 404 if (ct && nfqnl_ct_put(skb, ct, ctinfo) < 0)
403 goto nla_put_failure; 405 goto nla_put_failure;
404 406
407 if (cap_len > 0 && nla_put_be32(skb, NFQA_CAP_LEN, htonl(cap_len)))
408 goto nla_put_failure;
409
405 nlh->nlmsg_len = skb->tail - old_tail; 410 nlh->nlmsg_len = skb->tail - old_tail;
406 return skb; 411 return skb;
407 412