]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
[NETLINK]: Don't BUG on undersized allocations
authorPatrick McHardy <kaber@trash.net>
Thu, 1 Feb 2007 07:16:40 +0000 (23:16 -0800)
committerDavid S. Miller <davem@sunset.davemloft.net>
Thu, 8 Feb 2007 20:38:41 +0000 (12:38 -0800)
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>
12 files changed:
net/bridge/br_netlink.c
net/core/fib_rules.c
net/core/neighbour.c
net/core/rtnetlink.c
net/decnet/dn_dev.c
net/decnet/dn_table.c
net/ipv4/devinet.c
net/ipv4/fib_semantics.c
net/ipv4/inet_diag.c
net/ipv4/route.c
net/ipv6/addrconf.c
net/ipv6/route.c

index a9139682c49bf1aa9697fdbf1c4e5d2ebe29222a..7d68b24b5654565885922849c69bbe3758ea9515 100644 (file)
@@ -45,7 +45,7 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        hdr = nlmsg_data(nlh);
        hdr->ifi_family = AF_BRIDGE;
@@ -72,7 +72,8 @@ static int br_fill_ifinfo(struct sk_buff *skb, const struct net_bridge_port *por
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 /*
@@ -89,9 +90,12 @@ void br_ifinfo_notify(int event, struct net_bridge_port *port)
                goto errout;
 
        err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
-       /* failure implies BUG in br_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in br_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
index 1df6cd4568d373e150984998691fadf9341eb629..215f1bff048feeb8991ebd3a49bc406d15053f77 100644 (file)
@@ -331,7 +331,7 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
        if (nlh == NULL)
-               return -1;
+               return -EMSGSIZE;
 
        frh = nlmsg_data(nlh);
        frh->table = rule->table;
@@ -359,7 +359,8 @@ static int fib_nl_fill_rule(struct sk_buff *skb, struct fib_rule *rule,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
@@ -405,9 +406,12 @@ static void notify_rule_change(int event, struct fib_rule *rule,
                goto errout;
 
        err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
-       /* failure implies BUG in fib_rule_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in fib_rule_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
index e7300b6b40795e5011fa26ad87f0ed2766823fe7..9e26f38ea6e58fd26e2af3e78be1914050e26341 100644 (file)
@@ -1637,7 +1637,7 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        ndtmsg = nlmsg_data(nlh);
 
@@ -1706,7 +1706,8 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl,
 
 nla_put_failure:
        read_unlock_bh(&tbl->lock);
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 static int neightbl_fill_param_info(struct sk_buff *skb,
@@ -1720,7 +1721,7 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        ndtmsg = nlmsg_data(nlh);
 
@@ -1737,7 +1738,8 @@ static int neightbl_fill_param_info(struct sk_buff *skb,
        return nlmsg_end(skb, nlh);
 errout:
        read_unlock_bh(&tbl->lock);
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
  
 static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
@@ -1955,7 +1957,7 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        ndm = nlmsg_data(nlh);
        ndm->ndm_family  = neigh->ops->family;
@@ -1987,7 +1989,8 @@ static int neigh_fill_info(struct sk_buff *skb, struct neighbour *neigh,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 
@@ -2429,9 +2432,12 @@ static void __neigh_notify(struct neighbour *n, int type, int flags)
                goto errout;
 
        err = neigh_fill_info(skb, n, 0, 0, type, flags);
-       /* failure implies BUG in neigh_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in neigh_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
index e76539a5eb5e09e79939fef2e4d96bd9449c1a7b..9bf9ae05f1571ed5a474b06749cbdb8b743a4d4d 100644 (file)
@@ -320,7 +320,7 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        ifm = nlmsg_data(nlh);
        ifm->ifi_family = AF_UNSPEC;
@@ -384,7 +384,8 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
@@ -633,9 +634,12 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
 
        err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
                               NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
-       /* failure impilies BUG in if_nlmsg_size or wireless_rtnetlink_get */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in if_nlmsg_size */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(nskb);
+               goto errout;
+       }
        err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
 errout:
        kfree(iw_buf);
@@ -678,9 +682,12 @@ void rtmsg_ifinfo(int type, struct net_device *dev, unsigned change)
                goto errout;
 
        err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
