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:
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
if (nlh == NULL)
hdr = nlmsg_data(nlh);
hdr->ifi_family = AF_BRIDGE;
hdr = nlmsg_data(nlh);
hdr->ifi_family = AF_BRIDGE;
return nlmsg_end(skb, nlh);
nla_put_failure:
return nlmsg_end(skb, nlh);
nla_put_failure:
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
goto errout;
err = br_fill_ifinfo(skb, port, 0, 0, event, 0);
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)
err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_ATOMIC);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*frh), flags);
if (nlh == NULL)
frh = nlmsg_data(nlh);
frh->table = rule->table;
frh = nlmsg_data(nlh);
frh->table = rule->table;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
goto errout;
err = fib_nl_fill_rule(skb, rule, pid, nlh->nlmsg_seq, event, 0, ops);
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)
err = rtnl_notify(skb, pid, ops->nlgroup, nlh, GFP_KERNEL);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
if (nlh == NULL)
ndtmsg = nlmsg_data(nlh);
ndtmsg = nlmsg_data(nlh);
nla_put_failure:
read_unlock_bh(&tbl->lock);
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,
}
static int neightbl_fill_param_info(struct sk_buff *skb,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndtmsg), flags);
if (nlh == NULL)
ndtmsg = nlmsg_data(nlh);
ndtmsg = nlmsg_data(nlh);
return nlmsg_end(skb, nlh);
errout:
read_unlock_bh(&tbl->lock);
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,
}
static inline struct neigh_parms *lookup_neigh_params(struct neigh_table *tbl,
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags);
if (nlh == NULL)
ndm = nlmsg_data(nlh);
ndm->ndm_family = neigh->ops->family;
ndm = nlmsg_data(nlh);
ndm->ndm_family = neigh->ops->family;
return nlmsg_end(skb, nlh);
nla_put_failure:
return nlmsg_end(skb, nlh);
nla_put_failure:
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
goto errout;
err = neigh_fill_info(skb, n, 0, 0, type, 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)
err = rtnl_notify(skb, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ifm), flags);
if (nlh == NULL)
ifm = nlmsg_data(nlh);
ifm->ifi_family = AF_UNSPEC;
ifm = nlmsg_data(nlh);
ifm->ifi_family = AF_UNSPEC;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
err = rtnl_fill_ifinfo(nskb, dev, iw, iw_buf_len, RTM_NEWLINK,
NETLINK_CB(skb).pid, nlh->nlmsg_seq, 0, 0);
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);
err = rtnl_unicast(nskb, NETLINK_CB(skb).pid);
errout:
kfree(iw_buf);
goto errout;
err = rtnl_fill_ifinfo(skb, dev, NULL, 0, type, 0, 0, change, 0);
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)
err = rtnl_notify(skb, 0, RTNLGRP_LINK, NULL, GFP_KERNEL);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
if (nlh == NULL)
ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_DECnet;
ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_DECnet;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
static void dn_ifaddr_notify(int event, struct dn_ifaddr *ifa)
goto errout;
err = dn_nl_fill_ifaddr(skb, ifa, 0, 0, event, 0);
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)
err = rtnl_notify(skb, 0, RTNLGRP_DECnet_IFADDR, NULL, GFP_KERNEL);
errout:
if (err < 0)
nlmsg_failure:
rtattr_failure:
skb_trim(skb, b - skb->data);
nlmsg_failure:
rtattr_failure:
skb_trim(skb, b - skb->data);
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);
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)
err = rtnl_notify(skb, pid, RTNLGRP_DECnet_ROUTE, nlh, GFP_KERNEL);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
if (nlh == NULL)
ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_INET;
ifm = nlmsg_data(nlh);
ifm->ifa_family = AF_INET;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
goto errout;
err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
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)
err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
errout:
if (err < 0)
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);
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:
err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
info->nlh, GFP_KERNEL);
errout:
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
if (nlh == NULL)
rtm = nlmsg_data(nlh);
rtm->rtm_family = AF_INET;
rtm = nlmsg_data(nlh);
rtm->rtm_family = AF_INET;
return nlmsg_end(skb, nlh);
nla_put_failure:
return nlmsg_end(skb, nlh);
nla_put_failure:
- return nlmsg_cancel(skb, nlh);
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
rtattr_failure:
nlmsg_failure:
skb_trim(skb, b - skb->data);
rtattr_failure:
nlmsg_failure:
skb_trim(skb, b - skb->data);
}
static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
}
static int inet_twsk_diag_fill(struct inet_timewait_sock *tw,
return skb->len;
nlmsg_failure:
skb_trim(skb, previous_tail - skb->data);
return skb->len;
nlmsg_failure:
skb_trim(skb, previous_tail - skb->data);
}
static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
}
static int sk_diag_fill(struct sock *sk, struct sk_buff *skb,
- 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)
err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
MSG_DONTWAIT);
if (err > 0)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
if (nlh == NULL)
r = nlmsg_data(nlh);
r->rtm_family = AF_INET;
r = nlmsg_data(nlh);
r->rtm_family = AF_INET;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
if (nlh == NULL)
put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
ifa->idev->dev->ifindex);
put_ifaddrmsg(nlh, ifa->prefix_len, ifa->flags, rt_scope(ifa->scope),
ifa->idev->dev->ifindex);
}
if (nla_put(skb, IFA_ADDRESS, 16, &ifa->addr) < 0 ||
}
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);
}
return nlmsg_end(skb, nlh);
}
nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
if (nlh == NULL)
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,
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);
}
return nlmsg_end(skb, nlh);
}
nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(struct ifaddrmsg), flags);
if (nlh == NULL)
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,
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);
}
return nlmsg_end(skb, nlh);
}
err = inet6_fill_ifaddr(skb, ifa, NETLINK_CB(in_skb).pid,
nlh->nlmsg_seq, RTM_NEWADDR, 0);
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);
err = rtnl_unicast(skb, NETLINK_CB(in_skb).pid);
errout_ifa:
in6_ifa_put(ifa);
goto errout;
err = inet6_fill_ifaddr(skb, ifa, 0, 0, event, 0);
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)
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*hdr), flags);
if (nlh == NULL)
hdr = nlmsg_data(nlh);
hdr->ifi_family = AF_INET6;
hdr = nlmsg_data(nlh);
hdr->ifi_family = AF_INET6;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
static int inet6_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb)
goto errout;
err = inet6_fill_ifinfo(skb, idev, 0, 0, event, 0);
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)
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_IFADDR, NULL, GFP_ATOMIC);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, event, sizeof(*pmsg), flags);
if (nlh == NULL)
pmsg = nlmsg_data(nlh);
pmsg->prefix_family = AF_INET6;
pmsg = nlmsg_data(nlh);
pmsg->prefix_family = AF_INET6;
return nlmsg_end(skb, nlh);
nla_put_failure:
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,
}
static void inet6_prefix_notify(int event, struct inet6_dev *idev,
goto errout;
err = inet6_fill_prefix(skb, idev, pinfo, 0, 0, event, 0);
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)
err = rtnl_notify(skb, 0, RTNLGRP_IPV6_PREFIX, NULL, GFP_ATOMIC);
errout:
if (err < 0)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
if (nlh == NULL)
nlh = nlmsg_put(skb, pid, seq, type, sizeof(*rtm), flags);
if (nlh == NULL)
rtm = nlmsg_data(nlh);
rtm->rtm_family = AF_INET6;
rtm = nlmsg_data(nlh);
rtm->rtm_family = AF_INET6;
return nlmsg_end(skb, nlh);
nla_put_failure:
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)
}
int rt6_dump_route(struct rt6_info *rt, void *p_arg)
goto errout;
err = rt6_fill_node(skb, rt, NULL, NULL, 0, event, pid, seq, 0, 0);
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)
err = rtnl_notify(skb, pid, RTNLGRP_IPV6_ROUTE, nlh, gfp_any());
errout:
if (err < 0)