From 927ccbcc28dceee29dad876982768cca29738564 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Tue, 9 Aug 2005 20:03:40 -0700 Subject: [PATCH] [NETFILTER]: attribute count is an attribute of message type, not subsytem Prior to this patch, every nfnetlink subsystem had to specify it's attribute count. However, in reality the attribute count depends on the message type within the subsystem, not the subsystem itself. This patch moves 'attr_count' from 'struct nfnetlink_subsys' into nfnl_callback to fix this. Signed-off-by: Harald Welte Signed-off-by: David S. Miller --- include/linux/netfilter/nfnetlink.h | 4 ++-- net/ipv4/netfilter/ip_conntrack_netlink.c | 9 +++++++-- net/netfilter/nfnetlink.c | 20 ++++++++++++++++---- net/netfilter/nfnetlink_log.c | 5 +++-- net/netfilter/nfnetlink_queue.c | 4 +++- 5 files changed, 31 insertions(+), 11 deletions(-) diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 561f9df28808..b0feb2374079 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h @@ -85,9 +85,10 @@ struct nfgenmsg { struct nfnl_callback { - kernel_cap_t cap_required; /* capabilities required for this msg */ int (*call)(struct sock *nl, struct sk_buff *skb, struct nlmsghdr *nlh, struct nfattr *cda[], int *errp); + kernel_cap_t cap_required; /* capabilities required for this msg */ + u_int16_t attr_count; /* number of nfattr's */ }; struct nfnetlink_subsystem @@ -95,7 +96,6 @@ struct nfnetlink_subsystem const char *name; __u8 subsys_id; /* nfnetlink subsystem ID */ __u8 cb_count; /* number of callbacks */ - u_int32_t attr_count; /* number of nfattr's */ struct nfnl_callback *cb; /* callback for individual types */ }; diff --git a/net/ipv4/netfilter/ip_conntrack_netlink.c b/net/ipv4/netfilter/ip_conntrack_netlink.c index 23f18f6a5535..53d98974dcf0 100644 --- a/net/ipv4/netfilter/ip_conntrack_netlink.c +++ b/net/ipv4/netfilter/ip_conntrack_netlink.c @@ -1484,21 +1484,28 @@ static struct notifier_block ctnl_notifier_exp = { static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack, + .attr_count = CTA_MAX, .cap_required = CAP_NET_ADMIN }, [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack, + .attr_count = CTA_MAX, .cap_required = CAP_NET_ADMIN }, [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack, + .attr_count = CTA_MAX, .cap_required = CAP_NET_ADMIN }, [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, + .attr_count = CTA_MAX, .cap_required = CAP_NET_ADMIN }, }; static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_MAX] = { [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect, + .attr_count = CTA_EXPECT_MAX, .cap_required = CAP_NET_ADMIN }, [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect, + .attr_count = CTA_EXPECT_MAX, .cap_required = CAP_NET_ADMIN }, [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, + .attr_count = CTA_EXPECT_MAX, .cap_required = CAP_NET_ADMIN }, }; @@ -1506,7 +1513,6 @@ static struct nfnetlink_subsystem ctnl_subsys = { .name = "conntrack", .subsys_id = NFNL_SUBSYS_CTNETLINK, .cb_count = IPCTNL_MSG_MAX, - .attr_count = CTA_MAX, .cb = ctnl_cb, }; @@ -1514,7 +1520,6 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = { .name = "conntrack_expect", .subsys_id = NFNL_SUBSYS_CTNETLINK_EXP, .cb_count = IPCTNL_MSG_EXP_MAX, - .attr_count = CTA_MAX, .cb = ctnl_exp_cb, }; diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 30b25f47f7cc..578e4fe40945 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c @@ -155,8 +155,18 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys, struct nlmsghdr *nlh, struct nfattr *cda[]) { int min_len; + u_int16_t attr_count; + u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type); - memset(cda, 0, sizeof(struct nfattr *) * subsys->attr_count); + if (unlikely(cb_id >= subsys->cb_count)) { + DEBUGP("msgtype %u >= %u, returning\n", + cb_id, subsys->cb_count); + return -EINVAL; + } + + attr_count = subsys->cb[cb_id].attr_count; + + memset(cda, 0, sizeof(struct nfattr *) * attr_count); /* check attribute lengths. */ min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg)); @@ -170,7 +180,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys, while (NFA_OK(attr, attrlen)) { unsigned flavor = attr->nfa_type; if (flavor) { - if (flavor > subsys->attr_count) + if (flavor > attr_count) return -EINVAL; cda[flavor - 1] = attr; } @@ -256,9 +266,11 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb, } { - struct nfattr *cda[ss->attr_count]; + u_int16_t attr_count = + ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count; + struct nfattr *cda[attr_count]; - memset(cda, 0, ss->attr_count*sizeof(struct nfattr *)); + memset(cda, 0, sizeof(struct nfattr *) * attr_count); err = nfnetlink_check_attributes(ss, nlh, cda); if (err < 0) diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index f41045e385ae..1750f0d6e4de 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c @@ -805,8 +805,10 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = { [NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp, - .cap_required = CAP_NET_ADMIN }, + .attr_count = NFULA_MAX, + .cap_required = CAP_NET_ADMIN, }, [NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config, + .attr_count = NFULA_CFG_MAX, .cap_required = CAP_NET_ADMIN }, }; @@ -814,7 +816,6 @@ static struct nfnetlink_subsystem nfulnl_subsys = { .name = "log", .subsys_id = NFNL_SUBSYS_ULOG, .cb_count = NFULNL_MSG_MAX, - .attr_count = NFULA_MAX, .cb = nfulnl_cb, }; diff --git a/net/netfilter/nfnetlink_queue.c b/net/netfilter/nfnetlink_queue.c index d7b0330d64b4..04323ee1eb8d 100644 --- a/net/netfilter/nfnetlink_queue.c +++ b/net/netfilter/nfnetlink_queue.c @@ -877,10 +877,13 @@ nfqnl_recv_config(struct sock *ctnl, struct sk_buff *skb, static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp, + .attr_count = NFQA_MAX, .cap_required = CAP_NET_ADMIN }, [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict, + .attr_count = NFQA_MAX, .cap_required = CAP_NET_ADMIN }, [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, + .attr_count = NFQA_CFG_MAX, .cap_required = CAP_NET_ADMIN }, }; @@ -888,7 +891,6 @@ static struct nfnetlink_subsystem nfqnl_subsys = { .name = "nf_queue", .subsys_id = NFNL_SUBSYS_QUEUE, .cb_count = NFQNL_MSG_MAX, - .attr_count = NFQA_MAX, .cb = nfqnl_cb, };