diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/auth.c | 8 | ||||
-rw-r--r-- | net/sctp/output.c | 1 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 46 | ||||
-rw-r--r-- | net/sctp/socket.c | 13 |
4 files changed, 41 insertions, 27 deletions
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index 86366390038a..ddbbf7c81fa1 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -543,16 +543,20 @@ struct sctp_hmac *sctp_auth_asoc_get_hmac(const struct sctp_association *asoc) | |||
543 | id = ntohs(hmacs->hmac_ids[i]); | 543 | id = ntohs(hmacs->hmac_ids[i]); |
544 | 544 | ||
545 | /* Check the id is in the supported range */ | 545 | /* Check the id is in the supported range */ |
546 | if (id > SCTP_AUTH_HMAC_ID_MAX) | 546 | if (id > SCTP_AUTH_HMAC_ID_MAX) { |
547 | id = 0; | ||
547 | continue; | 548 | continue; |
549 | } | ||
548 | 550 | ||
549 | /* See is we support the id. Supported IDs have name and | 551 | /* See is we support the id. Supported IDs have name and |
550 | * length fields set, so that we can allocated and use | 552 | * length fields set, so that we can allocated and use |
551 | * them. We can safely just check for name, for without the | 553 | * them. We can safely just check for name, for without the |
552 | * name, we can't allocate the TFM. | 554 | * name, we can't allocate the TFM. |
553 | */ | 555 | */ |
554 | if (!sctp_hmac_list[id].hmac_name) | 556 | if (!sctp_hmac_list[id].hmac_name) { |
557 | id = 0; | ||
555 | continue; | 558 | continue; |
559 | } | ||
556 | 560 | ||
557 | break; | 561 | break; |
558 | } | 562 | } |
diff --git a/net/sctp/output.c b/net/sctp/output.c index a646681f5acd..bcc4590ccaf2 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -92,7 +92,6 @@ struct sctp_packet *sctp_packet_config(struct sctp_packet *packet, | |||
92 | SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, | 92 | SCTP_DEBUG_PRINTK("%s: packet:%p vtag:0x%x\n", __func__, |
93 | packet, vtag); | 93 | packet, vtag); |
94 | 94 | ||
95 | sctp_packet_reset(packet); | ||
96 | packet->vtag = vtag; | 95 | packet->vtag = vtag; |
97 | 96 | ||
98 | if (ecn_capable && sctp_packet_empty(packet)) { | 97 | if (ecn_capable && sctp_packet_empty(packet)) { |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 24b2cd555637..d344dc481ccc 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -1232,6 +1232,18 @@ out: | |||
1232 | return 0; | 1232 | return 0; |
1233 | } | 1233 | } |
1234 | 1234 | ||
1235 | static bool list_has_sctp_addr(const struct list_head *list, | ||
1236 | union sctp_addr *ipaddr) | ||
1237 | { | ||
1238 | struct sctp_transport *addr; | ||
1239 | |||
1240 | list_for_each_entry(addr, list, transports) { | ||
1241 | if (sctp_cmp_addr_exact(ipaddr, &addr->ipaddr)) | ||
1242 | return true; | ||
1243 | } | ||
1244 | |||
1245 | return false; | ||
1246 | } | ||
1235 | /* A restart is occurring, check to make sure no new addresses | 1247 | /* A restart is occurring, check to make sure no new addresses |
1236 | * are being added as we may be under a takeover attack. | 1248 | * are being added as we may be under a takeover attack. |
1237 | */ | 1249 | */ |
@@ -1240,10 +1252,10 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
1240 | struct sctp_chunk *init, | 1252 | struct sctp_chunk *init, |
1241 | sctp_cmd_seq_t *commands) | 1253 | sctp_cmd_seq_t *commands) |
1242 | { | 1254 | { |
1243 | struct sctp_transport *new_addr, *addr; | 1255 | struct sctp_transport *new_addr; |
1244 | int found; | 1256 | int ret = 1; |
1245 | 1257 | ||
1246 | /* Implementor's Guide - Sectin 5.2.2 | 1258 | /* Implementor's Guide - Section 5.2.2 |
1247 | * ... | 1259 | * ... |
1248 | * Before responding the endpoint MUST check to see if the | 1260 | * Before responding the endpoint MUST check to see if the |
1249 | * unexpected INIT adds new addresses to the association. If new | 1261 | * unexpected INIT adds new addresses to the association. If new |
@@ -1254,31 +1266,19 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
1254 | /* Search through all current addresses and make sure | 1266 | /* Search through all current addresses and make sure |
1255 | * we aren't adding any new ones. | 1267 | * we aren't adding any new ones. |
1256 | */ | 1268 | */ |
1257 | new_addr = NULL; | ||
1258 | found = 0; | ||
1259 | |||
1260 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, | 1269 | list_for_each_entry(new_addr, &new_asoc->peer.transport_addr_list, |
1261 | transports) { | 1270 | transports) { |
1262 | found = 0; | 1271 | if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, |
1263 | list_for_each_entry(addr, &asoc->peer.transport_addr_list, | 1272 | &new_addr->ipaddr)) { |
1264 | transports) { | 1273 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, |
1265 | if (sctp_cmp_addr_exact(&new_addr->ipaddr, | 1274 | commands); |
1266 | &addr->ipaddr)) { | 1275 | ret = 0; |
1267 | found = 1; | ||
1268 | break; | ||
1269 | } | ||
1270 | } | ||
1271 | if (!found) | ||
1272 | break; | 1276 | break; |
1273 | } | 1277 | } |
1274 | |||
1275 | /* If a new address was added, ABORT the sender. */ | ||
1276 | if (!found && new_addr) { | ||
1277 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, commands); | ||
1278 | } | 1278 | } |
1279 | 1279 | ||
1280 | /* Return success if all addresses were found. */ | 1280 | /* Return success if all addresses were found. */ |
1281 | return found; | 1281 | return ret; |
1282 | } | 1282 | } |
1283 | 1283 | ||
1284 | /* Populate the verification/tie tags based on overlapping INIT | 1284 | /* Populate the verification/tie tags based on overlapping INIT |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index ca44917872d2..fbb70770ad05 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -916,6 +916,11 @@ SCTP_STATIC int sctp_setsockopt_bindx(struct sock* sk, | |||
916 | /* Walk through the addrs buffer and count the number of addresses. */ | 916 | /* Walk through the addrs buffer and count the number of addresses. */ |
917 | addr_buf = kaddrs; | 917 | addr_buf = kaddrs; |
918 | while (walk_size < addrs_size) { | 918 | while (walk_size < addrs_size) { |
919 | if (walk_size + sizeof(sa_family_t) > addrs_size) { | ||
920 | kfree(kaddrs); | ||
921 | return -EINVAL; | ||
922 | } | ||
923 | |||
919 | sa_addr = (struct sockaddr *)addr_buf; | 924 | sa_addr = (struct sockaddr *)addr_buf; |
920 | af = sctp_get_af_specific(sa_addr->sa_family); | 925 | af = sctp_get_af_specific(sa_addr->sa_family); |
921 | 926 | ||
@@ -1002,9 +1007,13 @@ static int __sctp_connect(struct sock* sk, | |||
1002 | /* Walk through the addrs buffer and count the number of addresses. */ | 1007 | /* Walk through the addrs buffer and count the number of addresses. */ |
1003 | addr_buf = kaddrs; | 1008 | addr_buf = kaddrs; |
1004 | while (walk_size < addrs_size) { | 1009 | while (walk_size < addrs_size) { |
1010 | if (walk_size + sizeof(sa_family_t) > addrs_size) { | ||
1011 | err = -EINVAL; | ||
1012 | goto out_free; | ||
1013 | } | ||
1014 | |||
1005 | sa_addr = (union sctp_addr *)addr_buf; | 1015 | sa_addr = (union sctp_addr *)addr_buf; |
1006 | af = sctp_get_af_specific(sa_addr->sa.sa_family); | 1016 | af = sctp_get_af_specific(sa_addr->sa.sa_family); |
1007 | port = ntohs(sa_addr->v4.sin_port); | ||
1008 | 1017 | ||
1009 | /* If the address family is not supported or if this address | 1018 | /* If the address family is not supported or if this address |
1010 | * causes the address buffer to overflow return EINVAL. | 1019 | * causes the address buffer to overflow return EINVAL. |
@@ -1014,6 +1023,8 @@ static int __sctp_connect(struct sock* sk, | |||
1014 | goto out_free; | 1023 | goto out_free; |
1015 | } | 1024 | } |
1016 | 1025 | ||
1026 | port = ntohs(sa_addr->v4.sin_port); | ||
1027 | |||
1017 | /* Save current address so we can work with it */ | 1028 | /* Save current address so we can work with it */ |
1018 | memcpy(&to, sa_addr, af->sockaddr_len); | 1029 | memcpy(&to, sa_addr, af->sockaddr_len); |
1019 | 1030 | ||