Fixed
Created: Jun 19, 2014
Updated: Dec 3, 2018
Resolved Date: Sep 2, 2014
Previous ID: LIN4-31522
Found In Version: 6.0
Fix Version: 6.0.0.10
Severity: Standard
Applicable for: Wind River Linux 6
Component/s: Kernel
Issue:
A malformed SCTP-AUTH chunk is injected to system along with COOKIE-ECHO after INIT,INIT-ACK exchange.
The system reboots while processing the AUTH chunk.
Observation:
The HMAC field is malformed in the SCTP-AUTH chunk.
While processing the received AUTH chunk, it passes all the validation checks and while verifying the HMAC of the received AUTH chunk the system reboots.
Path: linux/net/sctp/ sm_statefuns.c
function: sctp_disposition_t sctp_sf_do_5_1D_ce
/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo
* is supposed to be authenticated and we have to do delayed
* authentication. We've just recreated the association using
* the information in the cookie and now it's much easier to
* do the authentication.
*/
if (chunk->auth_chunk) {
struct sctp_chunk auth;
sctp_ierror_t ret;
/* set-up our fake chunk so that we can process it */
auth.skb = chunk->auth_chunk;
auth.asoc = chunk->asoc;
auth.sctp_hdr = chunk->sctp_hdr;
auth.chunk_hdr = (sctp_chunkhdr_t *)skb_push(chunk->auth_chunk,
sizeof(sctp_chunkhdr_t));
skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t));
auth.transport = chunk->transport;
ret = sctp_sf_authenticate(ep, new_asoc, type, &auth);
/* We can now safely free the auth_chunk clone */
kfree_skb(chunk->auth_chunk);
if (ret != SCTP_IERROR_NO_ERROR) {
sctp_association_free(new_asoc);
return sctp_sf_pdiscard(ep, asoc, type, arg, commands);
}
}
Function: static sctp_ierror_t sctp_sf_authenticate
/* Now that we've done validation checks, we can compute and
* verify the hmac. The steps involved are:
* 1. Save the digest from the chunk.
* 2. Zero out the digest in the chunk.
* 3. Compute the new digest
* 4. Compare saved and new digests.
*/
digest = auth_hdr->hmac;
skb_pull(chunk->skb, sig_len);
save_digest = kmemdup(digest, sig_len, GFP_ATOMIC);
if (!save_digest)
goto nomem;
memset(digest, 0, sig_len);
sctp_auth_calculate_hmac(asoc, chunk->skb,
(struct sctp_auth_chunk *)chunk->chunk_hdr,
GFP_ATOMIC);
Path: linux/net/sctp/auth.c
Function: void sctp_auth_calculate_hmac
/* set up scatter list */
end = skb_tail_pointer(skb);
sg_init_one(&sg, auth, end - (unsigned char *)auth);
desc.tfm = asoc->ep->auth_hmacs[hmac_id];
desc.flags = 0;
digest = auth->auth_hdr.hmac;
if (crypto_hash_setkey(desc.tfm, &asoc_key->data[0], asoc_key->len))
goto free;
crypto_hash_digest(&desc, &sg, sg.length, digest);
Case 1: auth_enable is not set:
# cat /proc/sys/net/sctp/auth_enable
0
When the auth_enable is set to zero, asoc->ep->auth_hmacs would be NULL and hence the crash.
Case 2: auth_enable is set:
# cat /proc/sys/net/sctp/auth_enable
1
When auth_enable is set to value 1, asoc_key->data[0] would be NULL and hence the crash .
Could not capture the pcap file as the system reboots soon after processing the AUTH chunk,.
Test performed with Codenomicon tools - see attachements for more details.