diff options
Diffstat (limited to 'net/sctp/inqueue.c')
| -rw-r--r-- | net/sctp/inqueue.c | 39 |
1 files changed, 24 insertions, 15 deletions
diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 2e83405b8be7..cedf4351556c 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -59,19 +59,6 @@ void sctp_inq_init(struct sctp_inq *queue) queue->malloced = 0; } -/* Create an initialized sctp_inq. */ -struct sctp_inq *sctp_inq_new(void) -{ - struct sctp_inq *retval; - - retval = t_new(struct sctp_inq, GFP_ATOMIC); - if (retval) { - sctp_inq_init(retval); - retval->malloced = 1; - } - return retval; -} - /* Release the memory associated with an SCTP inqueue. */ void sctp_inq_free(struct sctp_inq *queue) { @@ -157,14 +144,36 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) } chunk->chunk_hdr = ch; - chunk->chunk_end = ((__u8 *) ch) - + WORD_ROUND(ntohs(ch->length)); + chunk->chunk_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); + /* In the unlikely case of an IP reassembly, the skb could be + * non-linear. If so, update chunk_end so that it doesn't go past + * the skb->tail. + */ + if (unlikely(skb_is_nonlinear(chunk->skb))) { + if (chunk->chunk_end > chunk->skb->tail) + chunk->chunk_end = chunk->skb->tail; + } skb_pull(chunk->skb, sizeof(sctp_chunkhdr_t)); chunk->subh.v = NULL; /* Subheader is no longer valid. */ if (chunk->chunk_end < chunk->skb->tail) { /* This is not a singleton */ chunk->singleton = 0; + } else if (chunk->chunk_end > chunk->skb->tail) { + /* RFC 2960, Section 6.10 Bundling + * + * Partial chunks MUST NOT be placed in an SCTP packet. + * If the receiver detects a partial chunk, it MUST drop + * the chunk. + * + * Since the end of the chunk is past the end of our buffer + * (which contains the whole packet, we can freely discard + * the whole packet. + */ + sctp_chunk_free(chunk); + chunk = queue->in_progress = NULL; + + return NULL; } else { /* We are at the end of the packet, so mark the chunk * in case we need to send a SACK. |
