diff options
-rw-r--r-- | include/linux/netfilter/nfnetlink.h | 4 | ||||
-rw-r--r-- | net/ipv4/netfilter/ip_conntrack_netlink.c | 9 | ||||
-rw-r--r-- | net/netfilter/nfnetlink.c | 20 | ||||
-rw-r--r-- | net/netfilter/nfnetlink_log.c | 5 | ||||
-rw-r--r-- | 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 { | |||
85 | 85 | ||
86 | struct nfnl_callback | 86 | struct 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 | ||
93 | struct nfnetlink_subsystem | 94 | struct 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 | ||
1485 | static struct nfnl_callback ctnl_cb[IPCTNL_MSG_MAX] = { | 1485 | static 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 | ||
1496 | static struct nfnl_callback ctnl_exp_cb[IPCTNL_MSG_MAX] = { | 1500 | static 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 | ||
806 | static struct nfnl_callback nfulnl_cb[NFULNL_MSG_MAX] = { | 806 | static 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 | ||
878 | static struct nfnl_callback nfqnl_cb[NFQNL_MSG_MAX] = { | 878 | static 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 | ||