diff options
author | Patrick McHardy <kaber@trash.net> | 2007-02-01 02:16:40 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-02-08 15:38:41 -0500 |
commit | 26932566a42d46aee7e5d526cb34fba9380cad10 (patch) | |
tree | 3991d9209ddf2454ba4c71daccdc33951811dcf1 /net/ipv6 | |
parent | 2cf6c36cb46d69057db2ebae0d8ec352e065f48b (diff) |
[NETLINK]: Don't BUG on undersized allocations
Currently netlink users BUG when the allocated skb for an event
notification is undersized. While this is certainly a kernel bug,
its not critical and crashing the kernel is too drastic, especially
when considering that these errors have appeared multiple times in
the past and it BUGs even if no listeners are present.
This patch replaces BUG by WARN_ON and changes the notification
functions to inform potential listeners of undersized allocations
using a unique error code (EMSGSIZE).
Signed-off-by: Patrick McHardy <kaber@trash.net>
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/route.c | 14 |
2 files changed, 54 insertions, 30 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index e3854696988d..fe5e1d833871 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -3117,7 +3117,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
3117 | 3117 | ||
3118 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); | 3118 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); |
3119 | if (nlh == NULL) | 3119 | if (nlh == NULL) |
3120 | return -ENOBUFS; | 3120 | return -EMSGSIZE; |
3121 | 3121 | ||
3122 | put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), | 3122 | put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope), |
3123 | ifa->idev->dev->ifindex); | 3123 | ifa->idev->dev->ifindex); |
@@ -3137,8 +3137,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa, | |||
3137 | } | 3137 | } |
3138 | 3138 | ||
3139 | if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 || | 3139 | if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 || |
3140 | put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) | 3140 | put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) { |
3141 | return nlmsg_cancel(skb, nlh); | 3141 | nlmsg_cancel(skb, nlh); |
3142 | return -EMSGSIZE; | ||
3143 | } | ||
3142 | 3144 | ||
3143 | return nlmsg_end(skb, nlh); | 3145 | return nlmsg_end(skb, nlh); |
3144 | } | 3146 | } |
@@ -3155,13 +3157,15 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca, | |||
3155 | 3157 | ||
3156 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); | 3158 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); |
3157 | if (nlh == NULL) | 3159 | if (nlh == NULL) |
3158 | return -ENOBUFS; | 3160 | return -EMSGSIZE; |
3159 | 3161 | ||
3160 | put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); | 3162 | put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); |
3161 | if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 || | 3163 | if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 || |
3162 | put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, | 3164 | put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp, |
3163 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) | 3165 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) { |
3164 | return nlmsg_cancel(skb, nlh); | 3166 | nlmsg_cancel(skb, nlh); |
3167 | return -EMSGSIZE; | ||
3168 | } | ||
3165 | 3169 | ||
3166 | return nlmsg_end(skb, nlh); | 3170 | return nlmsg_end(skb, nlh); |
3167 | } | 3171 | } |
@@ -3178,13 +3182,15 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca, | |||
3178 | 3182 | ||
3179 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); | 3183 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags); |
3180 | if (nlh == NULL) | 3184 | if (nlh == NULL) |
3181 | return -ENOBUFS; | 3185 | return -EMSGSIZE; |
3182 | 3186 | ||
3183 | put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); | 3187 | put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex); |
3184 | if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 || | 3188 | if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 || |
3185 | put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, | 3189 | put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp, |
3186 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) | 3190 | INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) { |
3187 | return nlmsg_cancel(skb, nlh); | 3191 | nlmsg_cancel(skb, nlh); |
3192 | return -EMSGSIZE; | ||
3193 | } | ||
3188 | 3194 | ||
3189 | return nlmsg_end(skb, nlh); | 3195 | return nlmsg_end(skb, nlh); |
3190 | } | 3196 | } |
@@ -3334,9 +3340,12 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh, | |||
3334 | 3340 | ||
3335 | err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, | 3341 | err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid, |
3336 | nlh->nlmsg_seq, RTM_NEWADDR, 0); | 3342 | nlh->nlmsg_seq, RTM_NEWADDR, 0); |
3337 | /* failure implies BUG in inet6_ifaddr_msgsize() */ | 3343 | if (err < 0) { |
3338 | BUG_ON(err < 0); | 3344 | /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ |
3339 | 3345 | WARN_ON(err == -EMSGSIZE); | |
3346 | kfree_skb(skb); | ||
3347 | goto errout_ifa; | ||
3348 | } | ||
3340 | err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); | 3349 | err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid); |
3341 | errout_ifa: | 3350 | errout_ifa: |
3342 | in6_ifa_put(ifa); | 3351 | in6_ifa_put(ifa); |
@@ -3354,9 +3363,12 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa) | |||
3354 | goto errout; | 3363 | goto errout; |
3355 | 3364 | ||
3356 | err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); | 3365 | err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0); |
3357 | /* failure implies BUG in inet6_ifaddr_msgsize() */ | 3366 | if (err < 0) { |
3358 | BUG_ON(err < 0); | 3367 | /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */ |
3359 | 3368 | WARN_ON(err == -EMSGSIZE); | |
3369 | kfree_skb(skb); | ||
3370 | goto errout; | ||
3371 | } | ||
3360 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3372 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3361 | errout: | 3373 | errout: |
3362 | if (err < 0) | 3374 | if (err < 0) |
@@ -3426,7 +3438,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | |||
3426 | 3438 | ||
3427 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); | 3439 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags); |
3428 | if (nlh == NULL) | 3440 | if (nlh == NULL) |
3429 | return -ENOBUFS; | 3441 | return -EMSGSIZE; |
3430 | 3442 | ||
3431 | hdr = nlmsg_data(nlh); | 3443 | hdr = nlmsg_data(nlh); |
3432 | hdr->ifi_family = AF_INET6; | 3444 | hdr->ifi_family = AF_INET6; |
@@ -3469,7 +3481,8 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev, | |||
3469 | return nlmsg_end(skb, nlh); | 3481 | return nlmsg_end(skb, nlh); |
3470 | 3482 | ||
3471 | nla_put_failure: | 3483 | nla_put_failure: |
3472 | return nlmsg_cancel(skb, nlh); | 3484 | nlmsg_cancel(skb, nlh); |
3485 | return -EMSGSIZE; | ||
3473 | } | 3486 | } |
3474 | 3487 | ||
3475 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 3488 | static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) |
@@ -3507,9 +3520,12 @@ void inet6_ifinfo_notify(int event, struct inet6_dev *idev) | |||
3507 | goto errout; | 3520 | goto errout; |
3508 | 3521 | ||
3509 | err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); | 3522 | err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0); |
3510 | /* failure implies BUG in inet6_if_nlmsg_size() */ | 3523 | if (err < 0) { |
3511 | BUG_ON(err < 0); | 3524 | /* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */ |
3512 | 3525 | WARN_ON(err == -EMSGSIZE); | |
3526 | kfree_skb(skb); | ||
3527 | goto errout; | ||
3528 | } | ||
3513 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); | 3529 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC); |
3514 | errout: | 3530 | errout: |
3515 | if (err < 0) | 3531 | if (err < 0) |
@@ -3533,7 +3549,7 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | |||
3533 | 3549 | ||
3534 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags); | 3550 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags); |
3535 | if (nlh == NULL) | 3551 | if (nlh == NULL) |
3536 | return -ENOBUFS; | 3552 | return -EMSGSIZE; |
3537 | 3553 | ||
3538 | pmsg = nlmsg_data(nlh); | 3554 | pmsg = nlmsg_data(nlh); |
3539 | pmsg->prefix_family = AF_INET6; | 3555 | pmsg->prefix_family = AF_INET6; |
@@ -3558,7 +3574,8 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev, | |||
3558 | return nlmsg_end(skb, nlh); | 3574 | return nlmsg_end(skb, nlh); |
3559 | 3575 | ||
3560 | nla_put_failure: | 3576 | nla_put_failure: |
3561 | return nlmsg_cancel(skb, nlh); | 3577 | nlmsg_cancel(skb, nlh); |
3578 | return -EMSGSIZE; | ||
3562 | } | 3579 | } |
3563 | 3580 | ||
3564 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, | 3581 | static void inet6_prefix_notify(int event, struct inet6_dev *idev, |
@@ -3572,9 +3589,12 @@ static void inet6_prefix_notify(int event, struct inet6_dev *idev, | |||
3572 | goto errout; | 3589 | goto errout; |
3573 | 3590 | ||
3574 | err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); | 3591 | err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0); |
3575 | /* failure implies BUG in inet6_prefix_nlmsg_size() */ | 3592 | if (err < 0) { |
3576 | BUG_ON(err < 0); | 3593 | /* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */ |
3577 | 3594 | WARN_ON(err == -EMSGSIZE); | |
3595 | kfree_skb(skb); | ||
3596 | goto errout; | ||
3597 | } | ||
3578 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); | 3598 | err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC); |
3579 | errout: | 3599 | errout: |
3580 | if (err < 0) | 3600 | if (err < 0) |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 5f0043c30b70..f4fda80a41a2 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -2040,7 +2040,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2040 | 2040 | ||
2041 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); | 2041 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags); |
2042 | if (nlh == NULL) | 2042 | if (nlh == NULL) |
2043 | return -ENOBUFS; | 2043 | return -EMSGSIZE; |
2044 | 2044 | ||
2045 | rtm = nlmsg_data(nlh); | 2045 | rtm = nlmsg_data(nlh); |
2046 | rtm->rtm_family = AF_INET6; | 2046 | rtm->rtm_family = AF_INET6; |
@@ -2111,7 +2111,8 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt, | |||
2111 | return nlmsg_end(skb, nlh); | 2111 | return nlmsg_end(skb, nlh); |
2112 | 2112 | ||
2113 | nla_put_failure: | 2113 | nla_put_failure: |
2114 | return nlmsg_cancel(skb, nlh); | 2114 | nlmsg_cancel(skb, nlh); |
2115 | return -EMSGSIZE; | ||
2115 | } | 2116 | } |
2116 | 2117 | ||
2117 | int rt6_dump_route(struct rt6_info *rt, void *p_arg) | 2118 | int rt6_dump_route(struct rt6_info *rt, void *p_arg) |
@@ -2222,9 +2223,12 @@ void inet6_rt_notify(int event, struct rt6_info *rt, struct nl_info *info) | |||
2222 | goto errout; | 2223 | goto errout; |
2223 | 2224 | ||
2224 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); | 2225 | err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0); |
2225 | /* failure implies BUG in rt6_nlmsg_size() */ | 2226 | if (err < 0) { |
2226 | BUG_ON(err < 0); | 2227 | /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */ |
2227 | 2228 | WARN_ON(err == -EMSGSIZE); | |
2229 | kfree_skb(skb); | ||
2230 | goto errout; | ||
2231 | } | ||
2228 | err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); | 2232 | err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any()); |
2229 | errout: | 2233 | errout: |
2230 | if (err < 0) | 2234 | if (err < 0) |