Re: Fragmented ordered user messages with inconsistent stream sequence numbers are accepted and delivered to the application

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, Jan 18, 2017 at 03:08:14PM +0800, Xin Long wrote:
> On Wed, Jan 18, 2017 at 3:15 AM, Xin Long <lucien.xin@xxxxxxxxx> wrote:
> > On Wed, Jan 18, 2017 at 2:57 AM, Julian Cordes <julian.cordes@xxxxxxxxx> wrote:
> >> 2017-01-17 19:49 GMT+01:00 Xin Long <lucien.xin@xxxxxxxxx>:
> >>> On Tue, Jan 17, 2017 at 9:13 PM, Julian Cordes <julian.cordes@xxxxxxxxx> wrote:
> >>>> When fragmented ordered user messages are sent to the linux kernel user
> >>>> messages with inconsistent stream sequence numbers are accepted and
> >>>> delivered to the application. Take for example an look at the following test case:
> >>>> https://github.com/nplab/PR_SCTP_Testsuite/blob/master/forward-tsn/error-cases/packet-loss/ordered/ordered-packet-loss-2.pkt
> >>>>
> >>>> Here I first inject two DATA-Chunks with sid/ssn 1/1, 2/1 into the
> >>>> kernel with packetdrill:
> >>>> line 67: +0.0 < sctp: DATA[flgs=E, len=1016, tsn=2, sid=1, ssn=1,
> >>>> ppid=0]
> >>>> line 69: +0.1 < sctp: DATA[flgs=E, len=1016, tsn=4, sid=2, ssn=1,
> >>>> ppid=0]
> >>>>
> >>>> After 0.1 seconds i then inject an FORWARD-TSN with cum_tsn=2 bundled
> >>>> with an DATA-Chunk that looks like this:
> >>>> DATA[flgs=B, len=1016, tsn=3, sid=2, ssn=0, ppid=0]
> >>>>
> >>>> This "looks" like the first segment of the user message where already a
> >>>> fragment (tsn=4) was received. But the ssn-values are  not consistent.
> >>>> The DATA-Chunk with tsn=3 has ssn=0 and the ssn=1 therefore they should
> >>>> be ignored by the IUT and not be delivered to the userland application when
> >>>> calling sctp_recvmsg. Unfortunatly the linux kernel implementation does
> >>>> currently deliver these inconsistent user messages.
> >>> sorry, I may misunderstand you.
> >>>
> >>> after FORWARD-TSN, "DATA[flgs=E, len=1016, tsn=2, sid=1, ssn=1"
> >>> should be received, then only "sctp: DATA[flgs=E, len=1016, tsn=4,
> >>> sid=2, ssn=1" is in the queue, then "DATA[flgs=B, len=1016, tsn=3,
> >>> sid=2, ssn=0, ppid=0]" is processed, these two chunks (tsn=3 and
> >>> tsn=4) should be recvmsg, as their sid are the same and ssn are
> >>> consistent (ssn=0 and ssn=1).
> >>> and your sctp_recvmsg is after above, so it should be right.
> >>>
> >>> did I miss something?
> >>>
> >>>
> >> Shouldnt the ssn be 0 for both DATA-Chunks with sid=2, because they
> >> consistent to the same first fragmented user message of stream with
> >> sid=2?
> > ahh, got you now, will look into it tomorrow,  thanks.
> >
> linux sctp now doesn't yet support "interleave", it believes the chunks /
> fragmenteds from the same msg have continuous / consistent TSNs.
> That's why it can ignore the ssn and only care about tsn and flag
> when reasm fragmenteds.

Interleaving is a feature, but what is happening here is that we are not
validating the ssn in this case, and it allows an attacker to corrupt
the messages once necessary knowledge is obtained (such as knowing
vtag).

line 67: +0.0 < sctp: DATA[flgs=E, len=1016, tsn=2, sid=1, ssn=1, ppid=0]
line 69: +0.1 < sctp: DATA[flgs=E, len=1016, tsn=4, sid=2, ssn=1, ppid=0]
After 0.1 seconds i then inject an FORWARD-TSN with cum_tsn=2 bundled
with an DATA-Chunk that looks like this:
DATA[flgs=B, len=1016, tsn=3, sid=2, ssn=0, ppid=0]

Simplifying, looks like:
                                         v----------.
DATA[flgs=B, len=1016, tsn=3, sid=2, ssn=0, ppid=0] |
DATA[flgs=E, len=1016, tsn=4, sid=2, ssn=1, ppid=0] |
                                         ^----------+-- doesn't match

https://tools.ietf.org/html/rfc4960#section-6.9
   2)  The transmitter MUST then assign, in sequence, a separate TSN to
       each of the DATA chunks in the series.  The transmitter assigns
       the same SSN to each of the DATA chunks. ....

A draft, just to illustrate an initial fix for this:
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c
index aa3624d50278..273abcf631ef 100644
--- a/net/sctp/ulpqueue.c
+++ b/net/sctp/ulpqueue.c
@@ -419,6 +419,7 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
 	size_t pd_len = 0;
 	struct sctp_association *asoc;
 	u32 pd_point;
+	u16 cssn;
 
 	/* Initialized to 0 just to avoid compiler warning message.  Will
 	 * never be used with this value. It is referenced only after it
@@ -461,10 +462,12 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
 
 			first_frag = pos;
 			next_tsn = ctsn + 1;
+			cssn = cevent->ssn;
 			break;
 
 		case SCTP_DATA_MIDDLE_FRAG:
-			if ((first_frag) && (ctsn == next_tsn)) {
+			if (first_frag && ctsn == next_tsn &&
+			    cssn == cevent->ssn) {
 				next_tsn++;
 				if (pd_first) {
 				    pd_last = pos;
@@ -475,7 +478,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul
 			break;
 
 		case SCTP_DATA_LAST_FRAG:
-			if (first_frag && (ctsn == next_tsn))
+			if (first_frag && ctsn == next_tsn &&
+			    cssn == cevent->ssn)
 				goto found;
 			else
 				first_frag = NULL;

Though the real fix is more complicated than this because in such case
the fragments have to be discarded and this is not going to happen with
the above.

> 
> we will improve it when implementing "interleave" soon, thanks for reporting.
> 
> >>>>
> >>>> There are many test-cases that all reproduce this
> >>>> issue. Just take a look at the README at
> >>>> https://github.com/nplab/PR_SCTP_Testsuite/tree/master/forward-tsn/error-cases/packet-loss/ordered.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-sctp" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [Linux Networking Development]     [Linux OMAP]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux