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.
Unified · Split
| @@ -174,6 +174,7 @@ int netlink_sendskb(struct sock *sk, struct sk_buff *skb, int protocol); · 173 unmodified lines | ||
| 174 | 174 | */ |
| 175 | 175 | #define NLMSG_GOODORDER 0 |
| 176 | 176 | #define NLMSG_GOODSIZE (SKB_MAX_ORDER(0, NLMSG_GOODORDER)) |
| 177 | +#define NLMSG_DEFAULT_SIZE (NLMSG_GOODSIZE - NLMSG_HDRLEN) | |
| 177 | 178 | |
| 178 | 179 | |
| 179 | 180 | struct netlink_callback |
| @@ -52,6 +52,7 @@ struct fib_rules_ops · 51 unmodified lines | ||
| 52 | 52 | struct nlmsghdr *, |
| 53 | 53 | struct fib_rule_hdr *); |
| 54 | 54 | u32 (*default_pref)(void); |
| 55 | + size_t (*nlmsg_payload)(struct fib_rule *); | |
| 55 | 56 | |
| 56 | 57 | int nlgroup; |
| 57 | 58 | struct nla_policy *policy; |
| @@ -500,14 +500,15 @@ static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb, · 499 unmodified lines | ||
| 500 | 500 | |
| 501 | 501 | /** |
| 502 | 502 | * nlmsg_new - Allocate a new netlink message |
| 503 | − * @size: maximum size of message | |
| 503 | + * @payload: size of the message payload | |
| 504 | 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 | */ |
| 508 | −static inline struct sk_buff *nlmsg_new(int size, gfp_t flags) | |
| 509 | +static 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 | /** |
| @@ -77,8 +77,7 @@ static int prepare_reply(struct genl_info *info, u8 cmd, struct sk_buff **skbp, · 76 unmodified lines | ||
| 77 | 77 | /* |
| 78 | 78 | * If new attributes are added, please revisit this allocation |
| 79 | 79 | */ |
| 80 | − size = nlmsg_total_size(genlmsg_total_size(size)); | |
| 81 | − skb = nlmsg_new(size, GFP_KERNEL); | |
| 80 | + skb = nlmsg_new(genlmsg_total_size(size), GFP_KERNEL); | |
| 82 | 81 | if (!skb) |
| 83 | 82 | return -ENOMEM; |
| 84 | 83 | |
| @@ -15,6 +15,18 @@ · 14 unmodified lines | ||
| 15 | 15 | #include <net/netlink.h> |
| 16 | 16 | #include "br_private.h" |
| 17 | 17 | |
| 18 | +static 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 | 31 | * Create one netlink message for one interface |
| 20 | 32 | * Contains port and master info as well as carrier and bridge state. |
| @@ -77,19 +89,16 @@ rtattr_failure: · 56 unmodified lines | ||
| 77 | 89 | void br_ifinfo_notify(int event, struct net_bridge_port *port) |
| 78 | 90 | { |
| 79 | 91 | struct sk_buff *skb; |
| 80 | − int payload = sizeof(struct ifinfomsg) + 128; | |
| 81 | 92 | int err = -ENOBUFS; |
| 82 | 93 | |
| 83 | 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 | 96 | if (skb == NULL) |
| 86 | 97 | goto errout; |
| 87 | 98 | |
| 88 | 99 | err = br_fill_ifinfo(skb, port, 0, 0, event, 0); |
| 89 | − if (err < 0) { | |
| 90 | − kfree_skb(skb); | |
| 91 | − goto errout; | |
| 92 | − } | |
| 100 | + /* failure implies BUG in br_nlmsg_size() */ | |
| 101 | + BUG_ON(err < 0); | |
| 93 | 102 | |
| 94 | 103 | err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC); |
| 95 | 104 | errout: |
| @@ -306,6 +306,22 @@ errout: · 305 unmodified lines | ||
| 306 | 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 | 325 | static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule, |
| 310 | 326 | u32 pid, u32 seq, int type, int flags, |
| 311 | 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 | 400 | struct sk_buff *skb; |
| 385 | 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 | 404 | if (skb == NULL) |
| 389 | 405 | goto errout; |
| 390 | 406 | |
| 391 | 407 | err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops); |
| 392 | − if (err < 0) { | |
| 393 | − kfree_skb(skb); | |
| 394 | − goto errout; | |
| 395 | − } | |
| 408 | + /* failure implies BUG in fib_rule_nlmsg_size() */ | |
| 409 | + BUG_ON(err < 0); | |
| 396 | 410 | |
| 397 | 411 | err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL); |
| 398 | 412 | errout: |
| @@ -2410,20 +2410,27 @@ static struct file_operations neigh_stat_seq_fops = { · 2409 unmodified lines | ||
| 2410 | 2410 | #endif /* CONFIG_PROC_FS */ |
| 2411 | 2411 | |
| 2412 | 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 | 2422 | static void __neigh_notify(struct neighbour *n, int type, int flags) |
| 2414 | 2423 | { |
| 2415 | 2424 | struct sk_buff *skb; |
| 2416 | 2425 | int err = -ENOBUFS; |
| 2417 | 2426 | |
| 2418 | − skb = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | |
| 2427 | + skb = nlmsg_new(neigh_nlmsg_size(), GFP_ATOMIC); | |
| 2419 | 2428 | if (skb == NULL) |
| 2420 | 2429 | goto errout; |
| 2421 | 2430 | |
| 2422 | 2431 | err = neigh_fill_info(skb, n, 0, 0, type, flags); |
| 2423 | − if (err < 0) { | |
| 2424 | − kfree_skb(skb); | |
| 2425 | − goto errout; | |
| 2426 | − } | |
| 2432 | + /* failure implies BUG in neigh_nlmsg_size() */ | |
| 2433 | + BUG_ON(err < 0); | |
| 2427 | 2434 | |
| 2428 | 2435 | err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); |
| 2429 | 2436 | errout: |
| @@ -273,6 +273,25 @@ static void copy_rtnl_link_stats(struct rtnl_link_stats *a, · 272 unmodified lines | ||
| 273 | 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 | 295 | static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, |
| 277 | 296 | void *iwbuf, int iwbuflen, int type, u32 pid, |
| 278 | 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 | 577 | struct sk_buff *nskb; |
| 559 | 578 | char *iw_buf = NULL, *iw = NULL; |
| 560 | 579 | int iw_buf_len = 0; |
| 561 | − int err, payload; | |
| 580 | + int err; | |
| 562 | 581 | |
| 563 | 582 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); |
| 564 | 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 | 607 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ |
| 589 | 608 | |
| 590 | − payload = NLMSG_ALIGN(sizeof(struct ifinfomsg) + | |
| 591 | − nla_total_size(iw_buf_len)); | |
| 592 | − nskb = nlmsg_new(nlmsg_total_size(payload), GFP_KERNEL); | |
| 609 | + nskb = nlmsg_new(if_nlmsg_size(iw_buf_len), GFP_KERNEL); | |
| 593 | 610 | if (nskb == NULL) { |
| 594 | 611 | err = -ENOBUFS; |
| 595 | 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 | 615 | err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK, |
| 599 | 616 | NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0); |
| 600 | − if (err <= 0) { | |
| 601 | − kfree_skb(nskb); | |
| 602 | − goto errout; | |
| 603 | − } | |
| 617 | + /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */ | |
| 618 | + BUG_ON(err < 0); | |
| 604 | 619 | |
| 605 | 620 | err = rtnl_unicast(nskb, NETLINK_CB(skb).pid); |
| 606 | 621 | errout: |
| @@ -639,15 +654,13 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change) · 32 unmodified lines | ||
| 639 | 654 | struct sk_buff *skb; |
| 640 | 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 | 658 | if (skb == NULL) |
| 644 | 659 | goto errout; |
| 645 | 660 | |
| 646 | 661 | err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0); |
| 647 | − if (err < 0) { | |
| 648 | − kfree_skb(skb); | |
| 649 | − goto errout; | |
| 650 | − } | |
| 662 | + /* failure implies BUG in if_nlmsg_size() */ | |
| 663 | + BUG_ON(err < 0); | |
| 651 | 664 | |
| 652 | 665 | err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL); |
| 653 | 666 | errout: |
| @@ -241,6 +241,12 @@ static u32 dn_fib_rule_default_pref(void) · 240 unmodified lines | ||
| 241 | 241 | return 0; |
| 242 | 242 | } |
| 243 | 243 | |
| 244 | +static 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 | + | |
| 244 | 250 | int dn_fib_dump_rules(struct sk_buff *skb, struct netlink_callback *cb) |
| 245 | 251 | { |
| 246 | 252 | return fib_rules_dump(skb, cb, AF_DECnet); |
| @@ -263,6 +263,32 @@ static int dn_fib_nh_match(struct rtmsg *r, struct nlmsghdr *nlh, struct dn_kern · 262 unmodified lines | ||
| 263 | 263 | return 0; |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | +static 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 | + | |
| 266 | 292 | static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event, |
| 267 | 293 | u32 tb_id, u8 type, u8 scope, void *dst, int dst_len, |
| 268 | 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 | 361 | u32 pid = req ? req->pid : 0; |
| 336 | 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 | 365 | if (skb == NULL) |
| 340 | 366 | goto errout; |
| 341 | 367 | |
| 342 | 368 | err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id, |
| 343 | 369 | f->fn_type, f->fn_scope, &f->fn_key, z, |
| 344 | 370 | DN_FIB_INFO(f), 0); |
| 345 | − if (err < 0) { | |
| 346 | − kfree_skb(skb); | |
| 347 | − goto errout; | |
| 348 | − } | |
| 371 | + /* failure implies BUG in dn_fib_nlmsg_size() */ | |
| 372 | + BUG_ON(err < 0); | |
| 349 | 373 | |
| 350 | 374 | err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL); |
| 351 | 375 | errout: |
| @@ -1120,6 +1120,16 @@ static struct notifier_block ip_netdev_notifier = { · 1119 unmodified lines | ||
| 1120 | 1120 | .notifier_call =inetdev_event, |
| 1121 | 1121 | }; |
| 1122 | 1122 | |
| 1123 | +static 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 | + | |
| 1123 | 1133 | static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa, |
| 1124 | 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 | 1218 | u32 seq = nlh ? nlh->nlmsg_seq : 0; |
| 1209 | 1219 | int err = -ENOBUFS; |
| 1210 | 1220 | |
| 1211 | − skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | |
| 1221 | + skb = nlmsg_new(inet_nlmsg_size(), GFP_KERNEL); | |
| 1212 | 1222 | if (skb == NULL) |
| 1213 | 1223 | goto errout; |
| 1214 | 1224 | |
| 1215 | 1225 | err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); |
| 1216 | − if (err < 0) { | |
| 1217 | − kfree_skb(skb); | |
| 1218 | − goto errout; | |
| 1219 | − } | |
| 1226 | + /* failure implies BUG in inet_nlmsg_size() */ | |
| 1227 | + BUG_ON(err < 0); | |
| 1220 | 1228 | |
| 1221 | 1229 | err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); |
| 1222 | 1230 | errout: |
| @@ -299,6 +299,13 @@ static u32 fib4_rule_default_pref(void) · 298 unmodified lines | ||
| 299 | 299 | return 0; |
| 300 | 300 | } |
| 301 | 301 | |
| 302 | +static 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 | + | |
| 302 | 309 | static struct fib_rules_ops fib4_rules_ops = { |
| 303 | 310 | .family = AF_INET, |
| 304 | 311 | .rule_size = sizeof(struct fib4_rule), |
| @@ -308,6 +315,7 @@ static struct fib_rules_ops fib4_rules_ops = { · 3 unmodified lines | ||
| 308 | 315 | .compare = fib4_rule_compare, |
| 309 | 316 | .fill = fib4_rule_fill, |
| 310 | 317 | .default_pref = fib4_rule_default_pref, |
| 318 | + .nlmsg_payload = fib4_rule_nlmsg_payload, | |
| 311 | 319 | .nlgroup = RTNLGRP_IPV4_RULE, |
| 312 | 320 | .policy = fib4_rule_policy, |
| 313 | 321 | .rules_list = &fib4_rules, |
| @@ -273,25 +273,49 @@ int ip_fib_check_default(__be32 gw, struct net_device *dev) · 272 unmodified lines | ||
| 273 | 273 | return -1; |
| 274 | 274 | } |
| 275 | 275 | |
| 276 | +static 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 | + | |
| 276 | 303 | void rtmsg_fib(int event, __be32 key, struct fib_alias *fa, |
| 277 | 304 | int dst_len, u32 tb_id, struct nl_info *info) |
| 278 | 305 | { |
| 279 | 306 | struct sk_buff *skb; |
| 280 | − int payload = sizeof(struct rtmsg) + 256; | |
| 281 | 307 | u32 seq = info->nlh ? info->nlh->nlmsg_seq : 0; |
| 282 | 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 | 311 | if (skb == NULL) |
| 286 | 312 | goto errout; |
| 287 | 313 | |
| 288 | 314 | err = fib_dump_info(skb, info->pid, seq, event, tb_id, |
| 289 | 315 | fa->fa_type, fa->fa_scope, key, dst_len, |
| 290 | 316 | fa->fa_tos, fa->fa_info, 0); |
| 291 | − if (err < 0) { | |
| 292 | − kfree_skb(skb); | |
| 293 | − goto errout; | |
| 294 | − } | |
| 317 | + /* failure implies BUG in fib_nlmsg_size() */ | |
| 318 | + BUG_ON(err < 0); | |
| 295 | 319 | |
| 296 | 320 | err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, |
| 297 | 321 | info->nlh, GFP_KERNEL); |
| @@ -3098,10 +3098,9 @@ static inline int rt_scope(int ifa_scope) · 3097 unmodified lines | ||
| 3098 | 3098 | |
| 3099 | 3099 | static inline int inet6_ifaddr_msgsize(void) |
| 3100 | 3100 | { |
| 3101 | − return nlmsg_total_size(sizeof(struct ifaddrmsg) + | |
| 3102 | − nla_total_size(16) + | |
| 3103 | − nla_total_size(sizeof(struct ifa_cacheinfo)) + | |
| 3104 | − 128); | |
| 3101 | + return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) | |
| 3102 | + + nla_total_size(16) /* IFA_ADDRESS */ | |
| 3103 | + + nla_total_size(sizeof(struct ifa_cacheinfo)); | |
| 3105 | 3104 | } |
| 3106 | 3105 | |
| 3107 | 3106 | static 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 | 3329 | err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, |
| 3331 | 3330 | nlh->nlmsg_seq, RTM_NEWADDR, 0); |
| 3332 | − if (err < 0) { | |
| 3333 | − kfree_skb(skb); | |
| 3334 | − goto errout_ifa; | |
| 3335 | − } | |
| 3331 | + /* failure implies BUG in inet6_ifaddr_msgsize() */ | |
| 3332 | + BUG_ON(err < 0); | |
| 3336 | 3333 | |
| 3337 | 3334 | err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); |
| 3338 | 3335 | errout_ifa: |
| @@ -3351,10 +3348,8 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) · 12 unmodified lines | ||
| 3351 | 3348 | goto errout; |
| 3352 | 3349 | |
| 3353 | 3350 | err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); |
| 3354 | − if (err < 0) { | |
| 3355 | − kfree_skb(skb); | |
| 3356 | − goto errout; | |
| 3357 | − } | |
| 3351 | + /* failure implies BUG in inet6_ifaddr_msgsize() */ | |
| 3352 | + BUG_ON(err < 0); | |
| 3358 | 3353 | |
| 3359 | 3354 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
| 3360 | 3355 | errout: |
| @@ -3397,16 +3392,19 @@ static void inline ipv6_store_devconf(struct ipv6_devconf *cnf, · 36 unmodified lines | ||
| 3397 | 3392 | array[DEVCONF_PROXY_NDP] = cnf->proxy_ndp; |
| 3398 | 3393 | } |
| 3399 | 3394 | |
| 3400 | −/* Maximum length of ifinfomsg attributes */ | |
| 3401 | −#define INET6_IFINFO_RTA_SPACE \ | |
| 3402 | − RTA_SPACE(IFNAMSIZ) /* IFNAME */ + \ | |
| 3403 | − RTA_SPACE(MAX_ADDR_LEN) /* ADDRESS */ + \ | |
| 3404 | − RTA_SPACE(sizeof(u32)) /* MTU */ + \ | |
| 3405 | − RTA_SPACE(sizeof(int)) /* LINK */ + \ | |
| 3406 | − RTA_SPACE(0) /* PROTINFO */ + \ | |
| 3407 | − RTA_SPACE(sizeof(u32)) /* FLAGS */ + \ | |
| 3408 | − RTA_SPACE(sizeof(struct ifla_cacheinfo)) /* CACHEINFO */ + \ | |
| 3409 | − RTA_SPACE(sizeof(__s32[DEVCONF_MAX])) /* CONF */ | |
| 3395 | +static inline size_t inet6_if_nlmsg_size(void) | |
| 3396 | +{ | |
| 3397 | + return NLMSG_ALIGN(sizeof(struct ifinfomsg)) | |
| 3398 | + + nla_total_size(IFNAMSIZ) /* IFLA_IFNAME */ | |
| 3399 | + + nla_total_size(MAX_ADDR_LEN) /* IFLA_ADDRESS */ | |
| 3400 | + + nla_total_size(4) /* IFLA_MTU */ | |
| 3401 | + + nla_total_size(4) /* IFLA_LINK */ | |
| 3402 | + + nla_total_size( /* IFLA_PROTINFO */ | |
| 3403 | + nla_total_size(4) /* IFLA_INET6_FLAGS */ | |
| 3404 | + + nla_total_size(sizeof(struct ifla_cacheinfo)) | |
| 3405 | + + nla_total_size(DEVCONF_MAX * 4) /* IFLA_INET6_CONF */ | |
| 3406 | + ); | |
| 3407 | +} | |
| 3410 | 3408 | |
| 3411 | 3409 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, |
| 3412 | 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 | ||
| 3501 | 3499 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) |
| 3502 | 3500 | { |
| 3503 | 3501 | struct sk_buff *skb; |
| 3504 | − int payload = sizeof(struct ifinfomsg) + INET6_IFINFO_RTA_SPACE; | |
| 3505 | 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 | 3505 | if (skb == NULL) |
| 3509 | 3506 | goto errout; |
| 3510 | 3507 | |
| 3511 | 3508 | err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); |
| 3512 | − if (err < 0) { | |
| 3513 | − kfree_skb(skb); | |
| 3514 | − goto errout; | |
| 3515 | − } | |
| 3509 | + /* failure implies BUG in inet6_if_nlmsg_size() */ | |
| 3510 | + BUG_ON(err < 0); | |
| 3516 | 3511 | |
| 3517 | 3512 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
| 3518 | 3513 | errout: |
| @@ -3520,10 +3515,12 @@ errout: · 1 unmodified line | ||
| 3520 | 3515 | rtnl_set_sk_err(RTNLGRP_IPV6_IFADDR, err); |
| 3521 | 3516 | } |
| 3522 | 3517 | |
| 3523 | −/* Maximum length of prefix_cacheinfo attributes */ | |
| 3524 | −#define INET6_PREFIX_RTA_SPACE \ | |
| 3525 | − RTA_SPACE(sizeof(((struct prefix_info *)NULL)->prefix)) /* ADDRESS */ + \ | |
| 3526 | − RTA_SPACE(sizeof(struct prefix_cacheinfo)) /* CACHEINFO */ | |
| 3518 | +static inline size_t inet6_prefix_nlmsg_size(void) | |
| 3519 | +{ | |
| 3520 | + return NLMSG_ALIGN(sizeof(struct prefixmsg)) | |
| 3521 | + + nla_total_size(sizeof(struct in6_addr)) | |
| 3522 | + + nla_total_size(sizeof(struct prefix_cacheinfo)); | |
| 3523 | +} | |
| 3527 | 3524 | |
| 3528 | 3525 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, |
| 3529 | 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 | 3566 | struct prefix_info *pinfo) |
| 3570 | 3567 | { |
| 3571 | 3568 | struct sk_buff *skb; |
| 3572 | − int payload = sizeof(struct prefixmsg) + INET6_PREFIX_RTA_SPACE; | |
| 3573 | 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 | 3572 | if (skb == NULL) |
| 3577 | 3573 | goto errout; |
| 3578 | 3574 | |
| 3579 | 3575 | err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); |
| 3580 | − if (err < 0) { | |
| 3581 | − kfree_skb(skb); | |
| 3582 | − goto errout; | |
| 3583 | − } | |
| 3576 | + /* failure implies BUG in inet6_prefix_nlmsg_size() */ | |
| 3577 | + BUG_ON(err < 0); | |
| 3584 | 3578 | |
| 3585 | 3579 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
| 3586 | 3580 | errout: |
| @@ -232,6 +232,12 @@ static u32 fib6_rule_default_pref(void) · 231 unmodified lines | ||
| 232 | 232 | return 0x3FFF; |
| 233 | 233 | } |
| 234 | 234 | |
| 235 | +static 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 | + | |
| 235 | 241 | static struct fib_rules_ops fib6_rules_ops = { |
| 236 | 242 | .family = AF_INET6, |
| 237 | 243 | .rule_size = sizeof(struct fib6_rule), |
| @@ -241,6 +247,7 @@ static struct fib_rules_ops fib6_rules_ops = { · 3 unmodified lines | ||
| 241 | 247 | .compare = fib6_rule_compare, |
| 242 | 248 | .fill = fib6_rule_fill, |
| 243 | 249 | .default_pref = fib6_rule_default_pref, |
| 250 | + .nlmsg_payload = fib6_rule_nlmsg_payload, | |
| 244 | 251 | .nlgroup = RTNLGRP_IPV6_RULE, |
| 245 | 252 | .policy = fib6_rule_policy, |
| 246 | 253 | .rules_list = &fib6_rules, |
| @@ -2006,6 +2006,20 @@ int inet6_rtm_newroute(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) · 2005 unmodified lines | ||
| 2006 | 2006 | return ip6_route_add(&cfg); |
| 2007 | 2007 | } |
| 2008 | 2008 | |
| 2009 | +static 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 | + | |
| 2009 | 2023 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, |
| 2010 | 2024 | struct in6_addr *dst, struct in6_addr *src, |
| 2011 | 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 | 2214 | struct sk_buff *skb; |
| 2201 | 2215 | u32 pid = 0, seq = 0; |
| 2202 | 2216 | struct nlmsghdr *nlh = NULL; |
| 2203 | − int payload = sizeof(struct rtmsg) + 256; | |
| 2204 | 2217 | int err = -ENOBUFS; |
| 2205 | 2218 | |
| 2206 | 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 | 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 | 2227 | if (skb == NULL) |
| 2215 | 2228 | goto errout; |
| 2216 | 2229 | |
| 2217 | 2230 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); |
| 2218 | − if (err < 0) { | |
| 2219 | − kfree_skb(skb); | |
| 2220 | − goto errout; | |
| 2221 | − } | |
| 2231 | + /* failure implies BUG in rt6_nlmsg_size() */ | |
| 2232 | + BUG_ON(err < 0); | |
| 2222 | 2233 | |
| 2223 | 2234 | err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); |
| 2224 | 2235 | errout: |
| @@ -452,7 +452,7 @@ static int netlbl_cipsov4_list(struct sk_buff *skb, struct genl_info *info) · 451 unmodified lines | ||
| 452 | 452 | } |
| 453 | 453 | |
| 454 | 454 | list_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 | 456 | if (ans_skb == NULL) { |
| 457 | 457 | ret_val = -ENOMEM; |
| 458 | 458 | goto list_failure; |
| @@ -356,7 +356,7 @@ static int netlbl_mgmt_listdef(struct sk_buff *skb, struct genl_info *info) · 355 unmodified lines | ||
| 356 | 356 | void *data; |
| 357 | 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 | 360 | if (ans_skb == NULL) |
| 361 | 361 | return -ENOMEM; |
| 362 | 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 | 492 | struct sk_buff *ans_skb = NULL; |
| 493 | 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 | 496 | if (ans_skb == NULL) |
| 497 | 497 | return -ENOMEM; |
| 498 | 498 | data = netlbl_netlink_hdr_put(ans_skb, |
| @@ -138,7 +138,7 @@ static int netlbl_unlabel_list(struct sk_buff *skb, struct genl_info *info) · 137 unmodified lines | ||
| 138 | 138 | struct sk_buff *ans_skb; |
| 139 | 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 | 142 | if (ans_skb == NULL) |
| 143 | 143 | goto list_failure; |
| 144 | 144 | data = netlbl_netlink_hdr_put(ans_skb, |
| @@ -1148,7 +1148,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, · 1147 unmodified lines | ||
| 1148 | 1148 | if (len > sk->sk_sndbuf - 32) |
| 1149 | 1149 | goto out; |
| 1150 | 1150 | err = -ENOBUFS; |
| 1151 | − skb = nlmsg_new(len, GFP_KERNEL); | |
| 1151 | + skb = alloc_skb(len, GFP_KERNEL); | |
| 1152 | 1152 | if (skb==NULL) |
| 1153 | 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 | 1435 | struct sk_buff *skb; |
| 1436 | 1436 | struct nlmsghdr *rep; |
| 1437 | 1437 | struct nlmsgerr *errmsg; |
| 1438 | − int size; | |
| 1438 | + size_t payload = sizeof(*errmsg); | |
| 1439 | 1439 | |
| 1440 | − if (err == 0) | |
| 1441 | − size = nlmsg_total_size(sizeof(*errmsg)); | |
| 1442 | − else | |
| 1443 | − size = nlmsg_total_size(sizeof(*errmsg) + nlmsg_len(nlh)); | |
| 1440 | + /* error messages get the original request appened */ | |
| 1441 | + if (err) | |
| 1442 | + payload += nlmsg_len(nlh); | |
| 1444 | 1443 | |
| 1445 | − skb = nlmsg_new(size, GFP_KERNEL); | |
| 1444 | + skb = nlmsg_new(payload, GFP_KERNEL); | |
| 1446 | 1445 | if (!skb) { |
| 1447 | 1446 | struct sock *sk; |
| 1448 | 1447 | |
| @@ -480,7 +480,7 @@ static struct sk_buff *ctrl_build_msg(struct genl_family *family, u32 pid, · 479 unmodified lines | ||
| 480 | 480 | struct sk_buff *skb; |
| 481 | 481 | int err; |
| 482 | 482 | |
| 483 | − skb = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); | |
| 483 | + skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | |
| 484 | 484 | if (skb == NULL) |
| 485 | 485 | return ERR_PTR(-ENOBUFS); |
| 486 | 486 | |