aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-18 12:31:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-18 12:31:37 -0400
commit2e923b0251932ad4a82cc87ec1443a1f1d17073e (patch)
treed12032bc9bcfbb8a57659275d1b9b582f23f2ecc /net/sctp
parentffd8221bc348f8c282d1271883dbe629ea8ae289 (diff)
parentf2d9da1a8375cbe53df5b415d059429013a3a79f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Pull networking fixes from David Miller: 1) Include fixes for netrom and dsa (Fabian Frederick and Florian Fainelli) 2) Fix FIXED_PHY support in stmmac, from Giuseppe CAVALLARO. 3) Several SKB use after free fixes (vxlan, openvswitch, vxlan, ip_tunnel, fou), from Li ROngQing. 4) fec driver PTP support fixes from Luwei Zhou and Nimrod Andy. 5) Use after free in virtio_net, from Michael S Tsirkin. 6) Fix flow mask handling for megaflows in openvswitch, from Pravin B Shelar. 7) ISDN gigaset and capi bug fixes from Tilman Schmidt. 8) Fix route leak in ip_send_unicast_reply(), from Vasily Averin. 9) Fix two eBPF JIT bugs on x86, from Alexei Starovoitov. 10) TCP_SKB_CB() reorganization caused a few regressions, fixed by Cong Wang and Eric Dumazet. 11) Don't overwrite end of SKB when parsing malformed sctp ASCONF chunks, from Daniel Borkmann. 12) Don't call sock_kfree_s() with NULL pointers, this function also has the side effect of adjusting the socket memory usage. From Cong Wang. * git://git.kernel.org/pub/scm/linux/kernel/git/davem/net: (90 commits) bna: fix skb->truesize underestimation net: dsa: add includes for ethtool and phy_fixed definitions openvswitch: Set flow-key members. netrom: use linux/uaccess.h dsa: Fix conversion from host device to mii bus tipc: fix bug in bundled buffer reception ipv6: introduce tcp_v6_iif() sfc: add support for skb->xmit_more r8152: return -EBUSY for runtime suspend ipv4: fix a potential use after free in fou.c ipv4: fix a potential use after free in ip_tunnel_core.c hyperv: Add handling of IP header with option field in netvsc_set_hash() openvswitch: Create right mask with disabled megaflows vxlan: fix a free after use openvswitch: fix a use after free ipv4: dst_entry leak in ip_send_unicast_reply() ipv4: clean up cookie_v4_check() ipv4: share tcp_v4_save_options() with cookie_v4_check() ipv4: call __ip_options_echo() in cookie_v4_check() atm: simplify lanai.c by using module_pci_driver ...
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/associola.c2
-rw-r--r--net/sctp/inqueue.c33
-rw-r--r--net/sctp/sm_make_chunk.c99
-rw-r--r--net/sctp/sm_statefuns.c21
4 files changed, 69 insertions, 86 deletions
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index a88b8524846e..f791edd64d6c 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -1668,6 +1668,8 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
1668 * ack chunk whose serial number matches that of the request. 1668 * ack chunk whose serial number matches that of the request.
1669 */ 1669 */
1670 list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) { 1670 list_for_each_entry(ack, &asoc->asconf_ack_list, transmitted_list) {
1671 if (sctp_chunk_pending(ack))
1672 continue;
1671 if (ack->subh.addip_hdr->serial == serial) { 1673 if (ack->subh.addip_hdr->serial == serial) {
1672 sctp_chunk_hold(ack); 1674 sctp_chunk_hold(ack);
1673 return ack; 1675 return ack;
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c
index 4de12afa13d4..7e8a16c77039 100644
--- a/net/sctp/inqueue.c
+++ b/net/sctp/inqueue.c
@@ -140,18 +140,9 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
140 } else { 140 } else {
141 /* Nothing to do. Next chunk in the packet, please. */ 141 /* Nothing to do. Next chunk in the packet, please. */
142 ch = (sctp_chunkhdr_t *) chunk->chunk_end; 142 ch = (sctp_chunkhdr_t *) chunk->chunk_end;
143
144 /* Force chunk->skb->data to chunk->chunk_end. */ 143 /* Force chunk->skb->data to chunk->chunk_end. */
145 skb_pull(chunk->skb, 144 skb_pull(chunk->skb, chunk->chunk_end - chunk->skb->data);
146 chunk->chunk_end - chunk->skb->data); 145 /* We are guaranteed to pull a SCTP header. */
147
148 /* Verify that we have at least chunk headers
149 * worth of buffer left.
150 */
151 if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) {
152 sctp_chunk_free(chunk);
153 chunk = queue->in_progress = NULL;
154 }
155 } 146 }
156 } 147 }
157 148
@@ -187,24 +178,14 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
187 skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); 178 skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t));
188 chunk->subh.v = NULL; /* Subheader is no longer valid. */ 179 chunk->subh.v = NULL; /* Subheader is no longer valid. */
189 180
190 if (chunk->chunk_end < skb_tail_pointer(chunk->skb)) { 181 if (chunk->chunk_end + sizeof(sctp_chunkhdr_t) <
182 skb_tail_pointer(chunk->skb)) {
191 /* This is not a singleton */ 183 /* This is not a singleton */
192 chunk->singleton = 0; 184 chunk->singleton = 0;
193 } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) { 185 } else if (chunk->chunk_end > skb_tail_pointer(chunk->skb)) {
194 /* RFC 2960, Section 6.10 Bundling 186 /* Discard inside state machine. */
195 * 187 chunk->pdiscard = 1;
196 * Partial chunks MUST NOT be placed in an SCTP packet. 188 chunk->chunk_end = skb_tail_pointer(chunk->skb);
197 * If the receiver detects a partial chunk, it MUST drop
198 * the chunk.
199 *
200 * Since the end of the chunk is past the end of our buffer
201 * (which contains the whole packet, we can freely discard
202 * the whole packet.
203 */
204 sctp_chunk_free(chunk);
205 chunk = queue->in_progress = NULL;
206
207 return NULL;
208 } else { 189 } else {
209 /* We are at the end of the packet, so mark the chunk 190 /* We are at the end of the packet, so mark the chunk
210 * in case we need to send a SACK. 191 * in case we need to send a SACK.
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index ae0e616a7ca5..ab734be8cb20 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -3110,50 +3110,63 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
3110 return SCTP_ERROR_NO_ERROR; 3110 return SCTP_ERROR_NO_ERROR;
3111} 3111}
3112 3112
3113/* Verify the ASCONF packet before we process it. */ 3113/* Verify the ASCONF packet before we process it. */
3114int sctp_verify_asconf(const struct sctp_association *asoc, 3114bool sctp_verify_asconf(const struct sctp_association *asoc,
3115 struct sctp_paramhdr *param_hdr, void *chunk_end, 3115 struct sctp_chunk *chunk, bool addr_param_needed,
3116 struct sctp_paramhdr **errp) { 3116 struct sctp_paramhdr **errp)
3117 sctp_addip_param_t *asconf_param; 3117{
3118 sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) chunk->chunk_hdr;
3118 union sctp_params param; 3119 union sctp_params param;
3119 int length, plen; 3120 bool addr_param_seen = false;
3120
3121 param.v = (sctp_paramhdr_t *) param_hdr;
3122 while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) {
3123 length = ntohs(param.p->length);
3124 *errp = param.p;
3125 3121
3126 if (param.v > chunk_end - length || 3122 sctp_walk_params(param, addip, addip_hdr.params) {
3127 length < sizeof(sctp_paramhdr_t)) 3123 size_t length = ntohs(param.p->length);
3128 return 0;
3129 3124
3125 *errp = param.p;
3130 switch (param.p->type) { 3126 switch (param.p->type) {
3127 case SCTP_PARAM_ERR_CAUSE:
3128 break;
3129 case SCTP_PARAM_IPV4_ADDRESS:
3130 if (length != sizeof(sctp_ipv4addr_param_t))
3131 return false;
3132 addr_param_seen = true;
3133 break;
3134 case SCTP_PARAM_IPV6_ADDRESS:
3135 if (length != sizeof(sctp_ipv6addr_param_t))
3136 return false;
3137 addr_param_seen = true;
3138 break;
3131 case SCTP_PARAM_ADD_IP: 3139 case SCTP_PARAM_ADD_IP:
3132 case SCTP_PARAM_DEL_IP: 3140 case SCTP_PARAM_DEL_IP:
3133 case SCTP_PARAM_SET_PRIMARY: 3141 case SCTP_PARAM_SET_PRIMARY:
3134 asconf_param = (sctp_addip_param_t *)param.v; 3142 /* In ASCONF chunks, these need to be first. */
3135 plen = ntohs(asconf_param->param_hdr.length); 3143 if (addr_param_needed && !addr_param_seen)
3136 if (plen < sizeof(sctp_addip_param_t) + 3144 return false;
3137 sizeof(sctp_paramhdr_t)) 3145 length = ntohs(param.addip->param_hdr.length);
3138 return 0; 3146 if (length < sizeof(sctp_addip_param_t) +
3147 sizeof(sctp_paramhdr_t))
3148 return false;
3139 break; 3149 break;
3140 case SCTP_PARAM_SUCCESS_REPORT: 3150 case SCTP_PARAM_SUCCESS_REPORT:
3141 case SCTP_PARAM_ADAPTATION_LAYER_IND: 3151 case SCTP_PARAM_ADAPTATION_LAYER_IND:
3142 if (length != sizeof(sctp_addip_param_t)) 3152 if (length != sizeof(sctp_addip_param_t))
3143 return 0; 3153 return false;
3144
3145 break; 3154 break;
3146 default: 3155 default:
3147 break; 3156 /* This is unkown to us, reject! */
3157 return false;
3148 } 3158 }
3149
3150 param.v += WORD_ROUND(length);
3151 } 3159 }
3152 3160
3153 if (param.v != chunk_end) 3161 /* Remaining sanity checks. */
3154 return 0; 3162 if (addr_param_needed && !addr_param_seen)
3163 return false;
3164 if (!addr_param_needed && addr_param_seen)
3165 return false;
3166 if (param.v != chunk->chunk_end)
3167 return false;
3155 3168
3156 return 1; 3169 return true;
3157} 3170}
3158 3171
3159/* Process an incoming ASCONF chunk with the next expected serial no. and 3172/* Process an incoming ASCONF chunk with the next expected serial no. and
@@ -3162,16 +3175,17 @@ int sctp_verify_asconf(const struct sctp_association *asoc,
3162struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, 3175struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
3163 struct sctp_chunk *asconf) 3176 struct sctp_chunk *asconf)
3164{ 3177{
3178 sctp_addip_chunk_t *addip = (sctp_addip_chunk_t *) asconf->chunk_hdr;
3179 bool all_param_pass = true;
3180 union sctp_params param;
3165 sctp_addiphdr_t *hdr; 3181 sctp_addiphdr_t *hdr;
3166 union sctp_addr_param *addr_param; 3182 union sctp_addr_param *addr_param;
3167 sctp_addip_param_t *asconf_param; 3183 sctp_addip_param_t *asconf_param;
3168 struct sctp_chunk *asconf_ack; 3184 struct sctp_chunk *asconf_ack;
3169
3170 __be16 err_code; 3185 __be16 err_code;
3171 int length = 0; 3186 int length = 0;
3172 int chunk_len; 3187 int chunk_len;
3173 __u32 serial; 3188 __u32 serial;
3174 int all_param_pass = 1;
3175 3189
3176 chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); 3190 chunk_len = ntohs(asconf->chunk_hdr->length) - sizeof(sctp_chunkhdr_t);
3177 hdr = (sctp_addiphdr_t *)asconf->skb->data; 3191 hdr = (sctp_addiphdr_t *)asconf->skb->data;
@@ -3199,9 +3213,14 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
3199 goto done; 3213 goto done;
3200 3214
3201 /* Process the TLVs contained within the ASCONF chunk. */ 3215 /* Process the TLVs contained within the ASCONF chunk. */
3202 while (chunk_len > 0) { 3216 sctp_walk_params(param, addip, addip_hdr.params) {
3217 /* Skip preceeding address parameters. */
3218 if (param.p->type == SCTP_PARAM_IPV4_ADDRESS ||
3219 param.p->type == SCTP_PARAM_IPV6_ADDRESS)
3220 continue;
3221
3203 err_code = sctp_process_asconf_param(asoc, asconf, 3222 err_code = sctp_process_asconf_param(asoc, asconf,
3204 asconf_param); 3223 param.addip);
3205 /* ADDIP 4.1 A7) 3224 /* ADDIP 4.1 A7)
3206 * If an error response is received for a TLV parameter, 3225 * If an error response is received for a TLV parameter,
3207 * all TLVs with no response before the failed TLV are 3226 * all TLVs with no response before the failed TLV are
@@ -3209,28 +3228,20 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
3209 * the failed response are considered unsuccessful unless 3228 * the failed response are considered unsuccessful unless
3210 * a specific success indication is present for the parameter. 3229 * a specific success indication is present for the parameter.
3211 */ 3230 */
3212 if (SCTP_ERROR_NO_ERROR != err_code) 3231 if (err_code != SCTP_ERROR_NO_ERROR)
3213 all_param_pass = 0; 3232 all_param_pass = false;
3214
3215 if (!all_param_pass) 3233 if (!all_param_pass)
3216 sctp_add_asconf_response(asconf_ack, 3234 sctp_add_asconf_response(asconf_ack, param.addip->crr_id,
3217 asconf_param->crr_id, err_code, 3235 err_code, param.addip);
3218 asconf_param);
3219 3236
3220 /* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add 3237 /* ADDIP 4.3 D11) When an endpoint receiving an ASCONF to add
3221 * an IP address sends an 'Out of Resource' in its response, it 3238 * an IP address sends an 'Out of Resource' in its response, it
3222 * MUST also fail any subsequent add or delete requests bundled 3239 * MUST also fail any subsequent add or delete requests bundled
3223 * in the ASCONF. 3240 * in the ASCONF.
3224 */ 3241 */
3225 if (SCTP_ERROR_RSRC_LOW == err_code) 3242 if (err_code == SCTP_ERROR_RSRC_LOW)
3226 goto done; 3243 goto done;
3227
3228 /* Move to the next ASCONF param. */
3229 length = ntohs(asconf_param->param_hdr.length);
3230 asconf_param = (void *)asconf_param + length;
3231 chunk_len -= length;
3232 } 3244 }
3233
3234done: 3245done:
3235 asoc->peer.addip_serial++; 3246 asoc->peer.addip_serial++;
3236 3247
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index c8f606324134..3ee27b7704ff 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -170,6 +170,9 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk,
170{ 170{
171 __u16 chunk_length = ntohs(chunk->chunk_hdr->length); 171 __u16 chunk_length = ntohs(chunk->chunk_hdr->length);
172 172
173 /* Previously already marked? */
174 if (unlikely(chunk->pdiscard))
175 return 0;
173 if (unlikely(chunk_length < required_length)) 176 if (unlikely(chunk_length < required_length))
174 return 0; 177 return 0;
175 178
@@ -3591,9 +3594,7 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net,
3591 struct sctp_chunk *asconf_ack = NULL; 3594 struct sctp_chunk *asconf_ack = NULL;
3592 struct sctp_paramhdr *err_param = NULL; 3595 struct sctp_paramhdr *err_param = NULL;
3593 sctp_addiphdr_t *hdr; 3596 sctp_addiphdr_t *hdr;
3594 union sctp_addr_param *addr_param;
3595 __u32 serial; 3597 __u32 serial;
3596 int length;
3597 3598
3598 if (!sctp_vtag_verify(chunk, asoc)) { 3599 if (!sctp_vtag_verify(chunk, asoc)) {
3599 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, 3600 sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
@@ -3618,17 +3619,8 @@ sctp_disposition_t sctp_sf_do_asconf(struct net *net,
3618 hdr = (sctp_addiphdr_t *)chunk->skb->data; 3619 hdr = (sctp_addiphdr_t *)chunk->skb->data;
3619 serial = ntohl(hdr->serial); 3620 serial = ntohl(hdr->serial);
3620 3621
3621 addr_param = (union sctp_addr_param *)hdr->params;
3622 length = ntohs(addr_param->p.length);
3623 if (length < sizeof(sctp_paramhdr_t))
3624 return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
3625 (void *)addr_param, commands);
3626
3627 /* Verify the ASCONF chunk before processing it. */ 3622 /* Verify the ASCONF chunk before processing it. */
3628 if (!sctp_verify_asconf(asoc, 3623 if (!sctp_verify_asconf(asoc, chunk, true, &err_param))
3629 (sctp_paramhdr_t *)((void *)addr_param + length),
3630 (void *)chunk->chunk_end,
3631 &err_param))
3632 return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 3624 return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
3633 (void *)err_param, commands); 3625 (void *)err_param, commands);
3634 3626
@@ -3745,10 +3737,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net,
3745 rcvd_serial = ntohl(addip_hdr->serial); 3737 rcvd_serial = ntohl(addip_hdr->serial);
3746 3738
3747 /* Verify the ASCONF-ACK chunk before processing it. */ 3739 /* Verify the ASCONF-ACK chunk before processing it. */
3748 if (!sctp_verify_asconf(asoc, 3740 if (!sctp_verify_asconf(asoc, asconf_ack, false, &err_param))
3749 (sctp_paramhdr_t *)addip_hdr->params,
3750 (void *)asconf_ack->chunk_end,
3751 &err_param))
3752 return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, 3741 return sctp_sf_violation_paramlen(net, ep, asoc, type, arg,
3753 (void *)err_param, commands); 3742 (void *)err_param, commands);
3754 3743