Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
* 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6: [PPP_MPPE]: Don't put InterimKey on the stack SCTP : Add paramters validity check for ASCONF chunk SCTP: Discard OOTB packetes with bundled INIT early. SCTP: Clean up OOTB handling and fix infinite loop processing SCTP: Explicitely discard OOTB chunks SCTP: Send ABORT chunk with correct tag in response to INIT ACK SCTP: Validate buffer room when processing sequential chunks [PATCH] mac80211: fix initialisation when built-in [PATCH] net/mac80211/wme.c: fix sparse warning [PATCH] cfg80211: fix initialisation if built-in [PATCH] net/wireless/sysfs.c: Shut up build warning
This commit is contained in:
commit
d85f57938a
|
@ -136,7 +136,7 @@ struct ppp_mppe_state {
|
|||
* Key Derivation, from RFC 3078, RFC 3079.
|
||||
* Equivalent to Get_Key() for MS-CHAP as described in RFC 3079.
|
||||
*/
|
||||
static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *InterimKey)
|
||||
static void get_new_key_from_sha(struct ppp_mppe_state * state)
|
||||
{
|
||||
struct hash_desc desc;
|
||||
struct scatterlist sg[4];
|
||||
|
@ -153,8 +153,6 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *I
|
|||
desc.flags = 0;
|
||||
|
||||
crypto_hash_digest(&desc, sg, nbytes, state->sha1_digest);
|
||||
|
||||
memcpy(InterimKey, state->sha1_digest, state->keylen);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -163,21 +161,21 @@ static void get_new_key_from_sha(struct ppp_mppe_state * state, unsigned char *I
|
|||
*/
|
||||
static void mppe_rekey(struct ppp_mppe_state * state, int initial_key)
|
||||
{
|
||||
unsigned char InterimKey[MPPE_MAX_KEY_LEN];
|
||||
struct scatterlist sg_in[1], sg_out[1];
|
||||
struct blkcipher_desc desc = { .tfm = state->arc4 };
|
||||
|
||||
get_new_key_from_sha(state, InterimKey);
|
||||
get_new_key_from_sha(state);
|
||||
if (!initial_key) {
|
||||
crypto_blkcipher_setkey(state->arc4, InterimKey, state->keylen);
|
||||
setup_sg(sg_in, InterimKey, state->keylen);
|
||||
crypto_blkcipher_setkey(state->arc4, state->sha1_digest,
|
||||
state->keylen);
|
||||
setup_sg(sg_in, state->sha1_digest, state->keylen);
|
||||
setup_sg(sg_out, state->session_key, state->keylen);
|
||||
if (crypto_blkcipher_encrypt(&desc, sg_out, sg_in,
|
||||
state->keylen) != 0) {
|
||||
printk(KERN_WARNING "mppe_rekey: cipher_encrypt failed\n");
|
||||
}
|
||||
} else {
|
||||
memcpy(state->session_key, InterimKey, state->keylen);
|
||||
memcpy(state->session_key, state->sha1_digest, state->keylen);
|
||||
}
|
||||
if (state->keylen == 8) {
|
||||
/* See RFC 3078 */
|
||||
|
|
|
@ -114,7 +114,6 @@ sctp_state_fn_t sctp_sf_do_4_C;
|
|||
sctp_state_fn_t sctp_sf_eat_data_6_2;
|
||||
sctp_state_fn_t sctp_sf_eat_data_fast_4_4;
|
||||
sctp_state_fn_t sctp_sf_eat_sack_6_2;
|
||||
sctp_state_fn_t sctp_sf_tabort_8_4_8;
|
||||
sctp_state_fn_t sctp_sf_operr_notify;
|
||||
sctp_state_fn_t sctp_sf_t1_init_timer_expire;
|
||||
sctp_state_fn_t sctp_sf_t1_cookie_timer_expire;
|
||||
|
@ -247,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,
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -5259,7 +5259,7 @@ static void __exit ieee80211_exit(void)
|
|||
}
|
||||
|
||||
|
||||
module_init(ieee80211_init);
|
||||
subsys_initcall(ieee80211_init);
|
||||
module_exit(ieee80211_exit);
|
||||
|
||||
MODULE_DESCRIPTION("IEEE 802.11 subsystem");
|
||||
|
|
|
@ -431,7 +431,7 @@ static void __exit rate_control_simple_exit(void)
|
|||
}
|
||||
|
||||
|
||||
module_init(rate_control_simple_init);
|
||||
subsys_initcall(rate_control_simple_init);
|
||||
module_exit(rate_control_simple_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
|
||||
|
|
|
@ -424,7 +424,7 @@ static int wme_qdiscop_init(struct Qdisc *qd, struct rtattr *opt)
|
|||
skb_queue_head_init(&q->requeued[i]);
|
||||
q->queues[i] = qdisc_create_dflt(qd->dev, &pfifo_qdisc_ops,
|
||||
qd->handle);
|
||||
if (q->queues[i] == 0) {
|
||||
if (!q->queues[i]) {
|
||||
q->queues[i] = &noop_qdisc;
|
||||
printk(KERN_ERR "%s child qdisc %i creation failed", dev->name, i);
|
||||
}
|
||||
|
|
|
@ -622,6 +622,14 @@ static int sctp_rcv_ootb(struct sk_buff *skb)
|
|||
if (SCTP_CID_SHUTDOWN_COMPLETE == ch->type)
|
||||
goto discard;
|
||||
|
||||
/* RFC 4460, 2.11.2
|
||||
* This will discard packets with INIT chunk bundled as
|
||||
* subsequent chunks in the packet. When INIT is first,
|
||||
* the normal INIT processing will discard the chunk.
|
||||
*/
|
||||
if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data)
|
||||
goto discard;
|
||||
|
||||
/* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR
|
||||
* or a COOKIE ACK the SCTP Packet should be silently
|
||||
* discarded.
|
||||
|
|
|
@ -130,6 +130,14 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue)
|
|||
/* Force chunk->skb->data to chunk->chunk_end. */
|
||||
skb_pull(chunk->skb,
|
||||
chunk->chunk_end - chunk->skb->data);
|
||||
|
||||
/* Verify that we have at least chunk headers
|
||||
* worth of buffer left.
|
||||
*/
|
||||
if (skb_headlen(chunk->skb) < sizeof(sctp_chunkhdr_t)) {
|
||||
sctp_chunk_free(chunk);
|
||||
chunk = queue->in_progress = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -90,6 +90,11 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
|
|||
const sctp_subtype_t type,
|
||||
void *arg,
|
||||
sctp_cmd_seq_t *commands);
|
||||
static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
|
||||
const struct sctp_association *asoc,
|
||||
const sctp_subtype_t type,
|
||||
void *arg,
|
||||
sctp_cmd_seq_t *commands);
|
||||
static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk);
|
||||
|
||||
static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
|
||||
|
@ -98,6 +103,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands,
|
|||
struct sctp_transport *transport);
|
||||
|
||||
static sctp_disposition_t sctp_sf_abort_violation(
|
||||
const struct sctp_endpoint *ep,
|
||||
const struct sctp_association *asoc,
|
||||
void *arg,
|
||||
sctp_cmd_seq_t *commands,
|
||||
|
@ -111,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,
|
||||
|
@ -118,6 +131,13 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
|
|||
void *arg,
|
||||
sctp_cmd_seq_t *commands);
|
||||
|
||||
static sctp_disposition_t sctp_sf_violation_chunk(
|
||||
const struct sctp_endpoint *ep,
|
||||
const struct sctp_association *asoc,
|
||||
const sctp_subtype_t type,
|
||||
void *arg,
|
||||
sctp_cmd_seq_t *commands);
|
||||
|
||||
/* Small helper function that checks if the chunk length
|
||||
* is of the appropriate length. The 'required_length' argument
|
||||
* is set to be the size of a specific chunk we are testing.
|
||||
|
@ -181,16 +201,21 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep,
|
|||
struct sctp_chunk *chunk = arg;
|
||||
struct sctp_ulpevent *ev;
|
||||
|
||||
if (!sctp_vtag_verify_either(chunk, asoc))
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
|
||||
/* RFC 2960 6.10 Bundling
|
||||
*
|
||||
* An endpoint MUST NOT bundle INIT, INIT ACK or
|
||||
* SHUTDOWN COMPLETE with any other chunks.
|
||||
*/
|
||||
if (!chunk->singleton)
|
||||
return SCTP_DISPOSITION_VIOLATION;
|
||||
return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);
|
||||
|
||||
if (!sctp_vtag_verify_either(chunk, asoc))
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
/* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
/* RFC 2960 10.2 SCTP-to-ULP
|
||||
*
|
||||
|
@ -450,17 +475,17 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep,
|
|||
if (!sctp_vtag_verify(chunk, asoc))
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
|
||||
/* Make sure that the INIT-ACK chunk has a valid length */
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
/* 6.10 Bundling
|
||||
* An endpoint MUST NOT bundle INIT, INIT ACK or
|
||||
* SHUTDOWN COMPLETE with any other chunks.
|
||||
*/
|
||||
if (!chunk->singleton)
|
||||
return SCTP_DISPOSITION_VIOLATION;
|
||||
return sctp_sf_violation_chunk(ep, asoc, type, arg, commands);
|
||||
|
||||
/* Make sure that the INIT-ACK chunk has a valid length */
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
/* Grab the INIT header. */
|
||||
chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data;
|
||||
|
||||
|
@ -585,7 +610,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep,
|
|||
* control endpoint, respond with an ABORT.
|
||||
*/
|
||||
if (ep == sctp_sk((sctp_get_ctl_sock()))->ep)
|
||||
return sctp_sf_ootb(ep, asoc, type, arg, commands);
|
||||
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
|
||||
|
||||
/* Make sure that the COOKIE_ECHO chunk has a valid length.
|
||||
* In this case, we check that we have enough for at least a
|
||||
|
@ -2496,6 +2521,11 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep,
|
|||
struct sctp_chunk *chunk = (struct sctp_chunk *) arg;
|
||||
struct sctp_chunk *reply;
|
||||
|
||||
/* Make sure that the chunk has a valid length */
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
/* Since we are not going to really process this INIT, there
|
||||
* is no point in verifying chunk boundries. Just generate
|
||||
* the SHUTDOWN ACK.
|
||||
|
@ -2929,7 +2959,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep,
|
|||
*
|
||||
* The return value is the disposition of the chunk.
|
||||
*/
|
||||
sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
|
||||
static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
|
||||
const struct sctp_association *asoc,
|
||||
const sctp_subtype_t type,
|
||||
void *arg,
|
||||
|
@ -2965,6 +2995,7 @@ sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep,
|
|||
|
||||
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||
|
||||
sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
return SCTP_DISPOSITION_CONSUME;
|
||||
}
|
||||
|
||||
|
@ -3125,14 +3156,14 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
|
|||
|
||||
ch = (sctp_chunkhdr_t *) chunk->chunk_hdr;
|
||||
do {
|
||||
/* Break out if chunk length is less then minimal. */
|
||||
/* Report violation if the chunk is less then minimal */
|
||||
if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t))
|
||||
break;
|
||||
|
||||
ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
|
||||
if (ch_end > skb_tail_pointer(skb))
|
||||
break;
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
/* Now that we know we at least have a chunk header,
|
||||
* do things that are type appropriate.
|
||||
*/
|
||||
if (SCTP_CID_SHUTDOWN_ACK == ch->type)
|
||||
ootb_shut_ack = 1;
|
||||
|
||||
|
@ -3144,15 +3175,19 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep,
|
|||
if (SCTP_CID_ABORT == ch->type)
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
|
||||
/* Report violation if chunk len overflows */
|
||||
ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length));
|
||||
if (ch_end > skb_tail_pointer(skb))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
ch = (sctp_chunkhdr_t *) ch_end;
|
||||
} while (ch_end < skb_tail_pointer(skb));
|
||||
|
||||
if (ootb_shut_ack)
|
||||
sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands);
|
||||
return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands);
|
||||
else
|
||||
sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
|
||||
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -3218,7 +3253,11 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep,
|
|||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
|
||||
return SCTP_DISPOSITION_CONSUME;
|
||||
/* We need to discard the rest of the packet to prevent
|
||||
* potential bomming attacks from additional bundled chunks.
|
||||
* This is documented in SCTP Threats ID.
|
||||
*/
|
||||
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
|
||||
}
|
||||
|
||||
return SCTP_DISPOSITION_NOMEM;
|
||||
|
@ -3241,6 +3280,13 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep,
|
|||
void *arg,
|
||||
sctp_cmd_seq_t *commands)
|
||||
{
|
||||
struct sctp_chunk *chunk = arg;
|
||||
|
||||
/* Make sure that the SHUTDOWN_ACK chunk has a valid length. */
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
/* Although we do have an association in this case, it corresponds
|
||||
* to a restarted association. So the packet is treated as an OOTB
|
||||
* packet and the state function that handles OOTB SHUTDOWN_ACK is
|
||||
|
@ -3257,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,
|
||||
|
@ -3274,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'.
|
||||
|
@ -3328,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;
|
||||
|
||||
|
@ -3345,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);
|
||||
|
@ -3655,6 +3727,16 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep,
|
|||
void *arg,
|
||||
sctp_cmd_seq_t *commands)
|
||||
{
|
||||
struct sctp_chunk *chunk = arg;
|
||||
|
||||
/* Make sure that the chunk has a valid length.
|
||||
* Since we don't know the chunk type, we use a general
|
||||
* chunkhdr structure to make a comparison.
|
||||
*/
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk);
|
||||
return SCTP_DISPOSITION_DISCARD;
|
||||
}
|
||||
|
@ -3710,6 +3792,13 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
|
|||
void *arg,
|
||||
sctp_cmd_seq_t *commands)
|
||||
{
|
||||
struct sctp_chunk *chunk = arg;
|
||||
|
||||
/* Make sure that the chunk has a valid length. */
|
||||
if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t)))
|
||||
return sctp_sf_violation_chunklen(ep, asoc, type, arg,
|
||||
commands);
|
||||
|
||||
return SCTP_DISPOSITION_VIOLATION;
|
||||
}
|
||||
|
||||
|
@ -3717,12 +3806,14 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep,
|
|||
* Common function to handle a protocol violation.
|
||||
*/
|
||||
static sctp_disposition_t sctp_sf_abort_violation(
|
||||
const struct sctp_endpoint *ep,
|
||||
const struct sctp_association *asoc,
|
||||
void *arg,
|
||||
sctp_cmd_seq_t *commands,
|
||||
const __u8 *payload,
|
||||
const size_t paylen)
|
||||
{
|
||||
struct sctp_packet *packet = NULL;
|
||||
struct sctp_chunk *chunk = arg;
|
||||
struct sctp_chunk *abort = NULL;
|
||||
|
||||
|
@ -3731,30 +3822,51 @@ static sctp_disposition_t sctp_sf_abort_violation(
|
|||
if (!abort)
|
||||
goto nomem;
|
||||
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
|
||||
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||
if (asoc) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
|
||||
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||
|
||||
if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
|
||||
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
|
||||
SCTP_ERROR(ECONNREFUSED));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
|
||||
SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
|
||||
if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) {
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP,
|
||||
SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR,
|
||||
SCTP_ERROR(ECONNREFUSED));
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_INIT_FAILED,
|
||||
SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION));
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
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);
|
||||
packet = sctp_ootb_pkt_new(asoc, chunk);
|
||||
|
||||
if (!packet)
|
||||
goto nomem_pkt;
|
||||
|
||||
if (sctp_test_T_bit(abort))
|
||||
packet->vtag = ntohl(chunk->sctp_hdr->vtag);
|
||||
|
||||
abort->skb->sk = ep->base.sk;
|
||||
|
||||
sctp_packet_append_chunk(packet, abort);
|
||||
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT,
|
||||
SCTP_PACKET(packet));
|
||||
|
||||
SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS);
|
||||
}
|
||||
|
||||
sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL());
|
||||
sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands);
|
||||
|
||||
SCTP_INC_STATS(SCTP_MIB_ABORTEDS);
|
||||
|
||||
return SCTP_DISPOSITION_ABORT;
|
||||
|
||||
nomem_pkt:
|
||||
sctp_chunk_free(abort);
|
||||
nomem:
|
||||
return SCTP_DISPOSITION_NOMEM;
|
||||
}
|
||||
|
@ -3787,7 +3899,24 @@ static sctp_disposition_t sctp_sf_violation_chunklen(
|
|||
{
|
||||
char err_str[]="The following chunk had invalid length:";
|
||||
|
||||
return sctp_sf_abort_violation(asoc, arg, commands, err_str,
|
||||
return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
|
||||
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));
|
||||
}
|
||||
|
||||
|
@ -3806,10 +3935,31 @@ static sctp_disposition_t sctp_sf_violation_ctsn(
|
|||
{
|
||||
char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:";
|
||||
|
||||
return sctp_sf_abort_violation(asoc, arg, commands, err_str,
|
||||
return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
|
||||
sizeof(err_str));
|
||||
}
|
||||
|
||||
/* Handle protocol violation of an invalid chunk bundling. For example,
|
||||
* when we have an association and we recieve bundled INIT-ACK, or
|
||||
* SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle"
|
||||
* statement from the specs. Additinally, there might be an attacker
|
||||
* on the path and we may not want to continue this communication.
|
||||
*/
|
||||
static sctp_disposition_t sctp_sf_violation_chunk(
|
||||
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 chunk violates protocol:";
|
||||
|
||||
if (!asoc)
|
||||
return sctp_sf_violation(ep, asoc, type, arg, commands);
|
||||
|
||||
return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str,
|
||||
sizeof(err_str));
|
||||
}
|
||||
/***************************************************************************
|
||||
* These are the state functions for handling primitive (Section 10) events.
|
||||
***************************************************************************/
|
||||
|
@ -5176,7 +5326,22 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc
|
|||
* association exists, otherwise, use the peer's vtag.
|
||||
*/
|
||||
if (asoc) {
|
||||
vtag = asoc->peer.i.init_tag;
|
||||
/* Special case the INIT-ACK as there is no peer's vtag
|
||||
* yet.
|
||||
*/
|
||||
switch(chunk->chunk_hdr->type) {
|
||||
case SCTP_CID_INIT_ACK:
|
||||
{
|
||||
sctp_initack_chunk_t *initack;
|
||||
|
||||
initack = (sctp_initack_chunk_t *)chunk->chunk_hdr;
|
||||
vtag = ntohl(initack->init_hdr.init_tag);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
vtag = asoc->peer.i.init_tag;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Special case the INIT and stale COOKIE_ECHO as there is no
|
||||
* vtag yet.
|
||||
|
|
|
@ -110,7 +110,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -173,7 +173,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -194,7 +194,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -216,7 +216,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_violation), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -258,7 +258,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -300,7 +300,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type,
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -499,7 +499,7 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_
|
|||
/* SCTP_STATE_EMPTY */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_CLOSED */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8), \
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb), \
|
||||
/* SCTP_STATE_COOKIE_WAIT */ \
|
||||
TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \
|
||||
/* SCTP_STATE_COOKIE_ECHOED */ \
|
||||
|
@ -528,7 +528,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = {
|
|||
/* SCTP_STATE_EMPTY */
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb),
|
||||
/* SCTP_STATE_CLOSED */
|
||||
TYPE_SCTP_FUNC(sctp_sf_tabort_8_4_8),
|
||||
TYPE_SCTP_FUNC(sctp_sf_ootb),
|
||||
/* SCTP_STATE_COOKIE_WAIT */
|
||||
TYPE_SCTP_FUNC(sctp_sf_unk_chunk),
|
||||
/* SCTP_STATE_COOKIE_ECHOED */
|
||||
|
|
|
@ -213,7 +213,7 @@ out_fail_notifier:
|
|||
out_fail_sysfs:
|
||||
return err;
|
||||
}
|
||||
module_init(cfg80211_init);
|
||||
subsys_initcall(cfg80211_init);
|
||||
|
||||
static void cfg80211_exit(void)
|
||||
{
|
||||
|
|
|
@ -52,12 +52,14 @@ static void wiphy_dev_release(struct device *dev)
|
|||
cfg80211_dev_free(rdev);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
static int wiphy_uevent(struct device *dev, char **envp,
|
||||
int num_envp, char *buf, int size)
|
||||
{
|
||||
/* TODO, we probably need stuff here */
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct class ieee80211_class = {
|
||||
.name = "ieee80211",
|
||||
|
|
Loading…
Reference in New Issue