Unverified Commit 4f5b3a4d authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!12790 slip: make slhc_remember() more robust against malicious packets

parents 25ac155a 64ab5469
Loading
Loading
Loading
Loading
+34 −23
Original line number Diff line number Diff line
@@ -643,25 +643,32 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
int
slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
{
	struct cstate *cs;
	unsigned ihl;

	const struct tcphdr *th;
	unsigned char index;
	struct iphdr *iph;
	struct cstate *cs;
	unsigned int ihl;

	if(isize < 20) {
		/* The packet is shorter than a legal IP header */
	/* The packet is shorter than a legal IP header.
	 * Also make sure isize is positive.
	 */
	if (isize < (int)sizeof(struct iphdr)) {
runt:
		comp->sls_i_runt++;
		return slhc_toss(comp);
	}
	iph = (struct iphdr *)icp;
	/* Peek at the IP header's IHL field to find its length */
	ihl = icp[0] & 0xf;
	if(ihl < 20 / 4){
		/* The IP header length field is too small */
		comp->sls_i_runt++;
		return slhc_toss( comp );
	}
	index = icp[9];
	icp[9] = IPPROTO_TCP;
	ihl = iph->ihl;
	/* The IP header length field is too small,
	 * or packet is shorter than the IP header followed
	 * by minimal tcp header.
	 */
	if (ihl < 5 || isize < ihl * 4 + sizeof(struct tcphdr))
		goto runt;

	index = iph->protocol;
	iph->protocol = IPPROTO_TCP;

	if (ip_fast_csum(icp, ihl)) {
		/* Bad IP header checksum; discard */
@@ -672,17 +679,21 @@ slhc_remember(struct slcompress *comp, unsigned char *icp, int isize)
		comp->sls_i_error++;
		return slhc_toss(comp);
	}

	th = (struct tcphdr *)(icp + ihl * 4);
	if (th->doff < sizeof(struct tcphdr) / 4)
		goto runt;
	if (isize < ihl * 4 + th->doff * 4)
		goto runt;
	/* Update local state */
	cs = &comp->rstate[comp->recv_current = index];
	comp->flags &=~ SLF_TOSS;
	memcpy(&cs->cs_ip,icp,20);
	memcpy(&cs->cs_tcp,icp + ihl*4,20);
	memcpy(&cs->cs_ip, iph, sizeof(*iph));
	memcpy(&cs->cs_tcp, th, sizeof(*th));
	if (ihl > 5)
	  memcpy(cs->cs_ipopt, icp + sizeof(struct iphdr), (ihl - 5) * 4);
	if (cs->cs_tcp.doff > 5)
	  memcpy(cs->cs_tcpopt, icp + ihl*4 + sizeof(struct tcphdr), (cs->cs_tcp.doff - 5) * 4);
	cs->cs_hsize = ihl*2 + cs->cs_tcp.doff*2;
	  memcpy(cs->cs_ipopt, &iph[1], (ihl - 5) * 4);
	if (th->doff > 5)
	  memcpy(cs->cs_tcpopt, &th[1], (th->doff - 5) * 4);
	cs->cs_hsize = ihl*2 + th->doff*2;
	cs->initialized = true;
	/* Put headers back on packet
	 * Neither header checksum is recalculated