VYPR
Unrated severityNVD Advisory· Published May 27, 2026· Updated May 27, 2026

CVE-2026-45843

CVE-2026-45843

Description

In the Linux kernel, the following vulnerability has been resolved:

slip: bound decode() reads against the compressed packet length

slhc_uncompress() parses a VJ-compressed TCP header by advancing a pointer through the packet via decode() and pull16(). Neither helper bounds-checks against isize, and decode() masks its return with & 0xffff so it can never return the -1 that callers test for -- those error paths are dead code.

A short compressed frame whose change byte requests optional fields lets decode() read past the end of the packet. The over-read bytes are folded into the cached cstate and reflected into subsequent reconstructed packets.

Make decode() and pull16() take the packet end pointer and return -1 when exhausted. Add a bounds check before the TCP-checksum read. The existing == -1 tests now do what they were always meant to.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

A bounds-checking flaw in Linux kernel's slip driver allows VJ-compressed packet decoding to read past buffer end, leaking cached state.

Vulnerability

The decode() and pull16() functions in the Linux kernel's slip driver (drivers/net/slip/slhc.c) do not perform bounds checking against the compressed packet length (isize) when parsing VJ-compressed TCP headers. decode() masks its return with & 0xffff so it can never return -1, making the error checks in callers dead code. A short compressed frame with a change byte requesting optional fields can cause decode() to read past the end of the packet. This affects all kernel versions prior to the fix commit 0511ecb00e61 (introduced in the 2026-05-27 stable update). [1]

Exploitation

An attacker needs to send a specially crafted VJ-compressed SLIP packet with a short payload that triggers the parsing of optional fields beyond the actual packet length. No authentication is required beyond network access to the SLIP interface. The attacker crafts a compressed frame where the change byte indicates optional fields, causing decode() to read bytes from out-of-bounds memory. The over-read bytes are folded into the cached compression state (cstate) on the receiving side. [1]

Impact

An attacker can inject arbitrary data from adjacent kernel memory into the cached compression state. This corrupted state is then used to reconstruct subsequent uncompressed packets, potentially leaking sensitive kernel memory contents into the data stream visible to the receiver or causing incorrect decompression. The impact is information disclosure (confidentiality breach) and possible integrity compromise of reconstructed network traffic. [1]

Mitigation

The fix is included in Linux kernel stable update 0511ecb00e61bf28e2fec4bb41fcce385c3a3b2d, which makes decode() and pull16() take the packet end pointer and return -1 when exhausted, and adds a bounds check before the TCP-checksum read. Users should apply the kernel update for their distribution. No workaround exists; disabling VJ compression on SLIP interfaces may reduce risk but is not a complete mitigation. The vulnerability is not listed in CISA's KEV as of the publication date. [1]

AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected products

1

Patches

10
4c1367a2d7aa

slip: bound decode() reads against the compressed packet length

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWeiming ShiApr 16, 2026Fixed in 7.1-rc1via kernel-cna
1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index e18a4213d10cec..1a9b27d5e256b9 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
37537e42e6df

slip: bound decode() reads against the compressed packet length

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWeiming ShiApr 16, 2026Fixed in 6.6.141via kernel-cna
1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index 3474792a37a677..ef586ab250747a 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <asm/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
4cefe3263993

slip: bound decode() reads against the compressed packet length

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWeiming ShiApr 16, 2026Fixed in 6.12.91via kernel-cna
1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index fcb3eebe7311c6..daf086c283423c 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
d42bec6e4f6d

slip: bound decode() reads against the compressed packet length

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWeiming ShiApr 16, 2026Fixed in 7.0.10via kernel-cna
1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index e18a4213d10cec..1a9b27d5e256b9 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
0511ecb00e61

slip: bound decode() reads against the compressed packet length

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.gitWeiming ShiApr 16, 2026Fixed in 6.18.33via kernel-cna
1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index fcb3eebe7311c6..daf086c283423c 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
0511ecb00e61

slip: bound decode() reads against the compressed packet length

1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index fcb3eebe7311c6..daf086c283423c 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
37537e42e6df

slip: bound decode() reads against the compressed packet length

1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index 3474792a37a677..ef586ab250747a 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <asm/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
4cefe3263993

slip: bound decode() reads against the compressed packet length

1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index fcb3eebe7311c6..daf086c283423c 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
4c1367a2d7aa

slip: bound decode() reads against the compressed packet length

1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index e18a4213d10cec..1a9b27d5e256b9 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    
d42bec6e4f6d

slip: bound decode() reads against the compressed packet length