-       /* failure implies BUG in if_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in if_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
 errout:
        if (err < 0)
index ed083ab455b75f600ec5da51716ace4db8a04905..90b3dfd72b497d9a94500158b2eb21c570844bd5 100644 (file)
@@ -749,7 +749,7 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        ifm = nlmsg_data(nlh);
        ifm->ifa_family = AF_DECnet;
@@ -768,7 +768,8 @@ static int dn_nl_fill_ifaddr(struct sk_buff *skb, struct dn_ifaddr *ifa,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
@@ -781,9 +782,12 @@ static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
                goto errout;
 
        err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
-       /* failure implies BUG in dn_ifaddr_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in dn_ifaddr_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
 errout:
        if (err < 0)
index 13b2421991bac8618b5fb27f139a9a2a42bdb4f3..c1f0cc1b1c60af482f1fbb302e09ac63d26c414c 100644 (file)
@@ -350,7 +350,7 @@ static int dn_fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 nlmsg_failure:
 rtattr_failure:
         skb_trim(skb, b - skb->data);
-        return -1;
+        return -EMSGSIZE;
 }
 
 
@@ -368,9 +368,12 @@ static void dn_rtmsg_fib(int event, struct dn_fib_node *f, int z, u32 tb_id,
         err = dn_fib_dump_info(skb, pid, nlh->nlmsg_seq, event, tb_id,
                               f->fn_type, f->fn_scope, &f->fn_key, z,
                               DN_FIB_INFO(f), 0);
-       /* failure implies BUG in dn_fib_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in dn_fib_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
index 480ace9819f6d97ea0245b742445481f7fcb14e5..c40203640966f6a95b17281ba14a38d547ba2864 100644 (file)
@@ -1140,7 +1140,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        ifm = nlmsg_data(nlh);
        ifm->ifa_family = AF_INET;
@@ -1167,7 +1167,8 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
@@ -1225,9 +1226,12 @@ static void rtmsg_ifa(int event, struct in_ifaddr* ifa, struct nlmsghdr *nlh,
                goto errout;
 
        err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
-       /* failure implies BUG in inet_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
 errout:
        if (err < 0)
index e63b8a98fb4df624b91f0bb44bf06e864570d7f5..be1028c9933e66f2e89c871eff7e7cf9009fdf27 100644 (file)
@@ -314,9 +314,12 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
        err = fib_dump_info(skb, info->pid, seq, event, tb_id,
                            fa->fa_type, fa->fa_scope, key, dst_len,
                            fa->fa_tos, fa->fa_info, 0);
-       /* failure implies BUG in fib_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in fib_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
                          info->nlh, GFP_KERNEL);
 errout:
@@ -960,7 +963,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        rtm = nlmsg_data(nlh);
        rtm->rtm_family = AF_INET;
@@ -1031,7 +1034,8 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 /*
index 77761ac4f7bb0589bc22d89127e3d64abb14c65a..9cd53addb78459db61857b65114fc4047ab08222 100644 (file)
@@ -153,7 +153,7 @@ static int inet_csk_diag_fill(struct sock *sk,
 rtattr_failure:
 nlmsg_failure:
        skb_trim(skb, b - skb->data);
-       return -1;
+       return -EMSGSIZE;
 }
 
 static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
@@ -209,7 +209,7 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
        return skb->len;
 nlmsg_failure:
        skb_trim(skb, previous_tail - skb->data);
-       return -1;
+       return -EMSGSIZE;
 }
 
 static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
@@ -274,11 +274,14 @@ static int inet_diag_get_exact(struct sk_buff *in_skb,
        if (!rep)
                goto out;
 
-       if (sk_diag_fill(sk, rep, req->idiag_ext,
-                        NETLINK_CB(in_skb).pid,
-                        nlh->nlmsg_seq, 0, nlh) <= 0)
-               BUG();
-
+       err = sk_diag_fill(sk, rep, req->idiag_ext,
+                          NETLINK_CB(in_skb).pid,
+                          nlh->nlmsg_seq, 0, nlh);
+       if (err < 0) {
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(rep);
+               goto out;
+       }
        err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
                              MSG_DONTWAIT);
        if (err > 0)
index 2daa0dc19d339e5dd3659ca63a9118279d4cc039..baee304a3cb76127affa65fca0a4898c7028de1f 100644 (file)
@@ -2635,7 +2635,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        r = nlmsg_data(nlh);
        r->rtm_family    = AF_INET;
@@ -2718,7 +2718,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
index e3854696988d76ec4bd16b2e4b6e35067de28d02..fe5e1d833871b19f142998b37b7fd522a7db5a86 100644 (file)
@@ -3117,7 +3117,7 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
                      ifa->idev->dev->ifindex);
@@ -3137,8 +3137,10 @@ static int inet6_fill_ifaddr(struct sk_buff *skb, struct inet6_ifaddr *ifa,
        }
 
        if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
-           put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0)
-               return nlmsg_cancel(skb, nlh);
+           put_cacheinfo(skb, ifa->cstamp, ifa->tstamp, preferred, valid) < 0) {
+               nlmsg_cancel(skb, nlh);
+               return -EMSGSIZE;
+       }
 
        return nlmsg_end(skb, nlh);
 }
@@ -3155,13 +3157,15 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb, struct ifmcaddr6 *ifmca,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
        if (nla_put(skb, IFA_MULTICAST, 16, &ifmca->mca_addr) < 0 ||
            put_cacheinfo(skb, ifmca->mca_cstamp, ifmca->mca_tstamp,
-                         INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
-               return nlmsg_cancel(skb, nlh);
+                         INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
+               nlmsg_cancel(skb, nlh);
+               return -EMSGSIZE;
+       }
 
        return nlmsg_end(skb, nlh);
 }
@@ -3178,13 +3182,15 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, struct ifacaddr6 *ifaca,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        put_ifaddrmsg(nlh, 128, IFA_F_PERMANENT, scope, ifindex);
        if (nla_put(skb, IFA_ANYCAST, 16, &ifaca->aca_addr) < 0 ||
            put_cacheinfo(skb, ifaca->aca_cstamp, ifaca->aca_tstamp,
-                         INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0)
-               return nlmsg_cancel(skb, nlh);
+                         INFINITY_LIFE_TIME, INFINITY_LIFE_TIME) < 0) {
+               nlmsg_cancel(skb, nlh);
+               return -EMSGSIZE;
+       }
 
        return nlmsg_end(skb, nlh);
 }
@@ -3334,9 +3340,12 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr* nlh,
 
        err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
                                nlh->nlmsg_seq, RTM_NEWADDR, 0);
-       /* failure implies BUG in inet6_ifaddr_msgsize() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout_ifa;
+       }
        err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
 errout_ifa:
        in6_ifa_put(ifa);
@@ -3354,9 +3363,12 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
                goto errout;
 
        err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
-       /* failure implies BUG in inet6_ifaddr_msgsize() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet6_ifaddr_msgsize() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
@@ -3426,7 +3438,7 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        hdr = nlmsg_data(nlh);
        hdr->ifi_family = AF_INET6;
@@ -3469,7 +3481,8 @@ static int inet6_fill_ifinfo(struct sk_buff *skb, struct inet6_dev *idev,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 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)
                goto errout;
 
        err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
-       /* failure implies BUG in inet6_if_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet6_if_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
@@ -3533,7 +3549,7 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
 
        nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        pmsg = nlmsg_data(nlh);
        pmsg->prefix_family = AF_INET6;
@@ -3558,7 +3574,8 @@ static int inet6_fill_prefix(struct sk_buff *skb, struct inet6_dev *idev,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 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,
                goto errout;
 
        err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
-       /* failure implies BUG in inet6_prefix_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in inet6_prefix_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
 errout:
        if (err < 0)
index 5f0043c30b70477c423a629a591899543e084415..f4fda80a41a2f759daf2f404d3bb5fc72450cffb 100644 (file)
@@ -2040,7 +2040,7 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
 
        nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
        if (nlh == NULL)
-               return -ENOBUFS;
+               return -EMSGSIZE;
 
        rtm = nlmsg_data(nlh);
        rtm->rtm_family = AF_INET6;
@@ -2111,7 +2111,8 @@ static int rt6_fill_node(struct sk_buff *skb, struct rt6_info *rt,
        return nlmsg_end(skb, nlh);
 
 nla_put_failure:
-       return nlmsg_cancel(skb, nlh);
+       nlmsg_cancel(skb, nlh);
+       return -EMSGSIZE;
 }
 
 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)
                goto errout;
 
        err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
-       /* failure implies BUG in rt6_nlmsg_size() */
-       BUG_ON(err < 0);
-
+       if (err < 0) {
+               /* -EMSGSIZE implies BUG in rt6_nlmsg_size() */
+               WARN_ON(err == -EMSGSIZE);
+               kfree_skb(skb);
+               goto errout;
+       }
        err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
 errout:
        if (err < 0)