aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4
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/ipv4
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/ipv4')
-rw-r--r--net/ipv4/devinet.c14
-rw-r--r--net/ipv4/fib_semantics.c14
-rw-r--r--net/ipv4/inet_diag.c17
-rw-r--r--net/ipv4/route.c5
4 files changed, 31 insertions, 19 deletions
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index 480ace9819f6..c40203640966 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -1140,7 +1140,7 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1140 1140
1141 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags); 1141 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*ifm), flags);
1142 if (nlh == NULL) 1142 if (nlh == NULL)
1143 return -ENOBUFS; 1143 return -EMSGSIZE;
1144 1144
1145 ifm = nlmsg_data(nlh); 1145 ifm = nlmsg_data(nlh);
1146 ifm->ifa_family = AF_INET; 1146 ifm->ifa_family = AF_INET;
@@ -1167,7 +1167,8 @@ static int inet_fill_ifaddr(struct sk_buff *skb, struct in_ifaddr *ifa,
1167 return nlmsg_end(skb, nlh); 1167 return nlmsg_end(skb, nlh);
1168 1168
1169nla_put_failure: 1169nla_put_failure:
1170 return nlmsg_cancel(skb, nlh); 1170 nlmsg_cancel(skb, nlh);
1171 return -EMSGSIZE;
1171} 1172}
1172 1173
1173static int inet_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) 1174static 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,
1225 goto errout; 1226 goto errout;
1226 1227
1227 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0); 1228 err = inet_fill_ifaddr(skb, ifa, pid, seq, event, 0);
1228 /* failure implies BUG in inet_nlmsg_size() */ 1229 if (err < 0) {
1229 BUG_ON(err < 0); 1230 /* -EMSGSIZE implies BUG in inet_nlmsg_size() */
1230 1231 WARN_ON(err == -EMSGSIZE);
1232 kfree_skb(skb);
1233 goto errout;
1234 }
1231 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL); 1235 err = rtnl_notify(skb, pid, RTNLGRP_IPV4_IFADDR, nlh, GFP_KERNEL);
1232errout: 1236errout:
1233 if (err < 0) 1237 if (err < 0)
diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c
index e63b8a98fb4d..be1028c9933e 100644
--- a/net/ipv4/fib_semantics.c
+++ b/net/ipv4/fib_semantics.c
@@ -314,9 +314,12 @@ void rtmsg_fib(int event, __be32 key, struct fib_alias *fa,
314 err = fib_dump_info(skb, info->pid, seq, event, tb_id, 314 err = fib_dump_info(skb, info->pid, seq, event, tb_id,
315 fa->fa_type, fa->fa_scope, key, dst_len, 315 fa->fa_type, fa->fa_scope, key, dst_len,
316 fa->fa_tos, fa->fa_info, 0); 316 fa->fa_tos, fa->fa_info, 0);
317 /* failure implies BUG in fib_nlmsg_size() */ 317 if (err < 0) {
318 BUG_ON(err < 0); 318 /* -EMSGSIZE implies BUG in fib_nlmsg_size() */
319 319 WARN_ON(err == -EMSGSIZE);
320 kfree_skb(skb);
321 goto errout;
322 }
320 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE, 323 err = rtnl_notify(skb, info->pid, RTNLGRP_IPV4_ROUTE,
321 info->nlh, GFP_KERNEL); 324 info->nlh, GFP_KERNEL);
322errout: 325errout:
@@ -960,7 +963,7 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
960 963
961 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags); 964 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*rtm), flags);
962 if (nlh == NULL) 965 if (nlh == NULL)
963 return -ENOBUFS; 966 return -EMSGSIZE;
964 967
965 rtm = nlmsg_data(nlh); 968 rtm = nlmsg_data(nlh);
966 rtm->rtm_family = AF_INET; 969 rtm->rtm_family = AF_INET;
@@ -1031,7 +1034,8 @@ int fib_dump_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
1031 return nlmsg_end(skb, nlh); 1034 return nlmsg_end(skb, nlh);
1032 1035
1033nla_put_failure: 1036nla_put_failure:
1034 return nlmsg_cancel(skb, nlh); 1037 nlmsg_cancel(skb, nlh);
1038 return -EMSGSIZE;
1035} 1039}
1036 1040
1037/* 1041/*
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c
index 77761ac4f7bb..9cd53addb784 100644
--- a/net/ipv4/inet_diag.c
+++ b/net/ipv4/inet_diag.c
@@ -153,7 +153,7 @@ static int inet_csk_diag_fill(struct sock *sk,
153rtattr_failure: 153rtattr_failure:
154nlmsg_failure: 154nlmsg_failure:
155 skb_trim(skb, b - skb->data); 155 skb_trim(skb, b - skb->data);
156 return -1; 156 return -EMSGSIZE;
157} 157}
158 158
159static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, 159static 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,
209 return skb->len; 209 return skb->len;
210nlmsg_failure: 210nlmsg_failure:
211 skb_trim(skb, previous_tail - skb->data); 211 skb_trim(skb, previous_tail - skb->data);
212 return -1; 212 return -EMSGSIZE;
213} 213}
214 214
215static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, 215static 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,
274 if (!rep) 274 if (!rep)
275 goto out; 275 goto out;
276 276
277 if (sk_diag_fill(sk, rep, req->idiag_ext, 277 err = sk_diag_fill(sk, rep, req->idiag_ext,
278 NETLINK_CB(in_skb).pid, 278 NETLINK_CB(in_skb).pid,
279 nlh->nlmsg_seq, 0, nlh) <= 0) 279 nlh->nlmsg_seq, 0, nlh);
280 BUG(); 280 if (err < 0) {
281 281 WARN_ON(err == -EMSGSIZE);
282 kfree_skb(rep);
283 goto out;
284 }
282 err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid, 285 err = netlink_unicast(idiagnl, rep, NETLINK_CB(in_skb).pid,
283 MSG_DONTWAIT); 286 MSG_DONTWAIT);
284 if (err > 0) 287 if (err > 0)
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 2daa0dc19d33..baee304a3cb7 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -2635,7 +2635,7 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2635 2635
2636 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags); 2636 nlh = nlmsg_put(skb, pid, seq, event, sizeof(*r), flags);
2637 if (nlh == NULL) 2637 if (nlh == NULL)
2638 return -ENOBUFS; 2638 return -EMSGSIZE;
2639 2639
2640 r = nlmsg_data(nlh); 2640 r = nlmsg_data(nlh);
2641 r->rtm_family = AF_INET; 2641 r->rtm_family = AF_INET;
@@ -2718,7 +2718,8 @@ static int rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, int event,
2718 return nlmsg_end(skb, nlh); 2718 return nlmsg_end(skb, nlh);
2719 2719
2720nla_put_failure: 2720nla_put_failure:
2721 return nlmsg_cancel(skb, nlh); 2721 nlmsg_cancel(skb, nlh);
2722 return -EMSGSIZE;
2722} 2723}
2723 2724
2724int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg) 2725int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr* nlh, void *arg)