aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorThomas Graf <tgraf@suug.ch>2006-11-10 17:10:15 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2006-12-03 00:22:11 -0500
commit339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68 (patch)
tree499ad948863d2753ca10283dcf006ad28954538e /net
parenta94f723d595ee085f81b1788d18e031af7eeba91 (diff)
[NETLINK]: Do precise netlink message allocations where possible
Account for the netlink message header size directly in nlmsg_new() instead of relying on the caller calculate it correctly. Replaces error handling of message construction functions when constructing notifications with bug traps since a failure implies a bug in calculating the size of the skb. Signed-off-by: Thomas Graf <tgraf@suug.ch> Acked-by: Paul Moore <paul.moore@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/bridge/br_netlink.c21
-rw-r--r--net/core/fib_rules.c24
-rw-r--r--net/core/neighbour.c17
-rw-r--r--net/core/rtnetlink.c39
-rw-r--r--net/decnet/dn_rules.c6
-rw-r--r--net/decnet/dn_table.c34
-rw-r--r--net/ipv4/devinet.c18
-rw-r--r--net/ipv4/fib_rules.c8
-rw-r--r--net/ipv4/fib_semantics.c36
-rw-r--r--net/ipv6/addrconf.c70
-rw-r--r--net/ipv6/fib6_rules.c7
-rw-r--r--net/ipv6/route.c23
-rw-r--r--net/netlabel/netlabel_cipso_v4.c2
-rw-r--r--net/netlabel/netlabel_mgmt.c4
-rw-r--r--net/netlabel/netlabel_unlabeled.c2
-rw-r--r--net/netlink/af_netlink.c13
-rw-r--r--net/netlink/genetlink.c2
17 files changed, 225 insertions, 101 deletions
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 8f661195d09d..15d6efbe7519 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -15,6 +15,18 @@
15#include <net/netlink.h> 15#include <net/netlink.h>
16#include "br_private.h" 16#include "br_private.h"
17 17
18static inline size_t br_nlmsg_size(void)
19{
20 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
21 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
22 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
23 + nla_total_size(4) /* IFLA_MASTER */
24 + nla_total_size(4) /* IFLA_MTU */
25 + nla_total_size(4) /* IFLA_LINK */
26 + nla_total_size(1) /* IFLA_OPERSTATE */
27 + nla_total_size(1); /* IFLA_PROTINFO */
28}
29
18/* 30/*
19 * Create one netlink message for one interface 31 * Create one netlink message for one interface
20 * Contains port and master info as well as carrier and bridge state. 32 * Contains port and master info as well as carrier and bridge state.
@@ -77,19 +89,16 @@ rtattr_failure:
77void br_ifinfo_notify(int event, struct net_bridge_port *port) 89void br_ifinfo_notify(int event, struct net_bridge_port *port)
78{ 90{
79 struct sk_buff *skb; 91 struct sk_buff *skb;
80 int payload = sizeof(struct ifinfomsg) + 128;
81 int err = -ENOBUFS; 92 int err = -ENOBUFS;
82 93
83 pr_debug("bridge notify event=%d\n", event); 94 pr_debug("bridge notify event=%d\n", event);
84 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); 95 skb = nlmsg_new(br_nlmsg_size(), GFP_ATOMIC);
85 if (skb == NULL) 96 if (skb == NULL)
86 goto errout; 97 goto errout;
87 98
88 err = br_fill_ifinfo(skb, port, 0, 0, event, 0); 99 err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
89 if (err < 0) { 100 /* failure implies BUG in br_nlmsg_size() */
90 kfree_skb(skb); 101 BUG_ON(err < 0);
91 goto errout;
92 }
93 102
94 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); 103 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
95errout: 104errout:
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 4148e274a204..1df6cd4568d3 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -306,6 +306,22 @@ errout:
306 return err; 306 return err;
307} 307}
308 308
309static inline size_t fib_rule_nlmsg_size(struct fib_rules_ops *ops,
310 struct fib_rule *rule)
311{
312 size_t payload = NLMSG_ALIGN(sizeof(struct fib_rule_hdr))
313 + nla_total_size(IFNAMSIZ) /* FRA_IFNAME */
314 + nla_total_size(4) /* FRA_PRIORITY */
315 + nla_total_size(4) /* FRA_TABLE */
316 + nla_total_size(4) /* FRA_FWMARK */
317 + nla_total_size(4); /* FRA_FWMASK */
318
319 if (ops->nlmsg_payload)
320 payload += ops->nlmsg_payload(rule);
321
322 return payload;
323}
324
309static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, 325static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
310 u32 pid, u32 seq, int type, int flags, 326 u32 pid, u32 seq, int type, int flags,
311 struct fib_rules_ops *ops) 327 struct fib_rules_ops *ops)
@@ -384,15 +400,13 @@ static void notify_rule_change(int event, struct fib_rule *rule,
384 struct sk_buff *skb; 400 struct sk_buff *skb;
385 int err = -ENOBUFS; 401 int err = -ENOBUFS;
386 402
387 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 403 skb = nlmsg_new(fib_rule_nlmsg_size(ops, rule), GFP_KERNEL);
388 if (skb == NULL) 404 if (skb == NULL)
389 goto errout; 405 goto errout;
390 406
391 err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); 407 err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
392 if (err < 0) { 408 /* failure implies BUG in fib_rule_nlmsg_size() */
393 kfree_skb(skb); 409 BUG_ON(err < 0);
394 goto errout;
395 }
396 410
397 err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); 411 err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
398errout: 412errout:
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index b4b478353b27..0e097ba14d73 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -2410,20 +2410,27 @@ static struct file_operations neigh_stat_seq_fops = {
2410#endif /* CONFIG_PROC_FS */ 2410#endif /* CONFIG_PROC_FS */
2411 2411
2412#ifdef CONFIG_ARPD 2412#ifdef CONFIG_ARPD
2413static inline size_t neigh_nlmsg_size(void)
2414{
2415 return NLMSG_ALIGN(sizeof(struct ndmsg))
2416 + nla_total_size(MAX_ADDR_LEN) /* NDA_DST */
2417 + nla_total_size(MAX_ADDR_LEN) /* NDA_LLADDR */
2418 + nla_total_size(sizeof(struct nda_cacheinfo))
2419 + nla_total_size(4); /* NDA_PROBES */
2420}
2421
2413static void __neigh_notify(struct neighbour *n, int type, int flags) 2422static void __neigh_notify(struct neighbour *n, int type, int flags)
2414{ 2423{
2415 struct sk_buff *skb; 2424 struct sk_buff *skb;
2416 int err = -ENOBUFS; 2425 int err = -ENOBUFS;
2417 2426
2418 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); 2427 skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC);
2419 if (skb == NULL) 2428 if (skb == NULL)
2420 goto errout; 2429 goto errout;
2421 2430
2422 err = neigh_fill_info(skb, n, 0, 0, type, flags); 2431 err = neigh_fill_info(skb, n, 0, 0, type, flags);
2423 if (err < 0) { 2432 /* failure implies BUG in neigh_nlmsg_size() */
2424 kfree_skb(skb); 2433 BUG_ON(err < 0);
2425 goto errout;
2426 }
2427 2434
2428 err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); 2435 err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
2429errout: 2436errout:
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 02f3c7947898..50d6cb40c6e3 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -273,6 +273,25 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
273 a->tx_compressed = b->tx_compressed; 273 a->tx_compressed = b->tx_compressed;
274}; 274};
275 275
276static inline size_t if_nlmsg_size(int iwbuflen)
277{
278 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
279 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
280 + nla_total_size(IFNAMSIZ) /* IFLA_QDISC */
281 + nla_total_size(sizeof(struct rtnl_link_ifmap))
282 + nla_total_size(sizeof(struct rtnl_link_stats))
283 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
284 + nla_total_size(MAX_ADDR_LEN) /* IFLA_BROADCAST */
285 + nla_total_size(4) /* IFLA_TXQLEN */
286 + nla_total_size(4) /* IFLA_WEIGHT */
287 + nla_total_size(4) /* IFLA_MTU */
288 + nla_total_size(4) /* IFLA_LINK */
289 + nla_total_size(4) /* IFLA_MASTER */
290 + nla_total_size(1) /* IFLA_OPERSTATE */
291 + nla_total_size(1) /* IFLA_LINKMODE */
292 + nla_total_size(iwbuflen);
293}
294
276static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, 295static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
277 void *iwbuf, int iwbuflen, int type, u32 pid, 296 void *iwbuf, int iwbuflen, int type, u32 pid,
278 u32 seq, u32 change, unsigned int flags) 297 u32 seq, u32 change, unsigned int flags)
@@ -558,7 +577,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
558 struct sk_buff *nskb; 577 struct sk_buff *nskb;
559 char *iw_buf = NULL, *iw = NULL; 578 char *iw_buf = NULL, *iw = NULL;
560 int iw_buf_len = 0; 579 int iw_buf_len = 0;
561 int err, payload; 580 int err;
562 581
563 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); 582 err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy);
564 if (err < 0) 583 if (err < 0)
@@ -587,9 +606,7 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
587 } 606 }
588#endif /* CONFIG_NET_WIRELESS_RTNETLINK */ 607#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
589 608
590 payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) + 609 nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL);
591 nla_total_size(iw_buf_len));
592 nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL);
593 if (nskb == NULL) { 610 if (nskb == NULL) {
594 err = -ENOBUFS; 611 err = -ENOBUFS;
595 goto errout; 612 goto errout;
@@ -597,10 +614,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
597 614
598 err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK, 615 err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
599 NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0); 616 NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
600 if (err <= 0) { 617 /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
601 kfree_skb(nskb); 618 BUG_ON(err < 0);
602 goto errout;
603 }
604 619
605 err = rtnl_unicast(nskb, NETLINK_CB(skb).pid); 620 err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
606errout: 621errout:
@@ -639,15 +654,13 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
639 struct sk_buff *skb; 654 struct sk_buff *skb;
640 int err = -ENOBUFS; 655 int err = -ENOBUFS;
641 656
642 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 657 skb = nlmsg_new(if_nlmsg_size(0), GFP_KERNEL);
643 if (skb == NULL) 658 if (skb == NULL)
644 goto errout; 659 goto errout;
645 660
646 err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0); 661 err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
647 if (err < 0) { 662 /* failure implies BUG in if_nlmsg_size() */
648 kfree_skb(skb); 663 BUG_ON(err < 0);
649 goto errout;
650 }
651 664
652 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); 665 err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
653errout: 666errout:
diff --git a/net/decnet/dn_rules.c b/net/decnet/dn_rules.c
index e32d0c3d5a96..b7dfd04a9638 100644
--- a/net/decnet/dn_rules.c
+++ b/net/decnet/dn_rules.c
@@ -241,6 +241,12 @@ static u32 dn_fib_rule_default_pref(void)
241 return 0; 241 return 0;
242} 242}
243 243
244static size_t dn_fib_rule_nlmsg_payload(struct fib_rule *rule)
245{
246 return nla_total_size(2) /* dst */
247 + nla_total_size(2); /* src */
248}
249
244int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) 250int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb)
245{ 251{
246 return fib_rules_dump(skb, cb, AF_DECnet); 252 return fib_rules_dump(skb, cb, AF_DECnet);
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c
index 317904bb5896..e74b744254ab 100644
--- a/net/decnet/dn_table.c
+++ b/net/decnet/dn_table.c
@@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern
263 return 0; 263 return 0;
264} 264}
265 265
266static inline size_t dn_fib_nlmsg_size(struct dn_fib_info *fi)
267{
268 size_t payload = NLMSG_ALIGN(struct rtmsg)
269 + nla_total_size(4) /* RTA_TABLE */
270 + nla_total_size(2) /* RTA_DST */
271 + nla_total_size(4); /* RTA_PRIORITY */
272
273 /* space for nested metrics */
274 payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
275
276 if (fi->fib_nhs) {
277 /* Also handles the special case fib_nhs == 1 */
278
279 /* each nexthop is packed in an attribute */
280 size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
281
282 /* may contain a gateway attribute */
283 nhsize += nla_total_size(4);
284
285 /* all nexthops are packed in a nested attribute */
286 payload += nla_total_size(fi->fib_nhs * nhsize);
287 }
288
289 return payload;
290}
291
266static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, 292static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
267 u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, 293 u32 tb_id, u8 type, u8 scope, void *dst, int dst_len,
268 struct dn_fib_info *fi, unsigned int flags) 294 struct dn_fib_info *fi, unsigned int flags)
@@ -335,17 +361,15 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
335 u32 pid = req ? req->pid : 0; 361 u32 pid = req ? req->pid : 0;
336 int err = -ENOBUFS; 362 int err = -ENOBUFS;
337 363
338 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 364 skb = nlmsg_new(dn_fib_nlmsg_size(DN_FIB_INFO(f), GFP_KERNEL));
339 if (skb == NULL) 365 if (skb == NULL)
340 goto errout; 366 goto errout;
341 367
342 err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, 368 err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
343 f->fn_type, f->fn_scope, &f->fn_key, z, 369 f->fn_type, f->fn_scope, &f->fn_key, z,
344 DN_FIB_INFO(f), 0); 370 DN_FIB_INFO(f), 0);
345 if (err < 0) { 371 /* failure implies BUG in dn_fib_nlmsg_size() */
346 kfree_skb(skb); 372 BUG_ON(err < 0);
347 goto errout;
348 }
349 373
350 err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); 374 err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
351errout: 375errout:
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 7602c79a389b..f38cbbae0ae3 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1120,6 +1120,16 @@ static struct notifier_block ip_netdev_notifier = {
1120 .notifier_call =inetdev_event, 1120 .notifier_call =inetdev_event,
1121}; 1121};
1122 1122
1123static inline size_t inet_nlmsg_size(void)
1124{
1125 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
1126 + nla_total_size(4) /* IFA_ADDRESS */
1127 + nla_total_size(4) /* IFA_LOCAL */
1128 + nla_total_size(4) /* IFA_BROADCAST */
1129 + nla_total_size(4) /* IFA_ANYCAST */
1130 + nla_total_size(IFNAMSIZ); /* IFA_LABEL */
1131}
1132
1123static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, 1133static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1124 u32 pid, u32 seq, int event, unsigned int flags) 1134 u32 pid, u32 seq, int event, unsigned int flags)
1125{ 1135{
@@ -1208,15 +1218,13 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
1208 u32 seq = nlh ? nlh->nlmsg_seq : 0; 1218 u32 seq = nlh ? nlh->nlmsg_seq : 0;
1209 int err = -ENOBUFS; 1219 int err = -ENOBUFS;
1210 1220
1211 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 1221 skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL);
1212 if (skb == NULL) 1222 if (skb == NULL)
1213 goto errout; 1223 goto errout;
1214 1224
1215 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); 1225 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
1216 if (err < 0) { 1226 /* failure implies BUG in inet_nlmsg_size() */
1217 kfree_skb(skb); 1227 BUG_ON(err < 0);
1218 goto errout;
1219 }
1220 1228
1221 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); 1229 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
1222errout: 1230errout:
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index fd4a8cd4c06e..b837c33e0404 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -299,6 +299,13 @@ static u32 fib4_rule_default_pref(void)
299 return 0; 299 return 0;
300} 300}
301 301
302static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
303{
304 return nla_total_size(4) /* dst */
305 + nla_total_size(4) /* src */
306 + nla_total_size(4); /* flow */
307}
308
302static struct fib_rules_ops fib4_rules_ops = { 309static struct fib_rules_ops fib4_rules_ops = {
303 .family = AF_INET, 310 .family = AF_INET,
304 .rule_size = sizeof(struct fib4_rule), 311 .rule_size = sizeof(struct fib4_rule),
@@ -308,6 +315,7 @@ static struct fib_rules_ops fib4_rules_ops = {
308 .compare = fib4_rule_compare, 315 .compare = fib4_rule_compare,
309 .fill = fib4_rule_fill, 316 .fill = fib4_rule_fill,
310 .default_pref = fib4_rule_default_pref, 317 .default_pref = fib4_rule_default_pref,
318 .nlmsg_payload = fib4_rule_nlmsg_payload,
311 .nlgroup = RTNLGRP_IPV4_RULE, 319 .nlgroup = RTNLGRP_IPV4_RULE,
312 .policy = fib4_rule_policy, 320 .policy = fib4_rule_policy,
313 .rules_list = &fib4_rules, 321 .rules_list = &fib4_rules,
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index 884d176e0082..e63b8a98fb4d 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -273,25 +273,49 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev)
273 return -1; 273 return -1;
274} 274}
275 275
276static inline size_t fib_nlmsg_size(struct fib_info *fi)
277{
278 size_t payload = NLMSG_ALIGN(sizeof(struct rtmsg))
279 + nla_total_size(4) /* RTA_TABLE */
280 + nla_total_size(4) /* RTA_DST */
281 + nla_total_size(4) /* RTA_PRIORITY */
282 + nla_total_size(4); /* RTA_PREFSRC */
283
284 /* space for nested metrics */
285 payload += nla_total_size((RTAX_MAX * nla_total_size(4)));
286
287 if (fi->fib_nhs) {
288 /* Also handles the special case fib_nhs == 1 */
289
290 /* each nexthop is packed in an attribute */
291 size_t nhsize = nla_total_size(sizeof(struct rtnexthop));
292
293 /* may contain flow and gateway attribute */
294 nhsize += 2 * nla_total_size(4);
295
296 /* all nexthops are packed in a nested attribute */
297 payload += nla_total_size(fi->fib_nhs * nhsize);
298 }
299
300 return payload;
301}
302
276void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, 303void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
277 int dst_len, u32 tb_id, struct nl_info *info) 304 int dst_len, u32 tb_id, struct nl_info *info)
278{ 305{
279 struct sk_buff *skb; 306 struct sk_buff *skb;
280 int payload = sizeof(struct rtmsg) + 256;
281 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; 307 u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0;
282 int err = -ENOBUFS; 308 int err = -ENOBUFS;
283 309
284 skb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); 310 skb = nlmsg_new(fib_nlmsg_size(fa->fa_info), GFP_KERNEL);
285 if (skb == NULL) 311 if (skb == NULL)
286 goto errout; 312 goto errout;
287 313
288 err = fib_dump_info(skb, info->pid, seq, event, tb_id, 314 err = fib_dump_info(skb, info->pid, seq, event, tb_id,
289 fa->fa_type, fa->fa_scope, key, dst_len, 315 fa->fa_type, fa->fa_scope, key, dst_len,
290 fa->fa_tos, fa->fa_info, 0); 316 fa->fa_tos, fa->fa_info, 0);
291 if (err < 0) { 317 /* failure implies BUG in fib_nlmsg_size() */
292 kfree_skb(skb); 318 BUG_ON(err < 0);
293 goto errout;
294 }
295 319
296 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, 320 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
297 info->nlh, GFP_KERNEL); 321 info->nlh, GFP_KERNEL);
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 6a98f68348cb..967ea320a9ca 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope)
3098 3098
3099static inline int inet6_ifaddr_msgsize(void) 3099static inline int inet6_ifaddr_msgsize(void)
3100{ 3100{
3101 return nlmsg_total_size(sizeof(struct ifaddrmsg) + 3101 return NLMSG_ALIGN(sizeof(struct ifaddrmsg))
3102 nla_total_size(16) + 3102 + nla_total_size(16) /* IFA_ADDRESS */
3103 nla_total_size(sizeof(struct ifa_cacheinfo)) + 3103 + nla_total_size(sizeof(struct ifa_cacheinfo));
3104 128);
3105} 3104}
3106 3105
3107static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, 3106static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
@@ -3329,10 +3328,8 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
3329 3328
3330 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, 3329 err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
3331 nlh->nlmsg_seq, RTM_NEWADDR, 0); 3330 nlh->nlmsg_seq, RTM_NEWADDR, 0);
3332 if (err < 0) { 3331 /* failure implies BUG in inet6_ifaddr_msgsize() */
3333 kfree_skb(skb); 3332 BUG_ON(err < 0);
3334 goto errout_ifa;
3335 }
3336 3333
3337 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); 3334 err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
3338errout_ifa: 3335errout_ifa:
@@ -3351,10 +3348,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
3351 goto errout; 3348 goto errout;
3352 3349
3353 err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); 3350 err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
3354 if (err < 0) { 3351 /* failure implies BUG in inet6_ifaddr_msgsize() */
3355 kfree_skb(skb); 3352 BUG_ON(err < 0);
3356 goto errout;
3357 }
3358 3353
3359 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 3354 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3360errout: 3355errout:
@@ -3397,16 +3392,19 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf,
3397 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; 3392 array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp;
3398} 3393}
3399 3394
3400/* Maximum length of ifinfomsg attributes */ 3395static inline size_t inet6_if_nlmsg_size(void)
3401#define INET6_IFINFO_RTA_SPACE \ 3396{
3402 RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \ 3397 return NLMSG_ALIGN(sizeof(struct ifinfomsg))
3403 RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \ 3398 + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */
3404 RTA_SPACE(sizeof(u32)) /* MTU */ + \ 3399 + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */
3405 RTA_SPACE(sizeof(int)) /* LINK */ + \ 3400 + nla_total_size(4) /* IFLA_MTU */
3406 RTA_SPACE(0) /* PROTINFO */ + \ 3401 + nla_total_size(4) /* IFLA_LINK */
3407 RTA_SPACE(sizeof(u32)) /* FLAGS */ + \ 3402 + nla_total_size( /* IFLA_PROTINFO */
3408 RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \ 3403 nla_total_size(4) /* IFLA_INET6_FLAGS */
3409 RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */ 3404 + nla_total_size(sizeof(struct ifla_cacheinfo))
3405 + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */
3406 );
3407}
3410 3408
3411static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, 3409static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
3412 u32 pid, u32 seq, int event, unsigned int flags) 3410 u32 pid, u32 seq, int event, unsigned int flags)
@@ -3501,18 +3499,15 @@ static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
3501void inet6_ifinfo_notify(int event, struct inet6_dev *idev) 3499void inet6_ifinfo_notify(int event, struct inet6_dev *idev)
3502{ 3500{
3503 struct sk_buff *skb; 3501 struct sk_buff *skb;
3504 int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE;
3505 int err = -ENOBUFS; 3502 int err = -ENOBUFS;
3506 3503
3507 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); 3504 skb = nlmsg_new(inet6_if_nlmsg_size(), GFP_ATOMIC);
3508 if (skb == NULL) 3505 if (skb == NULL)
3509 goto errout; 3506 goto errout;
3510 3507
3511 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); 3508 err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
3512 if (err < 0) { 3509 /* failure implies BUG in inet6_if_nlmsg_size() */
3513 kfree_skb(skb); 3510 BUG_ON(err < 0);
3514 goto errout;
3515 }
3516 3511
3517 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); 3512 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
3518errout: 3513errout:
@@ -3520,10 +3515,12 @@ errout:
3520 rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); 3515 rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err);
3521} 3516}
3522 3517
3523/* Maximum length of prefix_cacheinfo attributes */ 3518static inline size_t inet6_prefix_nlmsg_size(void)
3524#define INET6_PREFIX_RTA_SPACE \ 3519{
3525 RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \ 3520 return NLMSG_ALIGN(sizeof(struct prefixmsg))
3526 RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */ 3521 + nla_total_size(sizeof(struct in6_addr))
3522 + nla_total_size(sizeof(struct prefix_cacheinfo));
3523}
3527 3524
3528static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, 3525static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
3529 struct prefix_info *pinfo, u32 pid, u32 seq, 3526 struct prefix_info *pinfo, u32 pid, u32 seq,
@@ -3569,18 +3566,15 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev,
3569 struct prefix_info *pinfo) 3566 struct prefix_info *pinfo)
3570{ 3567{
3571 struct sk_buff *skb; 3568 struct sk_buff *skb;
3572 int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE;
3573 int err = -ENOBUFS; 3569 int err = -ENOBUFS;
3574 3570
3575 skb = nlmsg_new(nlmsg_total_size(payload), GFP_ATOMIC); 3571 skb = nlmsg_new(inet6_prefix_nlmsg_size(), GFP_ATOMIC);
3576 if (skb == NULL) 3572 if (skb == NULL)
3577 goto errout; 3573 goto errout;
3578 3574
3579 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); 3575 err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
3580 if (err < 0) { 3576 /* failure implies BUG in inet6_prefix_nlmsg_size() */
3581 kfree_skb(skb); 3577 BUG_ON(err < 0);
3582 goto errout;
3583 }
3584 3578
3585 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); 3579 err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
3586errout: 3580errout:
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index 25804cb69cf0..d587dde5897e 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -232,6 +232,12 @@ static u32 fib6_rule_default_pref(void)
232 return 0x3FFF; 232 return 0x3FFF;
233} 233}
234 234
235static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
236{
237 return nla_total_size(16) /* dst */
238 + nla_total_size(16); /* src */
239}
240
235static struct fib_rules_ops fib6_rules_ops = { 241static struct fib_rules_ops fib6_rules_ops = {
236 .family = AF_INET6, 242 .family = AF_INET6,
237 .rule_size = sizeof(struct fib6_rule), 243 .rule_size = sizeof(struct fib6_rule),
@@ -241,6 +247,7 @@ static struct fib_rules_ops fib6_rules_ops = {
241 .compare = fib6_rule_compare, 247 .compare = fib6_rule_compare,
242 .fill = fib6_rule_fill, 248 .fill = fib6_rule_fill,
243 .default_pref = fib6_rule_default_pref, 249 .default_pref = fib6_rule_default_pref,
250 .nlmsg_payload = fib6_rule_nlmsg_payload,
244 .nlgroup = RTNLGRP_IPV6_RULE, 251 .nlgroup = RTNLGRP_IPV6_RULE,
245 .policy = fib6_rule_policy, 252 .policy = fib6_rule_policy,
246 .rules_list = &fib6_rules, 253 .rules_list = &fib6_rules,
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 0ad07c9087a7..a6472cb9054c 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2006,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
2006 return ip6_route_add(&cfg); 2006 return ip6_route_add(&cfg);
2007} 2007}
2008 2008
2009static inline size_t rt6_nlmsg_size(void)
2010{
2011 return NLMSG_ALIGN(sizeof(struct rtmsg))
2012 + nla_total_size(16) /* RTA_SRC */
2013 + nla_total_size(16) /* RTA_DST */
2014 + nla_total_size(16) /* RTA_GATEWAY */
2015 + nla_total_size(16) /* RTA_PREFSRC */
2016 + nla_total_size(4) /* RTA_TABLE */
2017 + nla_total_size(4) /* RTA_IIF */
2018 + nla_total_size(4) /* RTA_OIF */
2019 + nla_total_size(4) /* RTA_PRIORITY */
2020 + nla_total_size(sizeof(struct rta_cacheinfo));
2021}
2022
2009static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, 2023static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
2010 struct in6_addr *dst, struct in6_addr *src, 2024 struct in6_addr *dst, struct in6_addr *src,
2011 int iif, int type, u32 pid, u32 seq, 2025 int iif, int type, u32 pid, u32 seq,
@@ -2200,7 +2214,6 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2200 struct sk_buff *skb; 2214 struct sk_buff *skb;
2201 u32 pid = 0, seq = 0; 2215 u32 pid = 0, seq = 0;
2202 struct nlmsghdr *nlh = NULL; 2216 struct nlmsghdr *nlh = NULL;
2203 int payload = sizeof(struct rtmsg) + 256;
2204 int err = -ENOBUFS; 2217 int err = -ENOBUFS;
2205 2218
2206 if (info) { 2219 if (info) {
@@ -2210,15 +2223,13 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info)
2210 seq = nlh->nlmsg_seq; 2223 seq = nlh->nlmsg_seq;
2211 } 2224 }
2212 2225
2213 skb = nlmsg_new(nlmsg_total_size(payload), gfp_any()); 2226 skb = nlmsg_new(rt6_nlmsg_size(), gfp_any());
2214 if (skb == NULL) 2227 if (skb == NULL)
2215 goto errout; 2228 goto errout;
2216 2229
2217 err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); 2230 err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
2218 if (err < 0) { 2231 /* failure implies BUG in rt6_nlmsg_size() */
2219 kfree_skb(skb); 2232 BUG_ON(err < 0);
2220 goto errout;
2221 }
2222 2233
2223 err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); 2234 err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
2224errout: 2235errout:
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c
index a6ce1d6d5c59..f1788bd290f8 100644
--- a/net/netlabel/netlabel_cipso_v4.c
+++ b/net/netlabel/netlabel_cipso_v4.c
@@ -452,7 +452,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info)
452 } 452 }
453 453
454list_start: 454list_start:
455 ans_skb = nlmsg_new(NLMSG_GOODSIZE * nlsze_mult, GFP_KERNEL); 455 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE * nlsze_mult, GFP_KERNEL);
456 if (ans_skb == NULL) { 456 if (ans_skb == NULL) {
457 ret_val = -ENOMEM; 457 ret_val = -ENOMEM;
458 goto list_failure; 458 goto list_failure;
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c
index 53c9079ad2c3..c529622ff0b7 100644
--- a/net/netlabel/netlabel_mgmt.c
+++ b/net/netlabel/netlabel_mgmt.c
@@ -356,7 +356,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info)
356 void *data; 356 void *data;
357 struct netlbl_dom_map *entry; 357 struct netlbl_dom_map *entry;
358 358
359 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 359 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
360 if (ans_skb == NULL) 360 if (ans_skb == NULL)
361 return -ENOMEM; 361 return -ENOMEM;
362 data = netlbl_netlink_hdr_put(ans_skb, 362 data = netlbl_netlink_hdr_put(ans_skb,
@@ -492,7 +492,7 @@ static int netlbl_mgmt_version(struct sk_buff *skb, struct genl_info *info)
492 struct sk_buff *ans_skb = NULL; 492 struct sk_buff *ans_skb = NULL;
493 void *data; 493 void *data;
494 494
495 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 495 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
496 if (ans_skb == NULL) 496 if (ans_skb == NULL)
497 return -ENOMEM; 497 return -ENOMEM;
498 data = netlbl_netlink_hdr_put(ans_skb, 498 data = netlbl_netlink_hdr_put(ans_skb,
diff --git a/net/netlabel/netlabel_unlabeled.c b/net/netlabel/netlabel_unlabeled.c
index 1833ad233b39..219dccade4e1 100644
--- a/net/netlabel/netlabel_unlabeled.c
+++ b/net/netlabel/netlabel_unlabeled.c
@@ -138,7 +138,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info)
138 struct sk_buff *ans_skb; 138 struct sk_buff *ans_skb;
139 void *data; 139 void *data;
140 140
141 ans_skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 141 ans_skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
142 if (ans_skb == NULL) 142 if (ans_skb == NULL)
143 goto list_failure; 143 goto list_failure;
144 data = netlbl_netlink_hdr_put(ans_skb, 144 data = netlbl_netlink_hdr_put(ans_skb,
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d527c8977b1f..f61d81b3c61c 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1148,7 +1148,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
1148 if (len > sk->sk_sndbuf - 32) 1148 if (len > sk->sk_sndbuf - 32)
1149 goto out; 1149 goto out;
1150 err = -ENOBUFS; 1150 err = -ENOBUFS;
1151 skb = nlmsg_new(len, GFP_KERNEL); 1151 skb = alloc_skb(len, GFP_KERNEL);
1152 if (skb==NULL) 1152 if (skb==NULL)
1153 goto out; 1153 goto out;
1154 1154
@@ -1435,14 +1435,13 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err)
1435 struct sk_buff *skb; 1435 struct sk_buff *skb;
1436 struct nlmsghdr *rep; 1436 struct nlmsghdr *rep;
1437 struct nlmsgerr *errmsg; 1437 struct nlmsgerr *errmsg;
1438 int size; 1438 size_t payload = sizeof(*errmsg);
1439 1439
1440 if (err == 0) 1440 /* error messages get the original request appened */
1441 size = nlmsg_total_size(sizeof(*errmsg)); 1441 if (err)
1442 else 1442 payload += nlmsg_len(nlh);
1443 size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh));
1444 1443
1445 skb = nlmsg_new(size, GFP_KERNEL); 1444 skb = nlmsg_new(payload, GFP_KERNEL);
1446 if (!skb) { 1445 if (!skb) {
1447 struct sock *sk; 1446 struct sock *sk;
1448 1447
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 49bc2db7982b..70d60c818897 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -480,7 +480,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid,
480 struct sk_buff *skb; 480 struct sk_buff *skb;
481 int err; 481 int err;
482 482
483 skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 483 skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
484 if (skb == NULL) 484 if (skb == NULL)
485 return ERR_PTR(-ENOBUFS); 485 return ERR_PTR(-ENOBUFS);
486 486