1 file changed · +25 19
  • drivers/net/slip/slhc.c+25 19 modified
    diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
    index e18a4213d10cec..1a9b27d5e256b9 100644
    --- a/drivers/net/slip/slhc.c
    +++ b/drivers/net/slip/slhc.c
    @@ -80,9 +80,9 @@
     #include <linux/unaligned.h>
     
     static unsigned char *encode(unsigned char *cp, unsigned short n);
    -static long decode(unsigned char **cpp);
    +static long decode(unsigned char **cpp, const unsigned char *end);
     static unsigned char * put16(unsigned char *cp, unsigned short x);
    -static unsigned short pull16(unsigned char **cpp);
    +static long pull16(unsigned char **cpp, const unsigned char *end);
     
     /* Allocate compression data structure
      *	slots must be in range 0 to 255 (zero meaning no compression)
    @@ -190,30 +190,34 @@ encode(unsigned char *cp, unsigned short n)
     	return cp;
     }
     
    -/* Pull a 16-bit integer in host order from buffer in network byte order */
    -static unsigned short
    -pull16(unsigned char **cpp)
    +/* Pull a 16-bit integer in host order from buffer in network byte order.
    + * Returns -1 if the buffer is exhausted, otherwise the 16-bit value.
    + */
    +static long
    +pull16(unsigned char **cpp, const unsigned char *end)
     {
    -	short rval;
    +	long rval;
     
    +	if (*cpp + 2 > end)
    +		return -1;
     	rval = *(*cpp)++;
     	rval <<= 8;
     	rval |= *(*cpp)++;
     	return rval;
     }
     
    -/* Decode a number */
    +/* Decode a number. Returns -1 if the buffer is exhausted. */
     static long
    -decode(unsigned char **cpp)
    +decode(unsigned char **cpp, const unsigned char *end)
     {
     	int x;
     
    +	if (*cpp >= end)
    +		return -1;
     	x = *(*cpp)++;
    -	if(x == 0){
    -		return pull16(cpp) & 0xffff;	/* pull16 returns -1 on error */
    -	} else {
    -		return x & 0xff;		/* -1 if PULLCHAR returned error */
    -	}
    +	if (x == 0)
    +		return pull16(cpp, end);
    +	return x & 0xff;
     }
     
     /*
    @@ -499,6 +503,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	struct cstate *cs;
     	int len, hdrlen;
     	unsigned char *cp = icp;
    +	const unsigned char *end = icp + isize;
     
     	/* We've got a compressed packet; read the change byte */
     	comp->sls_i_compressed++;
    @@ -536,6 +541,8 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	thp = &cs->cs_tcp;
     	ip = &cs->cs_ip;
     
    +	if (cp + 2 > end)
    +		goto bad;
     	thp->check = *(__sum16 *)cp;
     	cp += 2;
     
    @@ -566,26 +573,26 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     	default:
     		if(changes & NEW_U){
     			thp->urg = 1;
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->urg_ptr = htons(x);
     		} else
     			thp->urg = 0;
     		if(changes & NEW_W){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->window = htons( ntohs(thp->window) + x);
     		}
     		if(changes & NEW_A){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->ack_seq = htonl( ntohl(thp->ack_seq) + x);
     		}
     		if(changes & NEW_S){
    -			if((x = decode(&cp)) == -1) {
    +			if((x = decode(&cp, end)) == -1) {
     				goto bad;
     			}
     			thp->seq = htonl( ntohl(thp->seq) + x);
    @@ -593,7 +600,7 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize)
     		break;
     	}
     	if(changes & NEW_I){
    -		if((x = decode(&cp)) == -1) {
    +		if((x = decode(&cp, end)) == -1) {
     			goto bad;
     		}
     		ip->id = htons (ntohs (ip->id) + x);
    -- 
    cgit 1.3-korg
    
    
    

Vulnerability mechanics

Root cause

"Missing bounds checks in decode() and pull16() allow out-of-bounds reads past the end of a VJ-compressed TCP packet."

Attack vector

An attacker sends a short VJ-compressed TCP frame over a SLIP interface whose change byte requests optional fields (e.g., NEW_U, NEW_W, NEW_A, NEW_S, or NEW_I). Because `decode()` and `pull16()` lack bounds checks, they read past the end of the compressed packet buffer. The over-read bytes are folded into the cached compression state (`cstate`) and reflected into subsequent reconstructed packets, potentially corrupting TCP/IP header fields of later connections. No authentication is required; the attacker only needs the ability to inject raw SLIP frames onto the link.

Affected code

The vulnerability resides in `drivers/net/slip/slhc.c` in the `slhc_uncompress()` function and its helper functions `decode()` and `pull16()`. The `decode()` helper previously masked its return with `& 0xffff`, making the `== -1` error checks in `slhc_uncompress()` dead code [patch_id=2654181]. Neither helper performed bounds checking against the compressed packet length (`isize`).

What the fix does

The patch modifies `decode()` and `pull16()` to accept an `end` pointer (derived from `icp + isize`) and return `-1` when the buffer is exhausted [patch_id=2654181]. The `& 0xffff` mask that prevented `-1` from propagating is removed from `decode()`. A new bounds check (`if (cp + 2 > end) goto bad;`) is added before the TCP-checksum read in `slhc_uncompress()`. All existing `== -1` tests in the callers, which were previously dead code, now correctly abort decompression on a truncated packet.

Preconditions

  • networkThe attacker must be able to send raw SLIP frames to a SLIP interface on the target system.
  • configThe target must have the SLIP (serial line IP) driver enabled and an active SLIP link.
  • authNo authentication is required; the vulnerability is reachable from any network path that can deliver a SLIP-encapsulated packet.

Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

5

News mentions

0

No linked articles in our index yet.