]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Ensure that ERROR chunks are always padded by implementing this
authortuexen <tuexen@FreeBSD.org>
Fri, 11 Sep 2015 13:54:33 +0000 (13:54 +0000)
committertuexen <tuexen@FreeBSD.org>
Fri, 11 Sep 2015 13:54:33 +0000 (13:54 +0000)
in the routine, which queues an ERROR chunk, instead on relyinh
on the callers to do so. Since one caller missed this, this actially
fixes a bug.

MFC after: 1 week

sys/netinet/sctp_constants.h
sys/netinet/sctp_indata.c
sys/netinet/sctp_input.c
sys/netinet/sctp_output.c

index 760c3b472cc81cbb9a9af7eba771ad3e983ffa30..a26bc5b5c333852cbdc8e46cc91b1ccb5c9f9314 100644 (file)
@@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
  */
 #define SCTP_LARGEST_INIT_ACCEPTED (65535 - 2048)
 
+/* Largest length of a chunk */
+#define SCTP_MAX_CHUNK_LENGTH 0xffff
 /* Number of addresses where we just skip the counting */
 #define SCTP_COUNT_LIMIT 40
 
index 7d92655cc745b11244e0cc3b8a855a7d2fdb5400..d9ca669467895a846c25371570d9908206810c67 100644 (file)
@@ -2513,11 +2513,7 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
                                                SCTP_BUF_LEN(merr) = sizeof(*phd);
                                                SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_NOWAIT);
                                                if (SCTP_BUF_NEXT(merr)) {
-                                                       if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL) == NULL) {
-                                                               sctp_m_freem(merr);
-                                                       } else {
-                                                               sctp_queue_op_err(stcb, merr);
-                                                       }
+                                                       sctp_queue_op_err(stcb, merr);
                                                } else {
                                                        sctp_m_freem(merr);
                                                }
index 297ddf2c788ec70955d0872d3841e97bf1bcf2c3..9f8d032888bfc500ae58afcf858c1caba39053d8 100644 (file)
@@ -5602,16 +5602,12 @@ process_control_chunks:
                                        SCTP_BUF_LEN(mm) = sizeof(*phd);
                                        SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, len, M_NOWAIT);
                                        if (SCTP_BUF_NEXT(mm)) {
-                                               if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(len) - len, NULL) == NULL) {
-                                                       sctp_m_freem(mm);
-                                               } else {
 #ifdef SCTP_MBUF_LOGGING
-                                                       if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
-                                                               sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY);
-                                                       }
-#endif
-                                                       sctp_queue_op_err(stcb, mm);
+                                               if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+                                                       sctp_log_mbc(SCTP_BUF_NEXT(mm), SCTP_MBUF_ICOPY);
                                                }
+#endif
+                                               sctp_queue_op_err(stcb, mm);
                                        } else {
                                                sctp_m_freem(mm);
                                        }
index 772ec949a9a473704e1fd65b778301319c63d857..f515d6a6cd2ba6afa729f0c00f2ffd6cd867f3a1 100644 (file)
@@ -8850,9 +8850,37 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
         */
        struct sctp_chunkhdr *hdr;
        struct sctp_tmit_chunk *chk;
-       struct mbuf *mat;
+       struct mbuf *mat, *last_mbuf;
+       uint32_t chunk_length;
+       uint16_t padding_length;
 
        SCTP_TCB_LOCK_ASSERT(stcb);
+       SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT);
+       if (op_err == NULL) {
+               return;
+       }
+       last_mbuf = NULL;
+       chunk_length = 0;
+       for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) {
+               chunk_length += SCTP_BUF_LEN(mat);
+               if (SCTP_BUF_NEXT(mat) == NULL) {
+                       last_mbuf = mat;
+               }
+       }
+       if (chunk_length > SCTP_MAX_CHUNK_LENGTH) {
+               sctp_m_freem(op_err);
+               return;
+       }
+       padding_length = chunk_length % 4;
+       if (padding_length != 0) {
+               padding_length = 4 - padding_length;
+       }
+       if (padding_length != 0) {
+               if (sctp_add_pad_tombuf(last_mbuf, padding_length) == NULL) {
+                       sctp_m_freem(op_err);
+                       return;
+               }
+       }
        sctp_alloc_a_chunk(stcb, chk);
        if (chk == NULL) {
                /* no memory */
@@ -8860,15 +8888,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
                return;
        }
        chk->copy_by_ref = 0;
-       SCTP_BUF_PREPEND(op_err, sizeof(struct sctp_chunkhdr), M_NOWAIT);
-       if (op_err == NULL) {
-               sctp_free_a_chunk(stcb, chk, SCTP_SO_NOT_LOCKED);
-               return;
-       }
-       chk->send_size = 0;
-       for (mat = op_err; mat != NULL; mat = SCTP_BUF_NEXT(mat)) {
-               chk->send_size += SCTP_BUF_LEN(mat);
-       }
+       chk->send_size = (uint16_t) chunk_length;
        chk->sent = SCTP_DATAGRAM_UNSENT;
        chk->snd_count = 0;
        chk->asoc = &stcb->asoc;
@@ -8878,9 +8898,7 @@ sctp_queue_op_err(struct sctp_tcb *stcb, struct mbuf *op_err)
        hdr->chunk_type = SCTP_OPERATION_ERROR;
        hdr->chunk_flags = 0;
        hdr->chunk_length = htons(chk->send_size);
-       TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue,
-           chk,
-           sctp_next);
+       TAILQ_INSERT_TAIL(&chk->asoc->control_send_queue, chk, sctp_next);
        chk->asoc->ctrl_queue_cnt++;
 }