aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/nfnetlink.h4
-rw-r--r--net/ipv4/netfilter/ip_conntrack_netlink.c9
-rw-r--r--net/netfilter/nfnetlink.c20
-rw-r--r--net/netfilter/nfnetlink_log.c5
-rw-r--r--net/netfilter/nfnetlink_queue.c4
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 {
85 85
86struct nfnl_callback 86struct nfnl_callback
87{ 87{
88 kernel_cap_t cap_required; /* capabilities required for this msg */
89 int (*call)(struct sock *nl, struct sk_buff *skb, 88 int (*call)(struct sock *nl, struct sk_buff *skb,
90 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp); 89 struct nlmsghdr *nlh, struct nfattr *cda[], int *errp);
90 kernel_cap_t cap_required; /* capabilities required for this msg */
91 u_int16_t attr_count; /* number of nfattr's */
91}; 92};
92 93
93struct nfnetlink_subsystem 94struct nfnetlink_subsystem
@@ -95,7 +96,6 @@ struct nfnetlink_subsystem
95 const char *name; 96 const char *name;
96 __u8 subsys_id; /* nfnetlink subsystem ID */ 97 __u8 subsys_id; /* nfnetlink subsystem ID */
97 __u8 cb_count; /* number of callbacks */ 98 __u8 cb_count; /* number of callbacks */
98 u_int32_t attr_count; /* number of nfattr's */
99 struct nfnl_callback *cb; /* callback for individual types */ 99 struct nfnl_callback *cb; /* callback for individual types */
100}; 100};
101 101
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 = {
1484 1484
1485static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { 1485static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = {
1486 [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack, 1486 [IPCTNL_MSG_CT_NEW] = { .call = ctnetlink_new_conntrack,
1487 .attr_count = CTA_MAX,
1487 .cap_required = CAP_NET_ADMIN }, 1488 .cap_required = CAP_NET_ADMIN },
1488 [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack, 1489 [IPCTNL_MSG_CT_GET] = { .call = ctnetlink_get_conntrack,
1490 .attr_count = CTA_MAX,
1489 .cap_required = CAP_NET_ADMIN }, 1491 .cap_required = CAP_NET_ADMIN },
1490 [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack, 1492 [IPCTNL_MSG_CT_DELETE] = { .call = ctnetlink_del_conntrack,
1493 .attr_count = CTA_MAX,
1491 .cap_required = CAP_NET_ADMIN }, 1494 .cap_required = CAP_NET_ADMIN },
1492 [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack, 1495 [IPCTNL_MSG_CT_GET_CTRZERO] = { .call = ctnetlink_get_conntrack,
1496 .attr_count = CTA_MAX,
1493 .cap_required = CAP_NET_ADMIN }, 1497 .cap_required = CAP_NET_ADMIN },
1494}; 1498};
1495 1499
1496static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_MAX] = { 1500static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_MAX] = {
1497 [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect, 1501 [IPCTNL_MSG_EXP_GET] = { .call = ctnetlink_get_expect,
1502 .attr_count = CTA_EXPECT_MAX,
1498 .cap_required = CAP_NET_ADMIN }, 1503 .cap_required = CAP_NET_ADMIN },
1499 [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect, 1504 [IPCTNL_MSG_EXP_NEW] = { .call = ctnetlink_new_expect,
1505 .attr_count = CTA_EXPECT_MAX,
1500 .cap_required = CAP_NET_ADMIN }, 1506 .cap_required = CAP_NET_ADMIN },
1501 [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect, 1507 [IPCTNL_MSG_EXP_DELETE] = { .call = ctnetlink_del_expect,
1508 .attr_count = CTA_EXPECT_MAX,
1502 .cap_required = CAP_NET_ADMIN }, 1509 .cap_required = CAP_NET_ADMIN },
1503}; 1510};
1504 1511
@@ -1506,7 +1513,6 @@ static struct nfnetlink_subsystem ctnl_subsys = {
1506 .name = "conntrack", 1513 .name = "conntrack",
1507 .subsys_id = NFNL_SUBSYS_CTNETLINK, 1514 .subsys_id = NFNL_SUBSYS_CTNETLINK,
1508 .cb_count = IPCTNL_MSG_MAX, 1515 .cb_count = IPCTNL_MSG_MAX,
1509 .attr_count = CTA_MAX,
1510 .cb = ctnl_cb, 1516 .cb = ctnl_cb,
1511}; 1517};
1512 1518
@@ -1514,7 +1520,6 @@ static struct nfnetlink_subsystem ctnl_exp_subsys = {
1514 .name = "conntrack_expect", 1520 .name = "conntrack_expect",
1515 .subsys_id = NFNL_SUBSYS_CTNETLINK_EXP, 1521 .subsys_id = NFNL_SUBSYS_CTNETLINK_EXP,
1516 .cb_count = IPCTNL_MSG_EXP_MAX, 1522 .cb_count = IPCTNL_MSG_EXP_MAX,
1517 .attr_count = CTA_MAX,
1518 .cb = ctnl_exp_cb, 1523 .cb = ctnl_exp_cb,
1519}; 1524};
1520 1525
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,
155 struct nlmsghdr *nlh, struct nfattr *cda[]) 155 struct nlmsghdr *nlh, struct nfattr *cda[])
156{ 156{
157 int min_len; 157 int min_len;
158 u_int16_t attr_count;
159 u_int8_t cb_id = NFNL_MSG_TYPE(nlh->nlmsg_type);
158 160
159 memset(cda, 0, sizeof(struct nfattr *) * subsys->attr_count); 161 if (unlikely(cb_id >= subsys->cb_count)) {
162 DEBUGP("msgtype %u >= %u, returning\n",
163 cb_id, subsys->cb_count);
164 return -EINVAL;
165 }
166
167 attr_count = subsys->cb[cb_id].attr_count;
168
169 memset(cda, 0, sizeof(struct nfattr *) * attr_count);
160 170
161 /* check attribute lengths. */ 171 /* check attribute lengths. */
162 min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg)); 172 min_len = NLMSG_ALIGN(sizeof(struct nfgenmsg));
@@ -170,7 +180,7 @@ nfnetlink_check_attributes(struct nfnetlink_subsystem *subsys,
170 while (NFA_OK(attr, attrlen)) { 180 while (NFA_OK(attr, attrlen)) {
171 unsigned flavor = attr->nfa_type; 181 unsigned flavor = attr->nfa_type;
172 if (flavor) { 182 if (flavor) {
173 if (flavor > subsys->attr_count) 183 if (flavor > attr_count)
174 return -EINVAL; 184 return -EINVAL;
175 cda[flavor - 1] = attr; 185 cda[flavor - 1] = attr;
176 } 186 }
@@ -256,9 +266,11 @@ static inline int nfnetlink_rcv_msg(struct sk_buff *skb,
256 } 266 }
257 267
258 { 268 {
259 struct nfattr *cda[ss->attr_count]; 269 u_int16_t attr_count =
270 ss->cb[NFNL_MSG_TYPE(nlh->nlmsg_type)].attr_count;
271 struct nfattr *cda[attr_count];
260 272
261 memset(cda, 0, ss->attr_count*sizeof(struct nfattr *)); 273 memset(cda, 0, sizeof(struct nfattr *) * attr_count);
262 274
263 err = nfnetlink_check_attributes(ss, nlh, cda); 275 err = nfnetlink_check_attributes(ss, nlh, cda);
264 if (err < 0) 276 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 @@ out_put:
805 805
806static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = { 806static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = {
807 [NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp, 807 [NFULNL_MSG_PACKET] = { .call = nfulnl_recv_unsupp,
808 .cap_required = CAP_NET_ADMIN }, 808 .attr_count = NFULA_MAX,
809 .cap_required = CAP_NET_ADMIN, },
809 [NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config, 810 [NFULNL_MSG_CONFIG] = { .call = nfulnl_recv_config,
811 .attr_count = NFULA_CFG_MAX,
810 .cap_required = CAP_NET_ADMIN }, 812 .cap_required = CAP_NET_ADMIN },
811}; 813};
812 814
@@ -814,7 +816,6 @@ static struct nfnetlink_subsystem nfulnl_subsys = {
814 .name = "log", 816 .name = "log",
815 .subsys_id = NFNL_SUBSYS_ULOG, 817 .subsys_id = NFNL_SUBSYS_ULOG,
816 .cb_count = NFULNL_MSG_MAX, 818 .cb_count = NFULNL_MSG_MAX,
817 .attr_count = NFULA_MAX,
818 .cb = nfulnl_cb, 819 .cb = nfulnl_cb,
819}; 820};
820 821
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 @@ out_put:
877 877
878static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { 878static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = {
879 [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp, 879 [NFQNL_MSG_PACKET] = { .call = nfqnl_recv_unsupp,
880 .attr_count = NFQA_MAX,
880 .cap_required = CAP_NET_ADMIN }, 881 .cap_required = CAP_NET_ADMIN },
881 [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict, 882 [NFQNL_MSG_VERDICT] = { .call = nfqnl_recv_verdict,
883 .attr_count = NFQA_MAX,
882 .cap_required = CAP_NET_ADMIN }, 884 .cap_required = CAP_NET_ADMIN },
883 [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config, 885 [NFQNL_MSG_CONFIG] = { .call = nfqnl_recv_config,
886 .attr_count = NFQA_CFG_MAX,
884 .cap_required = CAP_NET_ADMIN }, 887 .cap_required = CAP_NET_ADMIN },
885}; 888};
886 889
@@ -888,7 +891,6 @@ static struct nfnetlink_subsystem nfqnl_subsys = {
888 .name = "nf_queue", 891 .name = "nf_queue",
889 .subsys_id = NFNL_SUBSYS_QUEUE, 892 .subsys_id = NFNL_SUBSYS_QUEUE,
890 .cb_count = NFQNL_MSG_MAX, 893 .cb_count = NFQNL_MSG_MAX,
891 .attr_count = NFQA_MAX,
892 .cb = nfqnl_cb, 894 .cb = nfqnl_cb,
893}; 895};
894 896