slhc_init() allows rslots == 0 and in that case skips the allocation of comp->rstate, leaving it NULL. Because the struct is zero-initialized by kzalloc, comp->rslot_limit is also 0. The receive-side entry points slhc_uncompress() and slhc_remember() only compare a packet's slot index against rslot_limit, so slot 0 passes the bounds check even though no receive state array exists. Any VJ-compressed or VJ-uncompressed packet that selects slot 0 then dereferences the NULL rstate pointer. This can be reached through PPP by issuing PPPIOCSMAXCID with a value whose upper 16 bits, after arithmetic right shift, yield -1, making val2 + 1 == 0 and thus rslots == 0. Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] RIP: 0010:slhc_uncompress (drivers/net/slip/slhc.c:519) Call Trace: ppp_receive_nonmp_frame (drivers/net/ppp/ppp_generic.c:2466) ppp_input (drivers/net/ppp/ppp_generic.c:2359) ppp_async_process (drivers/net/ppp/ppp_async.c:492) tasklet_action_common (kernel/softirq.c:926) handle_softirqs (kernel/softirq.c:623) run_ksoftirqd (kernel/softirq.c:1055) smpboot_thread_fn (kernel/smpboot.c:160) kthread (kernel/kthread.c:436) ret_from_fork (arch/x86/kernel/process.c:164) Add a NULL check on comp->rstate at the entry of slhc_uncompress() and slhc_remember() so that frames are rejected when no receive slots exist. Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: Xiang Mei Signed-off-by: Weiming Shi --- drivers/net/slip/slhc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c index e3c785da3eef..e67052bcab57 100644 --- a/drivers/net/slip/slhc.c +++ b/drivers/net/slip/slhc.c @@ -502,6 +502,10 @@ slhc_uncompress(struct slcompress *comp, unsigned char *icp, int isize) /* We've got a compressed packet; read the change byte */ comp->sls_i_compressed++; + if (!comp->rstate) { + comp->sls_i_error++; + return 0; + } if(isize < 3){ comp->sls_i_error++; return 0; @@ -651,8 +655,9 @@ slhc_remember(struct slcompress *comp, unsigned char *icp, int isize) /* The packet is shorter than a legal IP header. * Also make sure isize is positive. + * Reject if no receive slots are configured (rstate is NULL). */ - if (isize < (int)sizeof(struct iphdr)) { + if (!comp->rstate || isize < (int)sizeof(struct iphdr)) { runt: comp->sls_i_runt++; return slhc_toss(comp); -- 2.43.0