diff options
Diffstat (limited to 'net/sctp/sm_make_chunk.c')
| -rw-r--r-- | net/sctp/sm_make_chunk.c | 91 |
1 files changed, 55 insertions, 36 deletions
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 2a8773691695..507dff72c585 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
| @@ -806,38 +806,26 @@ no_mem: | |||
| 806 | 806 | ||
| 807 | /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ | 807 | /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */ |
| 808 | struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, | 808 | struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, |
| 809 | const struct sctp_chunk *chunk, | 809 | const struct msghdr *msg, |
| 810 | const struct msghdr *msg) | 810 | size_t paylen) |
| 811 | { | 811 | { |
| 812 | struct sctp_chunk *retval; | 812 | struct sctp_chunk *retval; |
| 813 | void *payload = NULL, *payoff; | 813 | void *payload = NULL; |
| 814 | size_t paylen = 0; | 814 | int err; |
| 815 | struct iovec *iov = NULL; | ||
| 816 | int iovlen = 0; | ||
| 817 | |||
| 818 | if (msg) { | ||
| 819 | iov = msg->msg_iov; | ||
| 820 | iovlen = msg->msg_iovlen; | ||
| 821 | paylen = get_user_iov_size(iov, iovlen); | ||
| 822 | } | ||
| 823 | 815 | ||
| 824 | retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen); | 816 | retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen); |
| 825 | if (!retval) | 817 | if (!retval) |
| 826 | goto err_chunk; | 818 | goto err_chunk; |
| 827 | 819 | ||
| 828 | if (paylen) { | 820 | if (paylen) { |
| 829 | /* Put the msg_iov together into payload. */ | 821 | /* Put the msg_iov together into payload. */ |
| 830 | payload = kmalloc(paylen, GFP_ATOMIC); | 822 | payload = kmalloc(paylen, GFP_KERNEL); |
| 831 | if (!payload) | 823 | if (!payload) |
| 832 | goto err_payload; | 824 | goto err_payload; |
| 833 | payoff = payload; | ||
| 834 | 825 | ||
| 835 | for (; iovlen > 0; --iovlen) { | 826 | err = memcpy_fromiovec(payload, msg->msg_iov, paylen); |
| 836 | if (copy_from_user(payoff, iov->iov_base,iov->iov_len)) | 827 | if (err < 0) |
| 837 | goto err_copy; | 828 | goto err_copy; |
| 838 | payoff += iov->iov_len; | ||
| 839 | iov++; | ||
| 840 | } | ||
| 841 | } | 829 | } |
| 842 | 830 | ||
| 843 | sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); | 831 | sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); |
| @@ -1294,10 +1282,8 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, | |||
| 1294 | 1282 | ||
| 1295 | retval = kmalloc(*cookie_len, GFP_ATOMIC); | 1283 | retval = kmalloc(*cookie_len, GFP_ATOMIC); |
| 1296 | 1284 | ||
| 1297 | if (!retval) { | 1285 | if (!retval) |
| 1298 | *cookie_len = 0; | ||
| 1299 | goto nodata; | 1286 | goto nodata; |
| 1300 | } | ||
| 1301 | 1287 | ||
| 1302 | /* Clear this memory since we are sending this data structure | 1288 | /* Clear this memory since we are sending this data structure |
| 1303 | * out on the network. | 1289 | * out on the network. |
| @@ -1333,19 +1319,29 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep, | |||
| 1333 | ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len); | 1319 | ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len); |
| 1334 | 1320 | ||
| 1335 | if (sctp_sk(ep->base.sk)->hmac) { | 1321 | if (sctp_sk(ep->base.sk)->hmac) { |
| 1322 | struct hash_desc desc; | ||
| 1323 | |||
| 1336 | /* Sign the message. */ | 1324 | /* Sign the message. */ |
| 1337 | sg.page = virt_to_page(&cookie->c); | 1325 | sg.page = virt_to_page(&cookie->c); |
| 1338 | sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; | 1326 | sg.offset = (unsigned long)(&cookie->c) % PAGE_SIZE; |
| 1339 | sg.length = bodysize; | 1327 | sg.length = bodysize; |
| 1340 | keylen = SCTP_SECRET_SIZE; | 1328 | keylen = SCTP_SECRET_SIZE; |
| 1341 | key = (char *)ep->secret_key[ep->current_key]; | 1329 | key = (char *)ep->secret_key[ep->current_key]; |
| 1330 | desc.tfm = sctp_sk(ep->base.sk)->hmac; | ||
| 1331 | desc.flags = 0; | ||
| 1342 | 1332 | ||
| 1343 | sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, | 1333 | if (crypto_hash_setkey(desc.tfm, key, keylen) || |
| 1344 | &sg, 1, cookie->signature); | 1334 | crypto_hash_digest(&desc, &sg, bodysize, cookie->signature)) |
| 1335 | goto free_cookie; | ||
| 1345 | } | 1336 | } |
| 1346 | 1337 | ||
| 1347 | nodata: | ||
| 1348 | return retval; | 1338 | return retval; |
| 1339 | |||
| 1340 | free_cookie: | ||
| 1341 | kfree(retval); | ||
| 1342 | nodata: | ||
| 1343 | *cookie_len = 0; | ||
| 1344 | return NULL; | ||
| 1349 | } | 1345 | } |
| 1350 | 1346 | ||
| 1351 | /* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */ | 1347 | /* Unpack the cookie from COOKIE ECHO chunk, recreating the association. */ |
| @@ -1366,6 +1362,7 @@ struct sctp_association *sctp_unpack_cookie( | |||
| 1366 | sctp_scope_t scope; | 1362 | sctp_scope_t scope; |
| 1367 | struct sk_buff *skb = chunk->skb; | 1363 | struct sk_buff *skb = chunk->skb; |
| 1368 | struct timeval tv; | 1364 | struct timeval tv; |
| 1365 | struct hash_desc desc; | ||
| 1369 | 1366 | ||
| 1370 | /* Header size is static data prior to the actual cookie, including | 1367 | /* Header size is static data prior to the actual cookie, including |
| 1371 | * any padding. | 1368 | * any padding. |
| @@ -1401,17 +1398,25 @@ struct sctp_association *sctp_unpack_cookie( | |||
| 1401 | sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; | 1398 | sg.offset = (unsigned long)(bear_cookie) % PAGE_SIZE; |
| 1402 | sg.length = bodysize; | 1399 | sg.length = bodysize; |
| 1403 | key = (char *)ep->secret_key[ep->current_key]; | 1400 | key = (char *)ep->secret_key[ep->current_key]; |
| 1401 | desc.tfm = sctp_sk(ep->base.sk)->hmac; | ||
| 1402 | desc.flags = 0; | ||
| 1404 | 1403 | ||
| 1405 | memset(digest, 0x00, SCTP_SIGNATURE_SIZE); | 1404 | memset(digest, 0x00, SCTP_SIGNATURE_SIZE); |
| 1406 | sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, &sg, | 1405 | if (crypto_hash_setkey(desc.tfm, key, keylen) || |
| 1407 | 1, digest); | 1406 | crypto_hash_digest(&desc, &sg, bodysize, digest)) { |
| 1407 | *error = -SCTP_IERROR_NOMEM; | ||
| 1408 | goto fail; | ||
| 1409 | } | ||
| 1408 | 1410 | ||
| 1409 | if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { | 1411 | if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { |
| 1410 | /* Try the previous key. */ | 1412 | /* Try the previous key. */ |
| 1411 | key = (char *)ep->secret_key[ep->last_key]; | 1413 | key = (char *)ep->secret_key[ep->last_key]; |
| 1412 | memset(digest, 0x00, SCTP_SIGNATURE_SIZE); | 1414 | memset(digest, 0x00, SCTP_SIGNATURE_SIZE); |
| 1413 | sctp_crypto_hmac(sctp_sk(ep->base.sk)->hmac, key, &keylen, | 1415 | if (crypto_hash_setkey(desc.tfm, key, keylen) || |
| 1414 | &sg, 1, digest); | 1416 | crypto_hash_digest(&desc, &sg, bodysize, digest)) { |
| 1417 | *error = -SCTP_IERROR_NOMEM; | ||
| 1418 | goto fail; | ||
| 1419 | } | ||
| 1415 | 1420 | ||
| 1416 | if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { | 1421 | if (memcmp(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) { |
| 1417 | /* Yikes! Still bad signature! */ | 1422 | /* Yikes! Still bad signature! */ |
| @@ -1442,8 +1447,16 @@ no_hmac: | |||
| 1442 | /* Check to see if the cookie is stale. If there is already | 1447 | /* Check to see if the cookie is stale. If there is already |
| 1443 | * an association, there is no need to check cookie's expiration | 1448 | * an association, there is no need to check cookie's expiration |
| 1444 | * for init collision case of lost COOKIE ACK. | 1449 | * for init collision case of lost COOKIE ACK. |
| 1450 | * If skb has been timestamped, then use the stamp, otherwise | ||
| 1451 | * use current time. This introduces a small possibility that | ||
| 1452 | * that a cookie may be considered expired, but his would only slow | ||
| 1453 | * down the new association establishment instead of every packet. | ||
| 1445 | */ | 1454 | */ |
| 1446 | skb_get_timestamp(skb, &tv); | 1455 | if (sock_flag(ep->base.sk, SOCK_TIMESTAMP)) |
| 1456 | skb_get_timestamp(skb, &tv); | ||
| 1457 | else | ||
| 1458 | do_gettimeofday(&tv); | ||
| 1459 | |||
| 1447 | if (!asoc && tv_lt(bear_cookie->expiration, tv)) { | 1460 | if (!asoc && tv_lt(bear_cookie->expiration, tv)) { |
| 1448 | __u16 len; | 1461 | __u16 len; |
| 1449 | /* | 1462 | /* |
| @@ -1493,7 +1506,7 @@ no_hmac: | |||
| 1493 | 1506 | ||
| 1494 | /* Also, add the destination address. */ | 1507 | /* Also, add the destination address. */ |
| 1495 | if (list_empty(&retval->base.bind_addr.address_list)) { | 1508 | if (list_empty(&retval->base.bind_addr.address_list)) { |
| 1496 | sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, | 1509 | sctp_add_bind_addr(&retval->base.bind_addr, &chunk->dest, 1, |
| 1497 | GFP_ATOMIC); | 1510 | GFP_ATOMIC); |
| 1498 | } | 1511 | } |
| 1499 | 1512 | ||
| @@ -2017,7 +2030,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
| 2017 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); | 2030 | af->from_addr_param(&addr, param.addr, asoc->peer.port, 0); |
| 2018 | scope = sctp_scope(peer_addr); | 2031 | scope = sctp_scope(peer_addr); |
| 2019 | if (sctp_in_scope(&addr, scope)) | 2032 | if (sctp_in_scope(&addr, scope)) |
| 2020 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_ACTIVE)) | 2033 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) |
| 2021 | return 0; | 2034 | return 0; |
| 2022 | break; | 2035 | break; |
| 2023 | 2036 | ||
| @@ -2418,7 +2431,7 @@ static __u16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
| 2418 | * Due to Resource Shortage'. | 2431 | * Due to Resource Shortage'. |
| 2419 | */ | 2432 | */ |
| 2420 | 2433 | ||
| 2421 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_ACTIVE); | 2434 | peer = sctp_assoc_add_peer(asoc, &addr, GFP_ATOMIC, SCTP_UNCONFIRMED); |
| 2422 | if (!peer) | 2435 | if (!peer) |
| 2423 | return SCTP_ERROR_RSRC_LOW; | 2436 | return SCTP_ERROR_RSRC_LOW; |
| 2424 | 2437 | ||
| @@ -2565,6 +2578,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
| 2565 | union sctp_addr_param *addr_param; | 2578 | union sctp_addr_param *addr_param; |
| 2566 | struct list_head *pos; | 2579 | struct list_head *pos; |
| 2567 | struct sctp_transport *transport; | 2580 | struct sctp_transport *transport; |
| 2581 | struct sctp_sockaddr_entry *saddr; | ||
| 2568 | int retval = 0; | 2582 | int retval = 0; |
| 2569 | 2583 | ||
| 2570 | addr_param = (union sctp_addr_param *) | 2584 | addr_param = (union sctp_addr_param *) |
| @@ -2578,7 +2592,11 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
| 2578 | case SCTP_PARAM_ADD_IP: | 2592 | case SCTP_PARAM_ADD_IP: |
| 2579 | sctp_local_bh_disable(); | 2593 | sctp_local_bh_disable(); |
| 2580 | sctp_write_lock(&asoc->base.addr_lock); | 2594 | sctp_write_lock(&asoc->base.addr_lock); |
| 2581 | retval = sctp_add_bind_addr(bp, &addr, GFP_ATOMIC); | 2595 | list_for_each(pos, &bp->address_list) { |
| 2596 | saddr = list_entry(pos, struct sctp_sockaddr_entry, list); | ||
| 2597 | if (sctp_cmp_addr_exact(&saddr->a, &addr)) | ||
| 2598 | saddr->use_as_src = 1; | ||
| 2599 | } | ||
| 2582 | sctp_write_unlock(&asoc->base.addr_lock); | 2600 | sctp_write_unlock(&asoc->base.addr_lock); |
| 2583 | sctp_local_bh_enable(); | 2601 | sctp_local_bh_enable(); |
| 2584 | break; | 2602 | break; |
| @@ -2591,6 +2609,7 @@ static int sctp_asconf_param_success(struct sctp_association *asoc, | |||
| 2591 | list_for_each(pos, &asoc->peer.transport_addr_list) { | 2609 | list_for_each(pos, &asoc->peer.transport_addr_list) { |
| 2592 | transport = list_entry(pos, struct sctp_transport, | 2610 | transport = list_entry(pos, struct sctp_transport, |
| 2593 | transports); | 2611 | transports); |
| 2612 | dst_release(transport->dst); | ||
| 2594 | sctp_transport_route(transport, NULL, | 2613 | sctp_transport_route(transport, NULL, |
| 2595 | sctp_sk(asoc->base.sk)); | 2614 | sctp_sk(asoc->base.sk)); |
| 2596 | } | 2615 | } |
