From cabaa9bfb01eb4cee97ffb8a18405f4c5175d3d9 Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 10 Mar 2008 16:41:43 -0700 Subject: [NETFILTER]: nfnetlink_queue: fix computation of allocated size for netlink skb. Size of the netlink skb was wrongly computed because the formula was using NLMSG_ALIGN instead of NLMSG_SPACE. NLMSG_ALIGN does not add the room for netlink header as NLMSG_SPACE does. This was causing a failure of message building in some cases. On my test system, all messages for packets in range [8*k+41, 8*k+48] where k is an integer were invalid and the corresponding packets were dropped. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index 0043d3a9f87..c0cc3d3618a 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -224,7 +224,7 @@ nfqnl_build_packet_message(struct nfqnl_instance *queue, struct net_device *indev; struct net_device *outdev; - size = NLMSG_ALIGN(sizeof(struct nfgenmsg)) + size = NLMSG_SPACE(sizeof(struct nfgenmsg)) + nla_total_size(sizeof(struct nfqnl_msg_packet_hdr)) + nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ -- cgit v1.2.3 From 7000d38d6126d6ef928605bdacebc9f12279c5aa Mon Sep 17 00:00:00 2001 From: Eric Leblond Date: Mon, 10 Mar 2008 16:42:04 -0700 Subject: [NETFILTER]: nfnetlink_log: fix computation of netlink skb size This patch is similar to nfnetlink_queue fixes. It fixes the computation of skb size by using NLMSG_SPACE instead of NLMSG_ALIGN. Signed-off-by: Eric Leblond Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 7efa40d4739..c6802c0d6ed 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -556,7 +556,7 @@ nfulnl_log_packet(unsigned int pf, /* FIXME: do we want to make the size calculation conditional based on * what is actually present? way more branches and checks, but more * memory efficient... */ - size = NLMSG_ALIGN(sizeof(struct nfgenmsg)) + size = NLMSG_SPACE(sizeof(struct nfgenmsg)) + nla_total_size(sizeof(struct nfulnl_msg_packet_hdr)) + nla_total_size(sizeof(u_int32_t)) /* ifindex */ + nla_total_size(sizeof(u_int32_t)) /* ifindex */ -- cgit v1.2.3 From 4f4c9430cf5ee1ca3567bc88faf8b4c18ed0bd13 Mon Sep 17 00:00:00 2001 From: Jan Engelhardt Date: Mon, 10 Mar 2008 16:42:40 -0700 Subject: [NETFILTER]: xt_time: fix failure to match on Sundays From: Andrew Schulman xt_time_match() in net/netfilter/xt_time.c in kernel 2.6.24 never matches on Sundays. On my host I have a rule like iptables -A OUTPUT -m time --weekdays Sun -j REJECT and it never matches. The problem is in localtime_2(), which uses r->weekday = (4 + r->dse) % 7; to map the epoch day onto a weekday in {0,...,6}. In particular this gives 0 for Sundays. But 0 has to be wrong; a weekday of 0 can never match. xt_time_match() has if (!(info->weekdays_match & (1 << current_time.weekday))) return false; and when current_time.weekday = 0, the result of the & is always zero, even when info->weekdays_match = XT_TIME_ALL_WEEKDAYS = 0xFE. Signed-off-by: Jan Engelhardt Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/xt_time.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net/netfilter') diff --git a/net/netfilter/xt_time.c b/net/netfilter/xt_time.c index e9a8794bc3a..9fa2e082470 100644 --- a/net/netfilter/xt_time.c +++ b/net/netfilter/xt_time.c @@ -95,8 +95,11 @@ static inline void localtime_2(struct xtm *r, time_t time) */ r->dse = time / 86400; - /* 1970-01-01 (w=0) was a Thursday (4). */ - r->weekday = (4 + r->dse) % 7; + /* + * 1970-01-01 (w=0) was a Thursday (4). + * -1 and +1 map Sunday properly onto 7. + */ + r->weekday = (4 + r->dse - 1) % 7 + 1; } static void localtime_3(struct xtm *r, time_t time) -- cgit v1.2.3 From 3d89e9cf3690b4645ce73b86c219c8188f8fa50a Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 10 Mar 2008 16:43:10 -0700 Subject: [NETFILTER]: nf_conntrack: add \n to "expectation table full" message Signed-off-by: Alexey Dobriyan Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_expect.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index e06bf0028bb..684ec9c1ad3 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c @@ -381,7 +381,7 @@ int nf_ct_expect_related(struct nf_conntrack_expect *expect) if (nf_ct_expect_count >= nf_ct_expect_max) { if (net_ratelimit()) printk(KERN_WARNING - "nf_conntrack: expectation table full"); + "nf_conntrack: expectation table full\n"); ret = -EMFILE; goto out; } -- cgit v1.2.3 From 019f692ea719a2da17606511d2648b8cc1762268 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Mon, 10 Mar 2008 16:43:41 -0700 Subject: [NETFILTER]: nf_conntrack: replace horrible hack with ksize() There's a horrible slab abuse in net/netfilter/nf_conntrack_extend.c that can be replaced with a call to ksize(). Cc: Christoph Lameter Signed-off-by: Pekka Enberg Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_conntrack_extend.c | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nf_conntrack_extend.c b/net/netfilter/nf_conntrack_extend.c index 8b9be1e978c..2bd9963b5b3 100644 --- a/net/netfilter/nf_conntrack_extend.c +++ b/net/netfilter/nf_conntrack_extend.c @@ -19,14 +19,6 @@ static struct nf_ct_ext_type *nf_ct_ext_types[NF_CT_EXT_NUM]; static DEFINE_MUTEX(nf_ct_ext_type_mutex); -/* Horrible trick to figure out smallest amount worth kmallocing. */ -#define CACHE(x) (x) + 0 * -enum { - NF_CT_EXT_MIN_SIZE = -#include - 1 }; -#undef CACHE - void __nf_ct_ext_destroy(struct nf_conn *ct) { unsigned int i; @@ -53,7 +45,7 @@ EXPORT_SYMBOL(__nf_ct_ext_destroy); static void * nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) { - unsigned int off, len, real_len; + unsigned int off, len; struct nf_ct_ext_type *t; rcu_read_lock(); @@ -61,16 +53,14 @@ nf_ct_ext_create(struct nf_ct_ext **ext, enum nf_ct_ext_id id, gfp_t gfp) BUG_ON(t == NULL); off = ALIGN(sizeof(struct nf_ct_ext), t->align); len = off + t->len; - real_len = t->alloc_size; rcu_read_unlock(); - *ext = kzalloc(real_len, gfp); + *ext = kzalloc(t->alloc_size, gfp); if (!*ext) return NULL; (*ext)->offset[id] = off; (*ext)->len = len; - (*ext)->real_len = real_len; return (void *)(*ext) + off; } @@ -95,7 +85,7 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) newlen = newoff + t->len; rcu_read_unlock(); - if (newlen >= ct->ext->real_len) { + if (newlen >= ksize(ct->ext)) { new = kmalloc(newlen, gfp); if (!new) return NULL; @@ -114,7 +104,6 @@ void *__nf_ct_ext_add(struct nf_conn *ct, enum nf_ct_ext_id id, gfp_t gfp) rcu_read_unlock(); } kfree(ct->ext); - new->real_len = newlen; ct->ext = new; } @@ -156,8 +145,6 @@ static void update_alloc_size(struct nf_ct_ext_type *type) t1->alloc_size = ALIGN(t1->alloc_size, t2->align) + t2->len; } - if (t1->alloc_size < NF_CT_EXT_MIN_SIZE) - t1->alloc_size = NF_CT_EXT_MIN_SIZE; } } -- cgit v1.2.3 From b7047a1c886386b10a103b4fea26678db8b57832 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 10 Mar 2008 16:44:13 -0700 Subject: [NETFILTER]: nfnetlink_log: fix EPERM when binding/unbinding and instance 0 exists When binding or unbinding to an address family, the res_id is usually set to zero. When logging instance 0 already exists and is owned by a different process, this makes nfunl_recv_config return -EPERM without performing the bind operation. Since no operation on the foreign logging instance itself was requested, this is incorrect. Move bind/unbind commands before the queue instance permissions checks. Also remove an incorrect comment. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_log.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index c6802c0d6ed..bf3f19b21fe 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -702,20 +702,30 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, struct nfgenmsg *nfmsg = NLMSG_DATA(nlh); u_int16_t group_num = ntohs(nfmsg->res_id); struct nfulnl_instance *inst; + struct nfulnl_msg_config_cmd *cmd = NULL; int ret = 0; + if (nfula[NFULA_CFG_CMD]) { + u_int8_t pf = nfmsg->nfgen_family; + cmd = nla_data(nfula[NFULA_CFG_CMD]); + + /* Commands without queue context */ + switch (cmd->command) { + case NFULNL_CFG_CMD_PF_BIND: + return nf_log_register(pf, &nfulnl_logger); + case NFULNL_CFG_CMD_PF_UNBIND: + nf_log_unregister_pf(pf); + return 0; + } + } + inst = instance_lookup_get(group_num); if (inst && inst->peer_pid != NETLINK_CB(skb).pid) { ret = -EPERM; goto out_put; } - if (nfula[NFULA_CFG_CMD]) { - u_int8_t pf = nfmsg->nfgen_family; - struct nfulnl_msg_config_cmd *cmd; - - cmd = nla_data(nfula[NFULA_CFG_CMD]); - + if (cmd != NULL) { switch (cmd->command) { case NFULNL_CFG_CMD_BIND: if (inst) { @@ -738,14 +748,6 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, instance_destroy(inst); goto out; - case NFULNL_CFG_CMD_PF_BIND: - ret = nf_log_register(pf, &nfulnl_logger); - break; - case NFULNL_CFG_CMD_PF_UNBIND: - /* This is a bug and a feature. We cannot unregister - * other handlers, like nfnetlink_inst can */ - nf_log_unregister_pf(pf); - break; default: ret = -ENOTSUPP; break; -- cgit v1.2.3 From 914afea84e3e20cdbcd040f8387a0e6ef20ffc97 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 10 Mar 2008 16:44:36 -0700 Subject: [NETFILTER]: nfnetlink_queue: fix EPERM when binding/unbinding and instance 0 exists Similar to the nfnetlink_log problem, nfnetlink_queue incorrectly returns -EPERM when binding or unbinding to an address family and queueing instance 0 exists and is owned by a different process. Unlike nfnetlink_log it previously completes the operation, but it is still incorrect. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nfnetlink_queue.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index c0cc3d3618a..012cb691082 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -703,19 +703,12 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, /* Commands without queue context - might sleep */ switch (cmd->command) { case NFQNL_CFG_CMD_PF_BIND: - ret = nf_register_queue_handler(ntohs(cmd->pf), - &nfqh); - break; + return nf_register_queue_handler(ntohs(cmd->pf), + &nfqh); case NFQNL_CFG_CMD_PF_UNBIND: - ret = nf_unregister_queue_handler(ntohs(cmd->pf), - &nfqh); - break; - default: - break; + return nf_unregister_queue_handler(ntohs(cmd->pf), + &nfqh); } - - if (ret < 0) - return ret; } rcu_read_lock(); -- cgit v1.2.3 From 94be1a3f365e2b9f2615575d7fef16a0bad106a3 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 10 Mar 2008 16:45:05 -0700 Subject: [NETFILTER]: nf_queue: don't return error when unregistering a non-existant handler Commit ce7663d84: [NETFILTER]: nfnetlink_queue: don't unregister handler of other subsystem changed nf_unregister_queue_handler to return an error when attempting to unregister a queue handler that is not identical to the one passed in. This is correct in case we really do have a different queue handler already registered, but some existing userspace code always does an unbind before bind and aborts if that fails, so try to be nice and return success in that case. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/netfilter/nf_queue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/netfilter') diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index bfc2928c191..ddc80ea114c 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c @@ -51,7 +51,7 @@ int nf_unregister_queue_handler(int pf, const struct nf_queue_handler *qh) return -EINVAL; mutex_lock(&queue_handler_mutex); - if (queue_handler[pf] != qh) { + if (queue_handler[pf] && queue_handler[pf] != qh) { mutex_unlock(&queue_handler_mutex); return -EINVAL; } -- cgit v1.2.3