diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sctp/inqueue.c | 33 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 3 |
2 files changed, 10 insertions, 26 deletions
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_statefuns.c b/net/sctp/sm_statefuns.c index bdea3dfbad31..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 | ||