aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-02-01 02:16:40 -0500
committerDavid S. Miller <davem@sunset.davemloft.net>2007-02-08 15:38:41 -0500
commit26932566a42d46aee7e5d526cb34fba9380cad10 (patch)
tree3991d9209ddf2454ba4c71daccdc33951811dcf1 /net/ipv6
parent2cf6c36cb46d69057db2ebae0d8ec352e065f48b (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.c70
-rw-r--r--net/ipv6/route.c14
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);
3341errout_ifa: 3350errout_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);
3361errout: 3373errout:
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
3471nla_put_failure: 3483nla_put_failure:
3472 return nlmsg_cancel(skb, nlh); 3484 nlmsg_cancel(skb, nlh);
3485 return -EMSGSIZE;
3473} 3486}
3474 3487
3475static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) 3488static 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);
3514errout: 3530errout:
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
3560nla_put_failure: 3576nla_put_failure:
3561 return nlmsg_cancel(skb, nlh); 3577 nlmsg_cancel(skb, nlh);
3578 return -EMSGSIZE;
3562} 3579}
3563 3580
3564static void inet6_prefix_notify(int event, struct inet6_dev *idev, 3581static 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);
3579errout: 3599errout:
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
2113nla_put_failure: 2113nla_put_failure:
2114 return nlmsg_cancel(skb, nlh); 2114 nlmsg_cancel(skb, nlh);
2115 return -EMSGSIZE;
2115} 2116}
2116 2117
2117int rt6_dump_route(struct rt6_info *rt, void *p_arg) 2118int 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());
2229errout: 2233errout:
2230 if (err < 0) 2234 if (err < 0)