diff options
author | Wei Yongjun <yjwei@cn.fujitsu.com> | 2007-08-21 03:50:01 -0400 |
---|---|---|
committer | Vlad Yasevich <vladislav.yasevich@hp.com> | 2007-08-30 13:50:48 -0400 |
commit | 00f1c2df2a1c4903f4daa1333bafeb6dcbc9591d (patch) | |
tree | 61e9da42f580f7f120bac8c7cbeab39f2a0311ab | |
parent | 8d614ade511fef11f992d6a73e538d33b3b81f12 (diff) |
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>
-rw-r--r-- | include/net/sctp/sm.h | 2 | ||||
-rw-r--r-- | include/net/sctp/structs.h | 1 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 73 | ||||
-rw-r--r-- | net/sctp/sm_statefuns.c | 4 |
4 files changed, 56 insertions, 24 deletions
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h index 73cb9943c8a8..991c85bb9e36 100644 --- a/include/net/sctp/sm.h +++ b/include/net/sctp/sm.h | |||
@@ -214,7 +214,7 @@ struct sctp_chunk *sctp_make_shutdown_ack(const struct sctp_association *asoc, | |||
214 | const struct sctp_chunk *); | 214 | const struct sctp_chunk *); |
215 | struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, | 215 | struct sctp_chunk *sctp_make_shutdown_complete(const struct sctp_association *, |
216 | const struct sctp_chunk *); | 216 | const struct sctp_chunk *); |
217 | void sctp_init_cause(struct sctp_chunk *, __be16 cause, const void *, size_t); | 217 | void sctp_init_cause(struct sctp_chunk *, __be16 cause, size_t); |
218 | struct sctp_chunk *sctp_make_abort(const struct sctp_association *, | 218 | struct sctp_chunk *sctp_make_abort(const struct sctp_association *, |
219 | const struct sctp_chunk *, | 219 | const struct sctp_chunk *, |
220 | const size_t hint); | 220 | const size_t hint); |
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index ee4559b11302..c0d5848c33dc 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -726,6 +726,7 @@ int sctp_user_addto_chunk(struct sctp_chunk *chunk, int off, int len, | |||
726 | struct iovec *data); | 726 | struct iovec *data); |
727 | void sctp_chunk_free(struct sctp_chunk *); | 727 | void sctp_chunk_free(struct sctp_chunk *); |
728 | void *sctp_addto_chunk(struct sctp_chunk *, int len, const void *data); | 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); | ||
729 | struct sctp_chunk *sctp_chunkify(struct sk_buff *, | 730 | struct sctp_chunk *sctp_chunkify(struct sk_buff *, |
730 | const struct sctp_association *, | 731 | const struct sctp_association *, |
731 | struct sock *); | 732 | struct sock *); |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 93df833f34f4..adc5e5934728 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -110,7 +110,7 @@ static const struct sctp_paramhdr prsctp_param = { | |||
110 | * abort chunk. | 110 | * abort chunk. |
111 | */ | 111 | */ |
112 | void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, | 112 | void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, |
113 | const void *payload, size_t paylen) | 113 | size_t paylen) |
114 | { | 114 | { |
115 | sctp_errhdr_t err; | 115 | sctp_errhdr_t err; |
116 | __u16 len; | 116 | __u16 len; |
@@ -120,7 +120,6 @@ void sctp_init_cause(struct sctp_chunk *chunk, __be16 cause_code, | |||
120 | len = sizeof(sctp_errhdr_t) + paylen; | 120 | len = sizeof(sctp_errhdr_t) + paylen; |
121 | err.length = htons(len); | 121 | err.length = htons(len); |
122 | chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); | 122 | chunk->subh.err_hdr = sctp_addto_chunk(chunk, sizeof(sctp_errhdr_t), &err); |
123 | sctp_addto_chunk(chunk, paylen, payload); | ||
124 | } | 123 | } |
125 | 124 | ||
126 | /* 3.3.2 Initiation (INIT) (1) | 125 | /* 3.3.2 Initiation (INIT) (1) |
@@ -780,8 +779,8 @@ struct sctp_chunk *sctp_make_abort_no_data( | |||
780 | 779 | ||
781 | /* Put the tsn back into network byte order. */ | 780 | /* Put the tsn back into network byte order. */ |
782 | payload = htonl(tsn); | 781 | payload = htonl(tsn); |
783 | sctp_init_cause(retval, SCTP_ERROR_NO_DATA, (const void *)&payload, | 782 | sctp_init_cause(retval, SCTP_ERROR_NO_DATA, sizeof(payload)); |
784 | sizeof(payload)); | 783 | sctp_addto_chunk(retval, sizeof(payload), (const void *)&payload); |
785 | 784 | ||
786 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints | 785 | /* RFC 2960 6.4 Multi-homed SCTP Endpoints |
787 | * | 786 | * |
@@ -823,7 +822,8 @@ struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc, | |||
823 | goto err_copy; | 822 | goto err_copy; |
824 | } | 823 | } |
825 | 824 | ||
826 | sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen); | 825 | sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, paylen); |
826 | sctp_addto_chunk(retval, paylen, payload); | ||
827 | 827 | ||
828 | if (paylen) | 828 | if (paylen) |
829 | kfree(payload); | 829 | kfree(payload); |
@@ -850,15 +850,17 @@ struct sctp_chunk *sctp_make_abort_violation( | |||
850 | struct sctp_paramhdr phdr; | 850 | struct sctp_paramhdr phdr; |
851 | 851 | ||
852 | retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen | 852 | retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen |
853 | + sizeof(sctp_chunkhdr_t)); | 853 | + sizeof(sctp_paramhdr_t)); |
854 | if (!retval) | 854 | if (!retval) |
855 | goto end; | 855 | goto end; |
856 | 856 | ||
857 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, payload, paylen); | 857 | sctp_init_cause(retval, SCTP_ERROR_PROTO_VIOLATION, paylen |
858 | + sizeof(sctp_paramhdr_t)); | ||
858 | 859 | ||
859 | phdr.type = htons(chunk->chunk_hdr->type); | 860 | phdr.type = htons(chunk->chunk_hdr->type); |
860 | phdr.length = chunk->chunk_hdr->length; | 861 | phdr.length = chunk->chunk_hdr->length; |
861 | sctp_addto_chunk(retval, sizeof(sctp_paramhdr_t), &phdr); | 862 | sctp_addto_chunk(retval, paylen, payload); |
863 | sctp_addto_param(retval, sizeof(sctp_paramhdr_t), &phdr); | ||
862 | 864 | ||
863 | end: | 865 | end: |
864 | return retval; | 866 | return retval; |
@@ -955,7 +957,8 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *asoc, | |||
955 | if (!retval) | 957 | if (!retval) |
956 | goto nodata; | 958 | goto nodata; |
957 | 959 | ||
958 | sctp_init_cause(retval, cause_code, payload, paylen); | 960 | sctp_init_cause(retval, cause_code, paylen); |
961 | sctp_addto_chunk(retval, paylen, payload); | ||
959 | 962 | ||
960 | nodata: | 963 | nodata: |
961 | return retval; | 964 | return retval; |
@@ -1143,6 +1146,25 @@ void *sctp_addto_chunk(struct sctp_chunk *chunk, int len, const void *data) | |||
1143 | return target; | 1146 | return target; |
1144 | } | 1147 | } |
1145 | 1148 | ||
1149 | /* Append bytes to the end of a parameter. Will panic if chunk is not big | ||
1150 | * enough. | ||
1151 | */ | ||
1152 | void *sctp_addto_param(struct sctp_chunk *chunk, int len, const void *data) | ||
1153 | { | ||
1154 | void *target; | ||
1155 | int chunklen = ntohs(chunk->chunk_hdr->length); | ||
1156 | |||
1157 | target = skb_put(chunk->skb, len); | ||
1158 | |||
1159 | memcpy(target, data, len); | ||
1160 | |||
1161 | /* Adjust the chunk length field. */ | ||
1162 | chunk->chunk_hdr->length = htons(chunklen + len); | ||
1163 | chunk->chunk_end = skb_tail_pointer(chunk->skb); | ||
1164 | |||
1165 | return target; | ||
1166 | } | ||
1167 | |||
1146 | /* Append bytes from user space to the end of a chunk. Will panic if | 1168 | /* Append bytes from user space to the end of a chunk. Will panic if |
1147 | * chunk is not big enough. | 1169 | * chunk is not big enough. |
1148 | * Returns a kernel err value. | 1170 | * Returns a kernel err value. |
@@ -1477,7 +1499,8 @@ no_hmac: | |||
1477 | __be32 n = htonl(usecs); | 1499 | __be32 n = htonl(usecs); |
1478 | 1500 | ||
1479 | sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, | 1501 | sctp_init_cause(*errp, SCTP_ERROR_STALE_COOKIE, |
1480 | &n, sizeof(n)); | 1502 | sizeof(n)); |
1503 | sctp_addto_chunk(*errp, sizeof(n), &n); | ||
1481 | *error = -SCTP_IERROR_STALE_COOKIE; | 1504 | *error = -SCTP_IERROR_STALE_COOKIE; |
1482 | } else | 1505 | } else |
1483 | *error = -SCTP_IERROR_NOMEM; | 1506 | *error = -SCTP_IERROR_NOMEM; |
@@ -1567,7 +1590,8 @@ static int sctp_process_missing_param(const struct sctp_association *asoc, | |||
1567 | report.num_missing = htonl(1); | 1590 | report.num_missing = htonl(1); |
1568 | report.type = paramtype; | 1591 | report.type = paramtype; |
1569 | sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM, | 1592 | sctp_init_cause(*errp, SCTP_ERROR_MISS_PARAM, |
1570 | &report, sizeof(report)); | 1593 | sizeof(report)); |
1594 | sctp_addto_chunk(*errp, sizeof(report), &report); | ||
1571 | } | 1595 | } |
1572 | 1596 | ||
1573 | /* Stop processing this chunk. */ | 1597 | /* Stop processing this chunk. */ |
@@ -1585,7 +1609,7 @@ static int sctp_process_inv_mandatory(const struct sctp_association *asoc, | |||
1585 | *errp = sctp_make_op_error_space(asoc, chunk, 0); | 1609 | *errp = sctp_make_op_error_space(asoc, chunk, 0); |
1586 | 1610 | ||
1587 | if (*errp) | 1611 | if (*errp) |
1588 | sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, NULL, 0); | 1612 | sctp_init_cause(*errp, SCTP_ERROR_INV_PARAM, 0); |
1589 | 1613 | ||
1590 | /* Stop processing this chunk. */ | 1614 | /* Stop processing this chunk. */ |
1591 | return 0; | 1615 | return 0; |
@@ -1606,9 +1630,10 @@ static int sctp_process_inv_paramlength(const struct sctp_association *asoc, | |||
1606 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); | 1630 | *errp = sctp_make_op_error_space(asoc, chunk, payload_len); |
1607 | 1631 | ||
1608 | if (*errp) { | 1632 | if (*errp) { |
1609 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, error, | 1633 | sctp_init_cause(*errp, SCTP_ERROR_PROTO_VIOLATION, |
1610 | sizeof(error)); | 1634 | sizeof(error) + sizeof(sctp_paramhdr_t)); |
1611 | sctp_addto_chunk(*errp, sizeof(sctp_paramhdr_t), param); | 1635 | sctp_addto_chunk(*errp, sizeof(error), error); |
1636 | sctp_addto_param(*errp, sizeof(sctp_paramhdr_t), param); | ||
1612 | } | 1637 | } |
1613 | 1638 | ||
1614 | return 0; | 1639 | return 0; |
@@ -1629,9 +1654,10 @@ static int sctp_process_hn_param(const struct sctp_association *asoc, | |||
1629 | if (!*errp) | 1654 | if (!*errp) |
1630 | *errp = sctp_make_op_error_space(asoc, chunk, len); | 1655 | *errp = sctp_make_op_error_space(asoc, chunk, len); |
1631 | 1656 | ||
1632 | if (*errp) | 1657 | if (*errp) { |
1633 | sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, | 1658 | sctp_init_cause(*errp, SCTP_ERROR_DNS_FAILED, len); |
1634 | param.v, len); | 1659 | sctp_addto_chunk(*errp, len, param.v); |
1660 | } | ||
1635 | 1661 | ||
1636 | /* Stop processing this chunk. */ | 1662 | /* Stop processing this chunk. */ |
1637 | return 0; | 1663 | return 0; |
@@ -1683,10 +1709,13 @@ static int sctp_process_unk_param(const struct sctp_association *asoc, | |||
1683 | *errp = sctp_make_op_error_space(asoc, chunk, | 1709 | *errp = sctp_make_op_error_space(asoc, chunk, |
1684 | ntohs(chunk->chunk_hdr->length)); | 1710 | ntohs(chunk->chunk_hdr->length)); |
1685 | 1711 | ||
1686 | if (*errp) | 1712 | if (*errp) { |
1687 | sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, | 1713 | sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, |
1688 | param.v, | ||
1689 | WORD_ROUND(ntohs(param.p->length))); | 1714 | WORD_ROUND(ntohs(param.p->length))); |
1715 | sctp_addto_chunk(*errp, | ||
1716 | WORD_ROUND(ntohs(param.p->length)), | ||
1717 | param.v); | ||
1718 | } | ||
1690 | 1719 | ||
1691 | break; | 1720 | break; |
1692 | case SCTP_PARAM_ACTION_SKIP: | 1721 | case SCTP_PARAM_ACTION_SKIP: |
@@ -1701,8 +1730,10 @@ static int sctp_process_unk_param(const struct sctp_association *asoc, | |||
1701 | 1730 | ||
1702 | if (*errp) { | 1731 | if (*errp) { |
1703 | sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, | 1732 | sctp_init_cause(*errp, SCTP_ERROR_UNKNOWN_PARAM, |
1704 | param.v, | ||
1705 | WORD_ROUND(ntohs(param.p->length))); | 1733 | WORD_ROUND(ntohs(param.p->length))); |
1734 | sctp_addto_chunk(*errp, | ||
1735 | WORD_ROUND(ntohs(param.p->length)), | ||
1736 | param.v); | ||
1706 | } else { | 1737 | } else { |
1707 | /* If there is no memory for generating the ERROR | 1738 | /* If there is no memory for generating the ERROR |
1708 | * report as specified, an ABORT will be triggered | 1739 | * report as specified, an ABORT will be triggered |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 71cad56dd73f..350d47654720 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -3362,7 +3362,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3362 | abort = sctp_make_abort(asoc, asconf_ack, | 3362 | abort = sctp_make_abort(asoc, asconf_ack, |
3363 | sizeof(sctp_errhdr_t)); | 3363 | sizeof(sctp_errhdr_t)); |
3364 | if (abort) { | 3364 | if (abort) { |
3365 | sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, NULL, 0); | 3365 | sctp_init_cause(abort, SCTP_ERROR_ASCONF_ACK, 0); |
3366 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 3366 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
3367 | SCTP_CHUNK(abort)); | 3367 | SCTP_CHUNK(abort)); |
3368 | } | 3368 | } |
@@ -3392,7 +3392,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3392 | abort = sctp_make_abort(asoc, asconf_ack, | 3392 | abort = sctp_make_abort(asoc, asconf_ack, |
3393 | sizeof(sctp_errhdr_t)); | 3393 | sizeof(sctp_errhdr_t)); |
3394 | if (abort) { | 3394 | if (abort) { |
3395 | sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, NULL, 0); | 3395 | sctp_init_cause(abort, SCTP_ERROR_RSRC_LOW, 0); |
3396 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, | 3396 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, |
3397 | SCTP_CHUNK(abort)); | 3397 | SCTP_CHUNK(abort)); |
3398 | } | 3398 | } |