sctp: Fix kernel panic while process protocol violation parameter
Since call to function sctp_sf_abort_violation() need paramter 'arg' with 'struct sctp_chunk' type, it will read the chunk type and chunk length from the chunk_hdr member of chunk. But call to sctp_sf_violation_paramlen() always with 'struct sctp_paramhdr' type's parameter, it will be passed to sctp_sf_abort_violation(). This may cause kernel panic. sctp_sf_violation_paramlen() |-- sctp_sf_abort_violation() |-- sctp_make_abort_violation() This patch fixed this problem. This patch also fix two place which called sctp_sf_violation_paramlen() with wrong paramter type. Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com> Signed-off-by: Vlad Yasevich <vladislav.yasevich@hp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
8b122efd13
commit
ba0166708e
@@ -119,7 +119,7 @@ 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,
|
||||
void *arg, void *ext,
|
||||
sctp_cmd_seq_t *commands);
|
||||
|
||||
static sctp_disposition_t sctp_sf_violation_ctsn(
|
||||
@@ -3425,7 +3425,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
|
||||
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,
|
||||
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
||||
(void *)addr_param, commands);
|
||||
|
||||
/* Verify the ASCONF chunk before processing it. */
|
||||
@@ -3433,8 +3433,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep,
|
||||
(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);
|
||||
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
||||
(void *)err_param, commands);
|
||||
|
||||
/* ADDIP 5.2 E1) Compare the value of the serial number to the value
|
||||
* the endpoint stored in a new association variable
|
||||
@@ -3542,8 +3542,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep,
|
||||
(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);
|
||||
return sctp_sf_violation_paramlen(ep, asoc, type, arg,
|
||||
(void *)err_param, commands);
|
||||
|
||||
if (last_asconf) {
|
||||
addip_hdr = (sctp_addiphdr_t *)last_asconf->subh.addip_hdr;
|
||||
@@ -4240,12 +4240,38 @@ 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 const char err_str[] = "The following parameter had invalid length:";
|
||||
void *arg, void *ext,
|
||||
sctp_cmd_seq_t *commands)
|
||||
{
|
||||
struct sctp_chunk *chunk = arg;
|
||||
struct sctp_paramhdr *param = ext;
|
||||
struct sctp_chunk *abort = NULL;
|
||||
|
||||
return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
|
||||
sizeof(err_str));
|
||||
if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc))
|
||||
goto discard;
|
||||
|
||||
/* Make the abort chunk. */
|
||||
abort = sctp_make_violation_paramlen(asoc, chunk, param);
|
||||
if (!abort)
|
||||
goto nomem;
|
||||
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
|
||||
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
|
||||
SCTP_ERROR(ECONNABORTED));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED,
|
||||
SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
|
||||
SCTP_DEC_STATS(SCTP_MIB_CURRESTAB);
|
||||
|
||||
discard:
|
||||
sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
|
||||
|
||||
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
|
||||
|
||||
return SCTP_DISPOSITION_ABORT;
|
||||
nomem:
|
||||
return SCTP_DISPOSITION_NOMEM;
|
||||
}
|
||||
|
||||
/* Handle a protocol violation when the peer trying to advance the
|
||||
|
Reference in New Issue
Block a user