diff options
author | Thomas Graf <tgraf@suug.ch> | 2006-11-10 17:10:15 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:22:11 -0500 |
commit | 339bf98ffc6a8d8eb16fc532ac57ffbced2f8a68 (patch) | |
tree | 499ad948863d2753ca10283dcf006ad28954538e /net/core | |
parent | a94f723d595ee085f81b1788d18e031af7eeba91 (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/core')
-rw-r--r-- | net/core/fib_rules.c | 24 | ||||
-rw-r--r-- | net/core/neighbour.c | 17 | ||||
-rw-r--r-- | net/core/rtnetlink.c | 39 |
3 files changed, 57 insertions, 23 deletions
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 | ||
309 | static 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 | |||
309 | static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, | 325 | static 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); |
398 | errout: | 412 | errout: |
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 |
2413 | static 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 | |||
2413 | static void __neigh_notify(struct neighbour *n, int type, int flags) | 2422 | static 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); |
2429 | errout: | 2436 | errout: |
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 | ||
276 | static 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 | |||
276 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | 295 | static 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); |
606 | errout: | 621 | errout: |
@@ -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); |
653 | errout: | 666 | errout: |