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/ipv6 | |
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/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 70 | ||||
-rw-r--r-- | net/ipv6/fib6_rules.c | 7 | ||||
-rw-r--r-- | net/ipv6/route.c | 23 |
3 files changed, 56 insertions, 44 deletions
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 | ||
3099 | static inline int inet6_ifaddr_msgsize(void) | 3099 | static 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 | ||
3107 | static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | 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, | |||
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); |
3338 | errout_ifa: | 3335 | errout_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); |
3360 | errout: | 3355 | errout: |
@@ -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 */ | 3395 | static 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 | ||
3411 | static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | 3409 | static 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) | |||
3501 | void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | 3499 | void 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); |
3518 | errout: | 3513 | errout: |
@@ -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 */ | 3518 | static 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 | ||
3528 | static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | 3525 | static 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); |
3586 | errout: | 3580 | errout: |
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 | ||
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 | static struct fib_rules_ops fib6_rules_ops = { | 241 | static 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 | ||
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 | static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | 2023 | static 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()); |
2224 | errout: | 2235 | errout: |