Skip to content

Commit 88e4f75

Browse files
committed
Merge branch 'sctp-fix-gap-ack-blocks'
Marcelo Ricardo Leitner says: ==================== sctp: fix the handling of SACK Gap Ack blocks sctp_acked() is using 32bit arithmetics on 16bits vars, via TSN_lte() macros, which is weird and confusing. Once the offset to ctsn is calculated, all wrapping is already handled and thus to verify the Gap Ack blocks we can just use pure less/big-or-equal than checks. Also, rename gap variable to tsn_offset, so it's more meaningful, as it doesn't point to any gap at all. Even so, I don't think this discrepancy resulted in any practical bug. This patch is a preparation for the next one, which will introduce typecheck() for TSN_lte() macros and would cause a compile error here. Suggested-by: David Laight <[email protected]> Reported-by: David Laight <[email protected]> Signed-off-by: Marcelo Ricardo Leitner <[email protected]> ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 21641c2 + 182691d commit 88e4f75

File tree

2 files changed

+24
-81
lines changed

2 files changed

+24
-81
lines changed

include/net/sctp/sm.h

Lines changed: 18 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -307,85 +307,27 @@ static inline __u16 sctp_data_size(struct sctp_chunk *chunk)
307307
}
308308

309309
/* Compare two TSNs */
310+
#define TSN_lt(a,b) \
311+
(typecheck(__u32, a) && \
312+
typecheck(__u32, b) && \
313+
((__s32)((a) - (b)) < 0))
310314

311-
/* RFC 1982 - Serial Number Arithmetic
312-
*
313-
* 2. Comparison
314-
* Then, s1 is said to be equal to s2 if and only if i1 is equal to i2,
315-
* in all other cases, s1 is not equal to s2.
316-
*
317-
* s1 is said to be less than s2 if, and only if, s1 is not equal to s2,
318-
* and
319-
*
320-
* (i1 < i2 and i2 - i1 < 2^(SERIAL_BITS - 1)) or
321-
* (i1 > i2 and i1 - i2 > 2^(SERIAL_BITS - 1))
322-
*
323-
* s1 is said to be greater than s2 if, and only if, s1 is not equal to
324-
* s2, and
325-
*
326-
* (i1 < i2 and i2 - i1 > 2^(SERIAL_BITS - 1)) or
327-
* (i1 > i2 and i1 - i2 < 2^(SERIAL_BITS - 1))
328-
*/
329-
330-
/*
331-
* RFC 2960
332-
* 1.6 Serial Number Arithmetic
333-
*
334-
* Comparisons and arithmetic on TSNs in this document SHOULD use Serial
335-
* Number Arithmetic as defined in [RFC1982] where SERIAL_BITS = 32.
336-
*/
337-
338-
enum {
339-
TSN_SIGN_BIT = (1<<31)
340-
};
341-
342-
static inline int TSN_lt(__u32 s, __u32 t)
343-
{
344-
return ((s) - (t)) & TSN_SIGN_BIT;
345-
}
346-
347-
static inline int TSN_lte(__u32 s, __u32 t)
348-
{
349-
return ((s) == (t)) || (((s) - (t)) & TSN_SIGN_BIT);
350-
}
315+
#define TSN_lte(a,b) \
316+
(typecheck(__u32, a) && \
317+
typecheck(__u32, b) && \
318+
((__s32)((a) - (b)) <= 0))
351319

352320
/* Compare two SSNs */
353-
354-
/*
355-
* RFC 2960
356-
* 1.6 Serial Number Arithmetic
357-
*
358-
* Comparisons and arithmetic on Stream Sequence Numbers in this document
359-
* SHOULD use Serial Number Arithmetic as defined in [RFC1982] where
360-
* SERIAL_BITS = 16.
361-
*/
362-
enum {
363-
SSN_SIGN_BIT = (1<<15)
364-
};
365-
366-
static inline int SSN_lt(__u16 s, __u16 t)
367-
{
368-
return ((s) - (t)) & SSN_SIGN_BIT;
369-
}
370-
371-
static inline int SSN_lte(__u16 s, __u16 t)
372-
{
373-
return ((s) == (t)) || (((s) - (t)) & SSN_SIGN_BIT);
374-
}
375-
376-
/*
377-
* ADDIP 3.1.1
378-
* The valid range of Serial Number is from 0 to 4294967295 (2**32 - 1). Serial
379-
* Numbers wrap back to 0 after reaching 4294967295.
380-
*/
381-
enum {
382-
ADDIP_SERIAL_SIGN_BIT = (1<<31)
383-
};
384-
385-
static inline int ADDIP_SERIAL_gte(__u32 s, __u32 t)
386-
{
387-
return ((s) == (t)) || (((t) - (s)) & ADDIP_SERIAL_SIGN_BIT);
388-
}
321+
#define SSN_lt(a,b) \
322+
(typecheck(__u16, a) && \
323+
typecheck(__u16, b) && \
324+
((__s16)((a) - (b)) < 0))
325+
326+
/* ADDIP 3.1.1 */
327+
#define ADDIP_SERIAL_gte(a,b) \
328+
(typecheck(__u32, a) && \
329+
typecheck(__u32, b) && \
330+
((__s32)((b) - (a)) <= 0))
389331

390332
/* Check VTAG of the packet matches the sender's own tag. */
391333
static inline int

net/sctp/outqueue.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn)
17191719
{
17201720
int i;
17211721
sctp_sack_variable_t *frags;
1722-
__u16 gap;
1722+
__u16 tsn_offset, blocks;
17231723
__u32 ctsn = ntohl(sack->cum_tsn_ack);
17241724

17251725
if (TSN_lte(tsn, ctsn))
@@ -1738,10 +1738,11 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn)
17381738
*/
17391739

17401740
frags = sack->variable;
1741-
gap = tsn - ctsn;
1742-
for (i = 0; i < ntohs(sack->num_gap_ack_blocks); ++i) {
1743-
if (TSN_lte(ntohs(frags[i].gab.start), gap) &&
1744-
TSN_lte(gap, ntohs(frags[i].gab.end)))
1741+
blocks = ntohs(sack->num_gap_ack_blocks);
1742+
tsn_offset = tsn - ctsn;
1743+
for (i = 0; i < blocks; ++i) {
1744+
if (tsn_offset >= ntohs(frags[i].gab.start) &&
1745+
tsn_offset <= ntohs(frags[i].gab.end))
17451746
goto pass;
17461747
}
17471748

0 commit comments

Comments
 (0)