SCTP: Fix to encode PROTOCOL VIOLATION error cause correctly

PROTOCOL VIOLATION error cause in ABORT is bad encode when make abort
chunk. When SCTP encode ABORT chunk with PROTOCOL VIOLATION error cause,
it just add the error messages to PROTOCOL VIOLATION error cause, the
rest four bytes(struct sctp_paramhdr) is just add to the chunk, not
change the length of error cause. This cause the ABORT chunk to be a bad
format. The chunk is like this:

ABORT chunk
Chunk type: ABORT (6)
Chunk flags: 0x00
Chunk length: 72 (*1)
Protocol violation cause
Cause code: Protocol violation (0x000d)
Cause length: 62 (*2)
Cause information: 5468652063756D756C61746976652074736E2061636B2062...
Cause padding: 0000
[Needless] 00030010
Chunk Length(*1) = 72 but Cause length(*2) only 62, not include the
extend 4 bytes.
((72 - sizeof(chunk_hdr)) = 68) != (62 +3) / 4 * 4

Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com>

authored by Wei Yongjun and committed by Vlad Yasevich 00f1c2df 8d614ade

+56 -24
+1 -1
include/net/sctp/sm.h
··· 214 const struct sctp_chunk *); 215 struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, 216 const struct sctp_chunk *); 217 - void sctp_init_cause(struct sctp_chunk *, __be16 cause, const void *, size_t); 218 struct sctp_chunk *sctp_make_abort(const struct sctp_association *, 219 const struct sctp_chunk *, 220 const size_t hint);
··· 214 const struct sctp_chunk *); 215 struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, 216 const struct sctp_chunk *); 217 + void sctp_init_cause(struct sctp_chunk *, __be16 cause, size_t); 218 struct sctp_chunk *sctp_make_abort(const struct sctp_association *, 219 const struct sctp_chunk *, 220 const size_t hint);
+1
include/net/sctp/structs.h
··· 726 struct iovec *data); 727 void sctp_chunk_free(struct sctp_chunk *); 728 void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data); 729 struct sctp_chunk *sctp_chunkify(struct sk_buff *, 730 const struct sctp_association *, 731 struct sock *);
··· 726 struct iovec *data); 727 void sctp_chunk_free(struct sctp_chunk *); 728 void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data); 729 + void *sctp_addto_param(struct sctp_chunk *, int len, const void *data); 730 struct sctp_chunk *sctp_chunkify(struct sk_buff *, 731 const struct sctp_association *, 732 struct sock *);
+52 -21
net/sctp/sm_make_chunk.c
··· 110 * abort chunk. 111 */ 112 void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, 113 - const void *payload, size_t paylen) 114 { 115 sctp_errhdr_t err; 116 __u16 len; ··· 120 len = sizeof(sctp_errhdr_t) + paylen; 121 err.length = htons(len); 122 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); 123 - sctp_addto_chunk(chunk, paylen, payload); 124 } 125 126 /* 3.3.2 Initiation (INIT) (1) ··· 779 780 /* Put the tsn back into network byte order. */ 781 payload = htonl(tsn); 782 - sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload, 783 - sizeof(payload)); 784 785 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 786 * ··· 822 goto err_copy; 823 } 824 825 - sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); 826 827 if (paylen) 828 kfree(payload); ··· 850 struct sctp_paramhdr phdr; 851 852 retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen 853 - + sizeof(sctp_chunkhdr_t)); 854 if (!retval) 855 goto end; 856 857 - sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen); 858 859 phdr.type = htons(chunk->chunk_hdr->type); 860 phdr.length = chunk->chunk_hdr->length; 861 - sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr); 862 863 end: 864 return retval; ··· 957 if (!retval) 958 goto nodata; 959 960 - sctp_init_cause(retval, cause_code, payload, paylen); 961 962 nodata: 963 return retval; ··· 1141 1142 /* Adjust the chunk length field. */ 1143 chunk->chunk_hdr->length = htons(chunklen + padlen + len); 1144 chunk->chunk_end = skb_tail_pointer(chunk->skb); 1145 1146 return target; ··· 1499 __be32 n = htonl(usecs); 1500 1501 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, 1502 - &n, sizeof(n)); 1503 *error = -SCTP_IERROR_STALE_COOKIE; 1504 } else 1505 *error = -SCTP_IERROR_NOMEM; ··· 1590 report.num_missing = htonl(1); 1591 report.type = paramtype; 1592 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM, 1593 - &report, sizeof(report)); 1594 } 1595 1596 /* Stop processing this chunk. */ ··· 1609 *errp = sctp_make_op_error_space(asoc, chunk, 0); 1610 1611 if (*errp) 1612 - sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0); 1613 1614 /* Stop processing this chunk. */ 1615 return 0; ··· 1630 *errp = sctp_make_op_error_space(asoc, chunk, payload_len); 1631 1632 if (*errp) { 1633 - sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error, 1634 - sizeof(error)); 1635 - sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param); 1636 } 1637 1638 return 0; ··· 1654 if (!*errp) 1655 *errp = sctp_make_op_error_space(asoc, chunk, len); 1656 1657 - if (*errp) 1658 - sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, 1659 - param.v, len); 1660 1661 /* Stop processing this chunk. */ 1662 return 0; ··· 1709 *errp = sctp_make_op_error_space(asoc, chunk, 1710 ntohs(chunk->chunk_hdr->length)); 1711 1712 - if (*errp) 1713 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1714 - param.v, 1715 WORD_ROUND(ntohs(param.p->length))); 1716 1717 break; 1718 case SCTP_PARAM_ACTION_SKIP: ··· 1730 1731 if (*errp) { 1732 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1733 - param.v, 1734 WORD_ROUND(ntohs(param.p->length))); 1735 } else { 1736 /* If there is no memory for generating the ERROR 1737 * report as specified, an ABORT will be triggered
··· 110 * abort chunk. 111 */ 112 void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, 113 + size_t paylen) 114 { 115 sctp_errhdr_t err; 116 __u16 len; ··· 120 len = sizeof(sctp_errhdr_t) + paylen; 121 err.length = htons(len); 122 chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); 123 } 124 125 /* 3.3.2 Initiation (INIT) (1) ··· 780 781 /* Put the tsn back into network byte order. */ 782 payload = htonl(tsn); 783 + sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload)); 784 + sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload); 785 786 /* RFC 2960 6.4 Multi-homed SCTP Endpoints 787 * ··· 823 goto err_copy; 824 } 825 826 + sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen); 827 + sctp_addto_chunk(retval, paylen, payload); 828 829 if (paylen) 830 kfree(payload); ··· 850 struct sctp_paramhdr phdr; 851 852 retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen 853 + + sizeof(sctp_paramhdr_t)); 854 if (!retval) 855 goto end; 856 857 + sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen 858 + + sizeof(sctp_paramhdr_t)); 859 860 phdr.type = htons(chunk->chunk_hdr->type); 861 phdr.length = chunk->chunk_hdr->length; 862 + sctp_addto_chunk(retval, paylen, payload); 863 + sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr); 864 865 end: 866 return retval; ··· 955 if (!retval) 956 goto nodata; 957 958 + sctp_init_cause(retval, cause_code, paylen); 959 + sctp_addto_chunk(retval, paylen, payload); 960 961 nodata: 962 return retval; ··· 1138 1139 /* Adjust the chunk length field. */ 1140 chunk->chunk_hdr->length = htons(chunklen + padlen + len); 1141 + chunk->chunk_end = skb_tail_pointer(chunk->skb); 1142 + 1143 + return target; 1144 + } 1145 + 1146 + /* Append bytes to the end of a parameter. Will panic if chunk is not big 1147 + * enough. 1148 + */ 1149 + void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data) 1150 + { 1151 + void *target; 1152 + int chunklen = ntohs(chunk->chunk_hdr->length); 1153 + 1154 + target = skb_put(chunk->skb, len); 1155 + 1156 + memcpy(target, data, len); 1157 + 1158 + /* Adjust the chunk length field. */ 1159 + chunk->chunk_hdr->length = htons(chunklen + len); 1160 chunk->chunk_end = skb_tail_pointer(chunk->skb); 1161 1162 return target; ··· 1477 __be32 n = htonl(usecs); 1478 1479 sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, 1480 + sizeof(n)); 1481 + sctp_addto_chunk(*errp, sizeof(n), &n); 1482 *error = -SCTP_IERROR_STALE_COOKIE; 1483 } else 1484 *error = -SCTP_IERROR_NOMEM; ··· 1567 report.num_missing = htonl(1); 1568 report.type = paramtype; 1569 sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM, 1570 + sizeof(report)); 1571 + sctp_addto_chunk(*errp, sizeof(report), &report); 1572 } 1573 1574 /* Stop processing this chunk. */ ··· 1585 *errp = sctp_make_op_error_space(asoc, chunk, 0); 1586 1587 if (*errp) 1588 + sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0); 1589 1590 /* Stop processing this chunk. */ 1591 return 0; ··· 1606 *errp = sctp_make_op_error_space(asoc, chunk, payload_len); 1607 1608 if (*errp) { 1609 + sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, 1610 + sizeof(error) + sizeof(sctp_paramhdr_t)); 1611 + sctp_addto_chunk(*errp, sizeof(error), error); 1612 + sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); 1613 } 1614 1615 return 0; ··· 1629 if (!*errp) 1630 *errp = sctp_make_op_error_space(asoc, chunk, len); 1631 1632 + if (*errp) { 1633 + sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len); 1634 + sctp_addto_chunk(*errp, len, param.v); 1635 + } 1636 1637 /* Stop processing this chunk. */ 1638 return 0; ··· 1683 *errp = sctp_make_op_error_space(asoc, chunk, 1684 ntohs(chunk->chunk_hdr->length)); 1685 1686 + if (*errp) { 1687 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1688 WORD_ROUND(ntohs(param.p->length))); 1689 + sctp_addto_chunk(*errp, 1690 + WORD_ROUND(ntohs(param.p->length)), 1691 + param.v); 1692 + } 1693 1694 break; 1695 case SCTP_PARAM_ACTION_SKIP: ··· 1701 1702 if (*errp) { 1703 sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, 1704 WORD_ROUND(ntohs(param.p->length))); 1705 + sctp_addto_chunk(*errp, 1706 + WORD_ROUND(ntohs(param.p->length)), 1707 + param.v); 1708 } else { 1709 /* If there is no memory for generating the ERROR 1710 * report as specified, an ABORT will be triggered
+2 -2
net/sctp/sm_statefuns.c
··· 3362 abort = sctp_make_abort(asoc, asconf_ack, 3363 sizeof(sctp_errhdr_t)); 3364 if (abort) { 3365 - sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, NULL, 0); 3366 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3367 SCTP_CHUNK(abort)); 3368 } ··· 3392 abort = sctp_make_abort(asoc, asconf_ack, 3393 sizeof(sctp_errhdr_t)); 3394 if (abort) { 3395 - sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, NULL, 0); 3396 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3397 SCTP_CHUNK(abort)); 3398 }
··· 3362 abort = sctp_make_abort(asoc, asconf_ack, 3363 sizeof(sctp_errhdr_t)); 3364 if (abort) { 3365 + sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0); 3366 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3367 SCTP_CHUNK(abort)); 3368 } ··· 3392 abort = sctp_make_abort(asoc, asconf_ack, 3393 sizeof(sctp_errhdr_t)); 3394 if (abort) { 3395 + sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); 3396 sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, 3397 SCTP_CHUNK(abort)); 3398 }