summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authortuexen <tuexen@FreeBSD.org>2012-04-19 12:43:19 +0000
committertuexen <tuexen@FreeBSD.org>2012-04-19 12:43:19 +0000
commit9035fb1c4c6e1bb36fce152aa86c05ccac23239a (patch)
tree9c13f406a5f9af38a9f4b49f9732347046ec6112 /sys/netinet
parentfdb56713f24f9603c0b1d9d04f819a450c247a91 (diff)
downloadFreeBSD-src-9035fb1c4c6e1bb36fce152aa86c05ccac23239a.zip
FreeBSD-src-9035fb1c4c6e1bb36fce152aa86c05ccac23239a.tar.gz
Fix a bug where we copy out more data from a mbuf chain that are
actually in it. This happens when SCTP receives an unknown chunk, which requires the sending of an ERROR chunk, and there is no final padding but the chunk is not 4-byte aligned. Reported by yueting via rwatson@ MFC after: 3 days
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/sctp_indata.c10
-rw-r--r--sys/netinet/sctp_input.c27
2 files changed, 21 insertions, 16 deletions
diff --git a/sys/netinet/sctp_indata.c b/sys/netinet/sctp_indata.c
index 54372ac..d7b9d9c 100644
--- a/sys/netinet/sctp_indata.c
+++ b/sys/netinet/sctp_indata.c
@@ -2746,11 +2746,13 @@ sctp_process_data(struct mbuf **mm, int iphlen, int *offset, int length,
phd->param_length =
htons(chk_length + sizeof(*phd));
SCTP_BUF_LEN(merr) = sizeof(*phd);
- SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset,
- SCTP_SIZE32(chk_length),
- M_DONTWAIT);
+ SCTP_BUF_NEXT(merr) = SCTP_M_COPYM(m, *offset, chk_length, M_DONTWAIT);
if (SCTP_BUF_NEXT(merr)) {
- sctp_queue_op_err(stcb, merr);
+ if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(merr), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
+ sctp_m_freem(merr);
+ } else {
+ sctp_queue_op_err(stcb, merr);
+ }
} else {
sctp_m_freem(merr);
}
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index 1f9ee89..fe0e636 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -5461,23 +5461,26 @@ process_control_chunks:
phd->param_type = htons(SCTP_CAUSE_UNRECOG_CHUNK);
phd->param_length = htons(chk_length + sizeof(*phd));
SCTP_BUF_LEN(mm) = sizeof(*phd);
- SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, SCTP_SIZE32(chk_length),
- M_DONTWAIT);
+ SCTP_BUF_NEXT(mm) = SCTP_M_COPYM(m, *offset, chk_length, M_DONTWAIT);
if (SCTP_BUF_NEXT(mm)) {
+ if (sctp_pad_lastmbuf(SCTP_BUF_NEXT(mm), SCTP_SIZE32(chk_length) - chk_length, NULL)) {
+ sctp_m_freem(mm);
+ } else {
#ifdef SCTP_MBUF_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
- struct mbuf *mat;
-
- mat = SCTP_BUF_NEXT(mm);
- while (mat) {
- if (SCTP_BUF_IS_EXTENDED(mat)) {
- sctp_log_mb(mat, SCTP_MBUF_ICOPY);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_MBUF_LOGGING_ENABLE) {
+ struct mbuf *mat;
+
+ mat = SCTP_BUF_NEXT(mm);
+ while (mat) {
+ if (SCTP_BUF_IS_EXTENDED(mat)) {
+ sctp_log_mb(mat, SCTP_MBUF_ICOPY);
+ }
+ mat = SCTP_BUF_NEXT(mat);
}
- mat = SCTP_BUF_NEXT(mat);
}
- }
#endif
- sctp_queue_op_err(stcb, mm);
+ sctp_queue_op_err(stcb, mm);
+ }
} else {
sctp_m_freem(mm);
}
OpenPOWER on IntegriCloud