diff options
author | David S. Miller <davem@davemloft.net> | 2009-02-07 05:52:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-07 05:52:44 -0500 |
commit | 409f0a9014fe24d906ba21aaccff80eb7f7304da (patch) | |
tree | 8d9a6946d6cf1c5aab72651a193ff860651e5e65 /net/ipv6 | |
parent | 593721833d2a3987736467144ad062a709d3a72c (diff) | |
parent | 0b492fce3d72d982a7981905f85484a1e1ba7fde (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts:
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/ip6_flowlabel.c | 8 | ||||
-rw-r--r-- | net/ipv6/ip6_output.c | 67 |
2 files changed, 58 insertions, 17 deletions
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index c62dd247774f..7712578bdc66 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -323,17 +323,21 @@ static struct ip6_flowlabel * | |||
323 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, | 323 | fl_create(struct net *net, struct in6_flowlabel_req *freq, char __user *optval, |
324 | int optlen, int *err_p) | 324 | int optlen, int *err_p) |
325 | { | 325 | { |
326 | struct ip6_flowlabel *fl; | 326 | struct ip6_flowlabel *fl = NULL; |
327 | int olen; | 327 | int olen; |
328 | int addr_type; | 328 | int addr_type; |
329 | int err; | 329 | int err; |
330 | 330 | ||
331 | olen = optlen - CMSG_ALIGN(sizeof(*freq)); | ||
332 | err = -EINVAL; | ||
333 | if (olen > 64 * 1024) | ||
334 | goto done; | ||
335 | |||
331 | err = -ENOMEM; | 336 | err = -ENOMEM; |
332 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); | 337 | fl = kzalloc(sizeof(*fl), GFP_KERNEL); |
333 | if (fl == NULL) | 338 | if (fl == NULL) |
334 | goto done; | 339 | goto done; |
335 | 340 | ||
336 | olen = optlen - CMSG_ALIGN(sizeof(*freq)); | ||
337 | if (olen > 0) { | 341 | if (olen > 0) { |
338 | struct msghdr msg; | 342 | struct msghdr msg; |
339 | struct flowi flowi; | 343 | struct flowi flowi; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 4b15938bef4d..9fb49c3b518a 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -1105,6 +1105,18 @@ static inline int ip6_ufo_append_data(struct sock *sk, | |||
1105 | return err; | 1105 | return err; |
1106 | } | 1106 | } |
1107 | 1107 | ||
1108 | static inline struct ipv6_opt_hdr *ip6_opt_dup(struct ipv6_opt_hdr *src, | ||
1109 | gfp_t gfp) | ||
1110 | { | ||
1111 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | ||
1112 | } | ||
1113 | |||
1114 | static inline struct ipv6_rt_hdr *ip6_rthdr_dup(struct ipv6_rt_hdr *src, | ||
1115 | gfp_t gfp) | ||
1116 | { | ||
1117 | return src ? kmemdup(src, (src->hdrlen + 1) * 8, gfp) : NULL; | ||
1118 | } | ||
1119 | |||
1108 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | 1120 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
1109 | int offset, int len, int odd, struct sk_buff *skb), | 1121 | int offset, int len, int odd, struct sk_buff *skb), |
1110 | void *from, int length, int transhdrlen, | 1122 | void *from, int length, int transhdrlen, |
@@ -1130,17 +1142,37 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1130 | * setup for corking | 1142 | * setup for corking |
1131 | */ | 1143 | */ |
1132 | if (opt) { | 1144 | if (opt) { |
1133 | if (np->cork.opt == NULL) { | 1145 | if (WARN_ON(np->cork.opt)) |
1134 | np->cork.opt = kmalloc(opt->tot_len, | ||
1135 | sk->sk_allocation); | ||
1136 | if (unlikely(np->cork.opt == NULL)) | ||
1137 | return -ENOBUFS; | ||
1138 | } else if (np->cork.opt->tot_len < opt->tot_len) { | ||
1139 | printk(KERN_DEBUG "ip6_append_data: invalid option length\n"); | ||
1140 | return -EINVAL; | 1146 | return -EINVAL; |
1141 | } | 1147 | |
1142 | memcpy(np->cork.opt, opt, opt->tot_len); | 1148 | np->cork.opt = kmalloc(opt->tot_len, sk->sk_allocation); |
1143 | inet->cork.flags |= IPCORK_OPT; | 1149 | if (unlikely(np->cork.opt == NULL)) |
1150 | return -ENOBUFS; | ||
1151 | |||
1152 | np->cork.opt->tot_len = opt->tot_len; | ||
1153 | np->cork.opt->opt_flen = opt->opt_flen; | ||
1154 | np->cork.opt->opt_nflen = opt->opt_nflen; | ||
1155 | |||
1156 | np->cork.opt->dst0opt = ip6_opt_dup(opt->dst0opt, | ||
1157 | sk->sk_allocation); | ||
1158 | if (opt->dst0opt && !np->cork.opt->dst0opt) | ||
1159 | return -ENOBUFS; | ||
1160 | |||
1161 | np->cork.opt->dst1opt = ip6_opt_dup(opt->dst1opt, | ||
1162 | sk->sk_allocation); | ||
1163 | if (opt->dst1opt && !np->cork.opt->dst1opt) | ||
1164 | return -ENOBUFS; | ||
1165 | |||
1166 | np->cork.opt->hopopt = ip6_opt_dup(opt->hopopt, | ||
1167 | sk->sk_allocation); | ||
1168 | if (opt->hopopt && !np->cork.opt->hopopt) | ||
1169 | return -ENOBUFS; | ||
1170 | |||
1171 | np->cork.opt->srcrt = ip6_rthdr_dup(opt->srcrt, | ||
1172 | sk->sk_allocation); | ||
1173 | if (opt->srcrt && !np->cork.opt->srcrt) | ||
1174 | return -ENOBUFS; | ||
1175 | |||
1144 | /* need source address above miyazawa*/ | 1176 | /* need source address above miyazawa*/ |
1145 | } | 1177 | } |
1146 | dst_hold(&rt->u.dst); | 1178 | dst_hold(&rt->u.dst); |
@@ -1167,8 +1199,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1167 | } else { | 1199 | } else { |
1168 | rt = (struct rt6_info *)inet->cork.dst; | 1200 | rt = (struct rt6_info *)inet->cork.dst; |
1169 | fl = &inet->cork.fl; | 1201 | fl = &inet->cork.fl; |
1170 | if (inet->cork.flags & IPCORK_OPT) | 1202 | opt = np->cork.opt; |
1171 | opt = np->cork.opt; | ||
1172 | transhdrlen = 0; | 1203 | transhdrlen = 0; |
1173 | exthdrlen = 0; | 1204 | exthdrlen = 0; |
1174 | mtu = inet->cork.fragsize; | 1205 | mtu = inet->cork.fragsize; |
@@ -1407,9 +1438,15 @@ error: | |||
1407 | 1438 | ||
1408 | static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) | 1439 | static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) |
1409 | { | 1440 | { |
1410 | inet->cork.flags &= ~IPCORK_OPT; | 1441 | if (np->cork.opt) { |
1411 | kfree(np->cork.opt); | 1442 | kfree(np->cork.opt->dst0opt); |
1412 | np->cork.opt = NULL; | 1443 | kfree(np->cork.opt->dst1opt); |
1444 | kfree(np->cork.opt->hopopt); | ||
1445 | kfree(np->cork.opt->srcrt); | ||
1446 | kfree(np->cork.opt); | ||
1447 | np->cork.opt = NULL; | ||
1448 | } | ||
1449 | |||
1413 | if (inet->cork.dst) { | 1450 | if (inet->cork.dst) { |
1414 | dst_release(inet->cork.dst); | 1451 | dst_release(inet->cork.dst); |
1415 | inet->cork.dst = NULL; | 1452 | inet->cork.dst = NULL; |