Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 65172
b: refs/heads/master
c: 6f4c618
h: refs/heads/master
v: v3
  • Loading branch information
Wei Yongjun authored and David S. Miller committed Sep 26, 2007
1 parent ff35b66 commit 0cacc5d
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 3c77f961b55b6060858c68a213d7f4470d7f3eb2
refs/heads/master: 6f4c618ddb0e6b7e6d49cfc8134e694be1c0bc9b
3 changes: 3 additions & 0 deletions trunk/include/net/sctp/sm.h
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
int, __be16);
struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
union sctp_addr *addr);
int sctp_verify_asconf(const struct sctp_association *asoc,
struct sctp_paramhdr *param_hdr, void *chunk_end,
struct sctp_paramhdr **errp);
struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc,
struct sctp_chunk *asconf);
int sctp_process_asconf_ack(struct sctp_association *asoc,
Expand Down
1 change: 1 addition & 0 deletions trunk/include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ struct sctp_signed_cookie {
* internally.
*/
union sctp_addr_param {
struct sctp_paramhdr p;
struct sctp_ipv4addr_param v4;
struct sctp_ipv6addr_param v6;
};
Expand Down
46 changes: 46 additions & 0 deletions trunk/net/sctp/sm_make_chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -2499,6 +2499,52 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
return SCTP_ERROR_NO_ERROR;
}

/* Verify the ASCONF packet before we process it. */
int sctp_verify_asconf(const struct sctp_association *asoc,
struct sctp_paramhdr *param_hdr, void *chunk_end,
struct sctp_paramhdr **errp) {
sctp_addip_param_t *asconf_param;
union sctp_params param;
int length, plen;

param.v = (sctp_paramhdr_t *) param_hdr;
while (param.v <= chunk_end - sizeof(sctp_paramhdr_t)) {
length = ntohs(param.p->length);
*errp = param.p;

if (param.v > chunk_end - length ||
length < sizeof(sctp_paramhdr_t))
return 0;

switch (param.p->type) {
case SCTP_PARAM_ADD_IP:
case SCTP_PARAM_DEL_IP:
case SCTP_PARAM_SET_PRIMARY:
asconf_param = (sctp_addip_param_t *)param.v;
plen = ntohs(asconf_param->param_hdr.length);
if (plen < sizeof(sctp_addip_param_t) +
sizeof(sctp_paramhdr_t))
return 0;
break;
case SCTP_PARAM_SUCCESS_REPORT:
case SCTP_PARAM_ADAPTATION_LAYER_IND:
if (length != sizeof(sctp_addip_param_t))
return 0;

break;
default:
break;
}

param.v += WORD_ROUND(length);
}

if (param.v != chunk_end)
return 0;

return 1;
}

/* Process an incoming ASCONF chunk with the next expected serial no. and
* return an ASCONF_ACK chunk to be sent in response.
*/
Expand Down
50 changes: 50 additions & 0 deletions trunk/net/sctp/sm_statefuns.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,13 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
void *arg,
sctp_cmd_seq_t *commands);

static sctp_disposition_t sctp_sf_violation_paramlen(
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands);

static sctp_disposition_t sctp_sf_violation_ctsn(
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
Expand Down Expand Up @@ -3296,8 +3303,11 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
{
struct sctp_chunk *chunk = arg;
struct sctp_chunk *asconf_ack = NULL;
struct sctp_paramhdr *err_param = NULL;
sctp_addiphdr_t *hdr;
union sctp_addr_param *addr_param;
__u32 serial;
int length;

if (!sctp_vtag_verify(chunk, asoc)) {
sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG,
Expand All @@ -3313,6 +3323,20 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
hdr = (sctp_addiphdr_t *)chunk->skb->data;
serial = ntohl(hdr->serial);

addr_param = (union sctp_addr_param *)hdr->params;
length = ntohs(addr_param->p.length);
if (length < sizeof(sctp_paramhdr_t))
return sctp_sf_violation_paramlen(ep, asoc, type,
(void *)addr_param, commands);

/* Verify the ASCONF chunk before processing it. */
if (!sctp_verify_asconf(asoc,
(sctp_paramhdr_t *)((void *)addr_param + length),
(void *)chunk->chunk_end,
&err_param))
return sctp_sf_violation_paramlen(ep, asoc, type,
(void *)&err_param, commands);

/* ADDIP 4.2 C1) Compare the value of the serial number to the value
* the endpoint stored in a new association variable
* 'Peer-Serial-Number'.
Expand Down Expand Up @@ -3367,6 +3391,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
struct sctp_chunk *asconf_ack = arg;
struct sctp_chunk *last_asconf = asoc->addip_last_asconf;
struct sctp_chunk *abort;
struct sctp_paramhdr *err_param = NULL;
sctp_addiphdr_t *addip_hdr;
__u32 sent_serial, rcvd_serial;

Expand All @@ -3384,6 +3409,14 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data;
rcvd_serial = ntohl(addip_hdr->serial);

/* Verify the ASCONF-ACK chunk before processing it. */
if (!sctp_verify_asconf(asoc,
(sctp_paramhdr_t *)addip_hdr->params,
(void *)asconf_ack->chunk_end,
&err_param))
return sctp_sf_violation_paramlen(ep, asoc, type,
(void *)&err_param, commands);

if (last_asconf) {
addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
sent_serial = ntohl(addip_hdr->serial);
Expand Down Expand Up @@ -3870,6 +3903,23 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
sizeof(err_str));
}

/*
* Handle a protocol violation when the parameter length is invalid.
* "Invalid" length is identified as smaller then the minimal length a
* given parameter can be.
*/
static sctp_disposition_t sctp_sf_violation_paramlen(
const struct sctp_endpoint *ep,
const struct sctp_association *asoc,
const sctp_subtype_t type,
void *arg,
sctp_cmd_seq_t *commands) {
char err_str[] = "The following parameter had invalid length:";

return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
sizeof(err_str));
}

/* Handle a protocol violation when the peer trying to advance the
* cumulative tsn ack to a point beyond the max tsn currently sent.
*
Expand Down

0 comments on commit 0cacc5d

Please sign in to comment.