History

[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.

Thomas Graf committed 20 years ago

Commit 339bf981 parent a94f72321 files · +233 −107Browse files

Unified · Split

21 files
  1. include/linux/netlink.h +1 −0
  2. include/net/fib_rules.h +1 −0
  3. include/net/netlink.h +5 −4
  4. kernel/taskstats.c +1 −2
  5. net/bridge/br_netlink.c +15 −6
  6. net/core/fib_rules.c +19 −5
  7. net/core/neighbour.c +12 −5
  8. net/core/rtnetlink.c +26 −13
  9. net/decnet/dn_rules.c +6 −0
  10. net/decnet/dn_table.c +29 −5
  11. net/ipv4/devinet.c +13 −5
  12. net/ipv4/fib_rules.c +8 −0
  13. net/ipv4/fib_semantics.c +30 −6
  14. net/ipv6/addrconf.c +32 −38
  15. net/ipv6/fib6_rules.c +7 −0
  16. net/ipv6/route.c +17 −6
  17. net/netlabel/netlabel_cipso_v4.c +1 −1
  18. net/netlabel/netlabel_mgmt.c +2 −2
  19. net/netlabel/netlabel_unlabeled.c +1 −1
  20. net/netlink/af_netlink.c +6 −7
  21. net/netlink/genetlink.c +1 −1
include/linux/netlink.h+1−0
@@ -174,6 +174,7 @@ int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol); · 173 unmodified lines
174 */174 */
175#define NLMSG_GOODORDER 0175#define NLMSG_GOODORDER 0
176#define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER))176#define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER))
177#define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN)
177 178
178 179
179struct netlink_callback180struct netlink_callback
include/net/fib_rules.h+1−0
@@ -52,6 +52,7 @@ struct fib_rules_ops · 51 unmodified lines
52 struct nlmsghdr *,52 struct nlmsghdr *,
53 struct fib_rule_hdr *);53 struct fib_rule_hdr *);
54 u32 (*default_pref)(void);54 u32 (*default_pref)(void);
55 size_t (*nlmsg_payload)(struct fib_rule *);
55 56
56 int nlgroup;57 int nlgroup;
57 struct nla_policy *policy;58 struct nla_policy *policy;
include/net/netlink.h+5−4
@@ -500,14 +500,15 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb, · 499 unmodified lines
500 500
501/**501/**
502 * nlmsg_new - Allocate a new netlink message502 * nlmsg_new - Allocate a new netlink message
503 * @size: maximum size of message503 * @payload: size of the message payload
504 * @flags: the type of memory to allocate.504 * @flags: the type of memory to allocate.
505 *505 *
506 * Use NLMSG_GOODSIZE if size isn't know and you need a good default size.506 * Use NLMSG_DEFAULT_SIZE if the size of the payload isn't known
507 * and a good default is needed.
507 */508 */
508static inline struct sk_buff *nlmsg_new(int size, gfp_t flags)509static inline struct sk_buff *nlmsg_new(size_t payload, gfp_t flags)
509{510{
510 return alloc_skb(size, flags);511 return alloc_skb(nlmsg_total_size(payload), flags);
511}512}
512 513
513/**514/**
kernel/taskstats.c+1−2
@@ -77,8 +77,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, · 76 unmodified lines
77 /*77 /*
78 * If new attributes are added, please revisit this allocation78 * If new attributes are added, please revisit this allocation
79 */79 */
80 size = nlmsg_total_size(genlmsg_total_size(size));80 skb = nlmsg_new(genlmsg_total_size(size), GFP_KERNEL);
81 skb = nlmsg_new(size, GFP_KERNEL);
82 if (!skb)81 if (!skb)
83 return -ENOMEM;82 return -ENOMEM;
84 83
net/bridge/br_netlink.c+15−6
@@ -15,6 +15,18 @@ · 14 unmodified lines
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 interface31 * 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: · 56 unmodified lines
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:
net/core/fib_rules.c+19−5
@@ -306,6 +306,22 @@ errout: · 305 unmodified lines
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, · 72 unmodified lines
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:
net/core/neighbour.c+12−5
@@ -2410,20 +2410,27 @@ static struct file_operations neigh_stat_seq_fops = { · 2409 unmodified lines
2410#endif /* CONFIG_PROC_FS */2410#endif /* CONFIG_PROC_FS */
2411 2411
2412#ifdef CONFIG_ARPD2412#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:
net/core/rtnetlink.c+26−13
@@ -273,6 +273,25 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, · 272 unmodified lines
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) · 279 unmodified lines
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) · 22 unmodified lines
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) · 1 unmodified line
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) · 32 unmodified lines
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:
net/decnet/dn_rules.c+6−0
@@ -241,6 +241,12 @@ static u32 dn_fib_rule_default_pref(void) · 240 unmodified lines
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);
net/decnet/dn_table.c+29−5
@@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern · 262 unmodified lines
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, · 66 unmodified lines
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:
net/ipv4/devinet.c+13−5
@@ -1120,6 +1120,16 @@ static struct notifier_block ip_netdev_notifier = { · 1119 unmodified lines
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, · 82 unmodified lines
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:
net/ipv4/fib_rules.c+8−0
@@ -299,6 +299,13 @@ static u32 fib4_rule_default_pref(void) · 298 unmodified lines
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 = { · 3 unmodified lines
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,
net/ipv4/fib_semantics.c+30−6
@@ -273,25 +273,49 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev) · 272 unmodified lines
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);
net/ipv6/addrconf.c+32−38
@@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope) · 3097 unmodified lines
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, · 221 unmodified lines
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) · 12 unmodified lines
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, · 36 unmodified lines
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) · 88 unmodified lines
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: · 1 unmodified line
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, · 39 unmodified lines
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:
net/ipv6/fib6_rules.c+7−0
@@ -232,6 +232,12 @@ static u32 fib6_rule_default_pref(void) · 231 unmodified lines
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 = { · 3 unmodified lines
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,
net/ipv6/route.c+17−6
@@ -2006,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) · 2005 unmodified lines
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) · 188 unmodified lines
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) · 3 unmodified lines
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:
net/netlabel/netlabel_cipso_v4.c+1−1
@@ -452,7 +452,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) · 451 unmodified lines
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;
net/netlabel/netlabel_mgmt.c+2−2
@@ -356,7 +356,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) · 355 unmodified lines
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) · 129 unmodified lines
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,
net/netlabel/netlabel_unlabeled.c+1−1
@@ -138,7 +138,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) · 137 unmodified lines
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,
net/netlink/af_netlink.c+6−7
@@ -1148,7 +1148,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, · 1147 unmodified lines
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) · 280 unmodified lines
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 else1442 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
net/netlink/genetlink.c+1−1
@@ -480,7 +480,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid, · 479 unmodified lines
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