diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-01 12:37:04 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-10-01 12:37:04 -0400 |
| commit | ae1cfb1174c87b43b0639e35e782b7b2c95fb4ff (patch) | |
| tree | 656145b6eaaa0b21848fa3a97a2de665f4a5ec7c | |
| parent | de59985e3a623d4d5d6207f1777398ca0606ab1c (diff) | |
| parent | 0523820482dcb42784572ffd2296c2f08c275a2b (diff) | |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6:
af_key: Free dumping state on socket close
XFRM,IPv6: initialize ip6_dst_blackhole_ops.kmem_cachep
ipv6: NULL pointer dereferrence in tcp_v6_send_ack
tcp: Fix NULL dereference in tcp_4_send_ack()
sctp: Fix kernel panic while process protocol violation parameter
iucv: Fix mismerge again.
ipsec: Fix pskb_expand_head corruption in xfrm_state_check_space
| -rw-r--r-- | include/net/sctp/sm.h | 3 | ||||
| -rw-r--r-- | net/ipv4/tcp_ipv4.c | 2 | ||||
| -rw-r--r-- | net/ipv6/route.c | 2 | ||||
| -rw-r--r-- | net/ipv6/tcp_ipv6.c | 2 | ||||
| -rw-r--r-- | net/iucv/iucv.c | 3 | ||||
| -rw-r--r-- | net/key/af_key.c | 30 | ||||
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 37 | ||||
| -rw-r--r-- | net/sctp/sm_statefuns.c | 48 | ||||
| -rw-r--r-- | net/xfrm/xfrm_output.c | 12 |
9 files changed, 97 insertions, 42 deletions
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 24811732bdb2..029a54a02396 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h | |||
| @@ -227,6 +227,9 @@ struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *, | |||
| 227 | const struct sctp_chunk *, | 227 | const struct sctp_chunk *, |
| 228 | const __u8 *, | 228 | const __u8 *, |
| 229 | const size_t ); | 229 | const size_t ); |
| 230 | struct sctp_chunk *sctp_make_violation_paramlen(const struct sctp_association *, | ||
| 231 | const struct sctp_chunk *, | ||
| 232 | struct sctp_paramhdr *); | ||
| 230 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *, | 233 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *, |
| 231 | const struct sctp_transport *, | 234 | const struct sctp_transport *, |
| 232 | const void *payload, | 235 | const void *payload, |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1b4fee20fc93..011478e46c40 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -618,7 +618,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
| 618 | ]; | 618 | ]; |
| 619 | } rep; | 619 | } rep; |
| 620 | struct ip_reply_arg arg; | 620 | struct ip_reply_arg arg; |
| 621 | struct net *net = dev_net(skb->dev); | 621 | struct net *net = dev_net(skb->dst->dev); |
| 622 | 622 | ||
| 623 | memset(&rep.th, 0, sizeof(struct tcphdr)); | 623 | memset(&rep.th, 0, sizeof(struct tcphdr)); |
| 624 | memset(&arg, 0, sizeof(arg)); | 624 | memset(&arg, 0, sizeof(arg)); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 9af6115f0f50..63442a1e741c 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -2688,6 +2688,8 @@ int __init ip6_route_init(void) | |||
| 2688 | if (ret) | 2688 | if (ret) |
| 2689 | goto out_kmem_cache; | 2689 | goto out_kmem_cache; |
| 2690 | 2690 | ||
| 2691 | ip6_dst_blackhole_ops.kmem_cachep = ip6_dst_ops_template.kmem_cachep; | ||
| 2692 | |||
| 2691 | /* Registering of the loopback is done before this portion of code, | 2693 | /* Registering of the loopback is done before this portion of code, |
| 2692 | * the loopback reference in rt6_info will not be taken, do it | 2694 | * the loopback reference in rt6_info will not be taken, do it |
| 2693 | * manually for init_net */ | 2695 | * manually for init_net */ |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index b585c850a89a..10e22fd48222 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -1050,7 +1050,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
| 1050 | struct tcphdr *th = tcp_hdr(skb), *t1; | 1050 | struct tcphdr *th = tcp_hdr(skb), *t1; |
| 1051 | struct sk_buff *buff; | 1051 | struct sk_buff *buff; |
| 1052 | struct flowi fl; | 1052 | struct flowi fl; |
| 1053 | struct net *net = dev_net(skb->dev); | 1053 | struct net *net = dev_net(skb->dst->dev); |
| 1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; | 1054 | struct sock *ctl_sk = net->ipv6.tcp_sk; |
| 1055 | unsigned int tot_len = sizeof(struct tcphdr); | 1055 | unsigned int tot_len = sizeof(struct tcphdr); |
| 1056 | __be32 *topt; | 1056 | __be32 *topt; |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 705959b31e24..d7b54b5bfa69 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
| @@ -524,7 +524,6 @@ static int iucv_enable(void) | |||
| 524 | get_online_cpus(); | 524 | get_online_cpus(); |
| 525 | for_each_online_cpu(cpu) | 525 | for_each_online_cpu(cpu) |
| 526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); | 526 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); |
| 527 | preempt_enable(); | ||
| 528 | if (cpus_empty(iucv_buffer_cpumask)) | 527 | if (cpus_empty(iucv_buffer_cpumask)) |
| 529 | /* No cpu could declare an iucv buffer. */ | 528 | /* No cpu could declare an iucv buffer. */ |
| 530 | goto out_path; | 529 | goto out_path; |
| @@ -547,7 +546,9 @@ out: | |||
| 547 | */ | 546 | */ |
| 548 | static void iucv_disable(void) | 547 | static void iucv_disable(void) |
| 549 | { | 548 | { |
| 549 | get_online_cpus(); | ||
| 550 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); | 550 | on_each_cpu(iucv_retrieve_cpu, NULL, 1); |
| 551 | put_online_cpus(); | ||
| 551 | kfree(iucv_path_table); | 552 | kfree(iucv_path_table); |
| 552 | } | 553 | } |
| 553 | 554 | ||
diff --git a/net/key/af_key.c b/net/key/af_key.c index d628df97e02e..b7f5a1c353ee 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -73,22 +73,18 @@ static int pfkey_can_dump(struct sock *sk) | |||
| 73 | return 0; | 73 | return 0; |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static int pfkey_do_dump(struct pfkey_sock *pfk) | 76 | static void pfkey_terminate_dump(struct pfkey_sock *pfk) |
| 77 | { | 77 | { |
| 78 | int rc; | 78 | if (pfk->dump.dump) { |
| 79 | 79 | pfk->dump.done(pfk); | |
| 80 | rc = pfk->dump.dump(pfk); | 80 | pfk->dump.dump = NULL; |
| 81 | if (rc == -ENOBUFS) | 81 | pfk->dump.done = NULL; |
| 82 | return 0; | 82 | } |
| 83 | |||
| 84 | pfk->dump.done(pfk); | ||
| 85 | pfk->dump.dump = NULL; | ||
| 86 | pfk->dump.done = NULL; | ||
| 87 | return rc; | ||
| 88 | } | 83 | } |
| 89 | 84 | ||
| 90 | static void pfkey_sock_destruct(struct sock *sk) | 85 | static void pfkey_sock_destruct(struct sock *sk) |
| 91 | { | 86 | { |
| 87 | pfkey_terminate_dump(pfkey_sk(sk)); | ||
| 92 | skb_queue_purge(&sk->sk_receive_queue); | 88 | skb_queue_purge(&sk->sk_receive_queue); |
| 93 | 89 | ||
| 94 | if (!sock_flag(sk, SOCK_DEAD)) { | 90 | if (!sock_flag(sk, SOCK_DEAD)) { |
| @@ -310,6 +306,18 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, | |||
| 310 | return err; | 306 | return err; |
| 311 | } | 307 | } |
| 312 | 308 | ||
| 309 | static int pfkey_do_dump(struct pfkey_sock *pfk) | ||
| 310 | { | ||
| 311 | int rc; | ||
| 312 | |||
| 313 | rc = pfk->dump.dump(pfk); | ||
| 314 | if (rc == -ENOBUFS) | ||
| 315 | return 0; | ||
| 316 | |||
| 317 | pfkey_terminate_dump(pfk); | ||
| 318 | return rc; | ||
| 319 | } | ||
| 320 | |||
| 313 | static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) | 321 | static inline void pfkey_hdr_dup(struct sadb_msg *new, struct sadb_msg *orig) |
| 314 | { | 322 | { |
| 315 | *new = *orig; | 323 | *new = *orig; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b599cbba4fbe..d68869f966c3 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -1012,6 +1012,29 @@ end: | |||
| 1012 | return retval; | 1012 | return retval; |
| 1013 | } | 1013 | } |
| 1014 | 1014 | ||
| 1015 | struct sctp_chunk *sctp_make_violation_paramlen( | ||
| 1016 | const struct sctp_association *asoc, | ||
| 1017 | const struct sctp_chunk *chunk, | ||
| 1018 | struct sctp_paramhdr *param) | ||
| 1019 | { | ||
| 1020 | struct sctp_chunk *retval; | ||
| 1021 | static const char error[] = "The following parameter had invalid length:"; | ||
| 1022 | size_t payload_len = sizeof(error) + sizeof(sctp_errhdr_t) + | ||
| 1023 | sizeof(sctp_paramhdr_t); | ||
| 1024 | |||
| 1025 | retval = sctp_make_abort(asoc, chunk, payload_len); | ||
| 1026 | if (!retval) | ||
| 1027 | goto nodata; | ||
| 1028 | |||
| 1029 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, | ||
| 1030 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
| 1031 | sctp_addto_chunk(retval, sizeof(error), error); | ||
| 1032 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), param); | ||
| 1033 | |||
| 1034 | nodata: | ||
| 1035 | return retval; | ||
| 1036 | } | ||
| 1037 | |||
| 1015 | /* Make a HEARTBEAT chunk. */ | 1038 | /* Make a HEARTBEAT chunk. */ |
| 1016 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1039 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
| 1017 | const struct sctp_transport *transport, | 1040 | const struct sctp_transport *transport, |
| @@ -1782,11 +1805,6 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
| 1782 | const struct sctp_chunk *chunk, | 1805 | const struct sctp_chunk *chunk, |
| 1783 | struct sctp_chunk **errp) | 1806 | struct sctp_chunk **errp) |
| 1784 | { | 1807 | { |
| 1785 | static const char error[] = "The following parameter had invalid length:"; | ||
| 1786 | size_t payload_len = WORD_ROUND(sizeof(error)) + | ||
| 1787 | sizeof(sctp_paramhdr_t); | ||
| 1788 | |||
| 1789 | |||
| 1790 | /* This is a fatal error. Any accumulated non-fatal errors are | 1808 | /* This is a fatal error. Any accumulated non-fatal errors are |
| 1791 | * not reported. | 1809 | * not reported. |
| 1792 | */ | 1810 | */ |
| @@ -1794,14 +1812,7 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
| 1794 | sctp_chunk_free(*errp); | 1812 | sctp_chunk_free(*errp); |
| 1795 | 1813 | ||
| 1796 | /* Create an error chunk and fill it in with our payload. */ | 1814 | /* Create an error chunk and fill it in with our payload. */ |
| 1797 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1815 | *errp = sctp_make_violation_paramlen(asoc, chunk, param); |
| 1798 | |||
| 1799 | if (*errp) { | ||
| 1800 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, | ||
| 1801 | sizeof(error) + sizeof(sctp_paramhdr_t)); | ||
| 1802 | sctp_addto_chunk(*errp, sizeof(error), error); | ||
| 1803 | sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); | ||
| 1804 | } | ||
| 1805 | 1816 | ||
| 1806 | return 0; | 1817 | return 0; |
| 1807 | } | 1818 | } |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 8848d329aa2c..7c622af2ce55 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -119,7 +119,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
| 119 | const struct sctp_endpoint *ep, | 119 | const struct sctp_endpoint *ep, |
| 120 | const struct sctp_association *asoc, | 120 | const struct sctp_association *asoc, |
| 121 | const sctp_subtype_t type, | 121 | const sctp_subtype_t type, |
| 122 | void *arg, | 122 | void *arg, void *ext, |
| 123 | sctp_cmd_seq_t *commands); | 123 | sctp_cmd_seq_t *commands); |
| 124 | 124 | ||
| 125 | static sctp_disposition_t sctp_sf_violation_ctsn( | 125 | static sctp_disposition_t sctp_sf_violation_ctsn( |
| @@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
| 3425 | addr_param = (union sctp_addr_param *)hdr->params; | 3425 | addr_param = (union sctp_addr_param *)hdr->params; |
| 3426 | length = ntohs(addr_param->p.length); | 3426 | length = ntohs(addr_param->p.length); |
| 3427 | if (length < sizeof(sctp_paramhdr_t)) | 3427 | if (length < sizeof(sctp_paramhdr_t)) |
| 3428 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3428 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
| 3429 | (void *)addr_param, commands); | 3429 | (void *)addr_param, commands); |
| 3430 | 3430 | ||
| 3431 | /* Verify the ASCONF chunk before processing it. */ | 3431 | /* Verify the ASCONF chunk before processing it. */ |
| @@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
| 3433 | (sctp_paramhdr_t *)((void *)addr_param + length), | 3433 | (sctp_paramhdr_t *)((void *)addr_param + length), |
| 3434 | (void *)chunk->chunk_end, | 3434 | (void *)chunk->chunk_end, |
| 3435 | &err_param)) | 3435 | &err_param)) |
| 3436 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3436 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
| 3437 | (void *)&err_param, commands); | 3437 | (void *)err_param, commands); |
| 3438 | 3438 | ||
| 3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value | 3439 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value |
| 3440 | * the endpoint stored in a new association variable | 3440 | * the endpoint stored in a new association variable |
| @@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
| 3542 | (sctp_paramhdr_t *)addip_hdr->params, | 3542 | (sctp_paramhdr_t *)addip_hdr->params, |
| 3543 | (void *)asconf_ack->chunk_end, | 3543 | (void *)asconf_ack->chunk_end, |
| 3544 | &err_param)) | 3544 | &err_param)) |
| 3545 | return sctp_sf_violation_paramlen(ep, asoc, type, | 3545 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, |
| 3546 | (void *)&err_param, commands); | 3546 | (void *)err_param, commands); |
| 3547 | 3547 | ||
| 3548 | if (last_asconf) { | 3548 | if (last_asconf) { |
| 3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; | 3549 | addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr; |
| @@ -4240,12 +4240,38 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
| 4240 | const struct sctp_endpoint *ep, | 4240 | const struct sctp_endpoint *ep, |
| 4241 | const struct sctp_association *asoc, | 4241 | const struct sctp_association *asoc, |
| 4242 | const sctp_subtype_t type, | 4242 | const sctp_subtype_t type, |
| 4243 | void *arg, | 4243 | void *arg, void *ext, |
| 4244 | sctp_cmd_seq_t *commands) { | 4244 | sctp_cmd_seq_t *commands) |
| 4245 | static const char err_str[] = "The following parameter had invalid length:"; | 4245 | { |
| 4246 | struct sctp_chunk *chunk = arg; | ||
| 4247 | struct sctp_paramhdr *param = ext; | ||
| 4248 | struct sctp_chunk *abort = NULL; | ||
| 4246 | 4249 | ||
| 4247 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4250 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
| 4248 | sizeof(err_str)); | 4251 | goto discard; |
| 4252 | |||
| 4253 | /* Make the abort chunk. */ | ||
| 4254 | abort = sctp_make_violation_paramlen(asoc, chunk, param); | ||
| 4255 | if (!abort) | ||
| 4256 | goto nomem; | ||
| 4257 | |||
| 4258 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | ||
| 4259 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | ||
| 4260 | |||
| 4261 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | ||
| 4262 | SCTP_ERROR(ECONNABORTED)); | ||
| 4263 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | ||
| 4264 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | ||
| 4265 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | ||
| 4266 | |||
| 4267 | discard: | ||
| 4268 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | ||
| 4269 | |||
| 4270 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | ||
| 4271 | |||
| 4272 | return SCTP_DISPOSITION_ABORT; | ||
| 4273 | nomem: | ||
| 4274 | return SCTP_DISPOSITION_NOMEM; | ||
| 4249 | } | 4275 | } |
| 4250 | 4276 | ||
| 4251 | /* Handle a protocol violation when the peer trying to advance the | 4277 | /* Handle a protocol violation when the peer trying to advance the |
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index ac25b4c0e982..dc50f1e71f76 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c | |||
| @@ -27,10 +27,14 @@ static int xfrm_state_check_space(struct xfrm_state *x, struct sk_buff *skb) | |||
| 27 | - skb_headroom(skb); | 27 | - skb_headroom(skb); |
| 28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); | 28 | int ntail = dst->dev->needed_tailroom - skb_tailroom(skb); |
| 29 | 29 | ||
| 30 | if (nhead > 0 || ntail > 0) | 30 | if (nhead <= 0) { |
| 31 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | 31 | if (ntail <= 0) |
| 32 | 32 | return 0; | |
| 33 | return 0; | 33 | nhead = 0; |
| 34 | } else if (ntail < 0) | ||
| 35 | ntail = 0; | ||
| 36 | |||
| 37 | return pskb_expand_head(skb, nhead, ntail, GFP_ATOMIC); | ||
| 34 | } | 38 | } |
| 35 | 39 | ||
| 36 | static int xfrm_output_one(struct sk_buff *skb, int err) | 40 | static int xfrm_output_one(struct sk_buff *skb, int err) |
