slip: Check if rstate is initialized before uncompressing [Linux 4.9.95]

This Linux kernel change "slip: Check if rstate is initialized before uncompressing" is included in the Linux 4.9.95 release. This change is authored by Tejaswi Tanikella <tejaswit [at] codeaurora.org> on Wed Apr 11 16:34:47 2018 +0530. The commit for this change in Linux stable tree is 0eecffb (patch) which is from upstream commit 3f01ddb. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 3f01ddb.

slip: Check if rstate is initialized before uncompressing

[ Upstream commit 3f01ddb962dc506916c243f9524e8bef97119b77 ]

On receiving a packet the state index points to the rstate which must be
used to fill up IP and TCP headers. But if the state index points to a
rstate which is unitialized, i.e. filled with zeros, it gets stuck in an
infinite loop inside ip_fast_csum trying to compute the ip checsum of a
header with zero length.

89.666953:   <2> [<ffffff9dd3e94d38>] slhc_uncompress+0x464/0x468
89.666965:   <2> [<ffffff9dd3e87d88>] ppp_receive_nonmp_frame+0x3b4/0x65c
89.666978:   <2> [<ffffff9dd3e89dd4>] ppp_receive_frame+0x64/0x7e0
89.666991:   <2> [<ffffff9dd3e8a708>] ppp_input+0x104/0x198
89.667005:   <2> [<ffffff9dd3e93868>] pppopns_recv_core+0x238/0x370
89.667027:   <2> [<ffffff9dd4428fc8>] __sk_receive_skb+0xdc/0x250
89.667040:   <2> [<ffffff9dd3e939e4>] pppopns_recv+0x44/0x60
89.667053:   <2> [<ffffff9dd4426848>] __sock_queue_rcv_skb+0x16c/0x24c
89.667065:   <2> [<ffffff9dd4426954>] sock_queue_rcv_skb+0x2c/0x38
89.667085:   <2> [<ffffff9dd44f7358>] raw_rcv+0x124/0x154
89.667098:   <2> [<ffffff9dd44f7568>] raw_local_deliver+0x1e0/0x22c
89.667117:   <2> [<ffffff9dd44c8ba0>] ip_local_deliver_finish+0x70/0x24c
89.667131:   <2> [<ffffff9dd44c92f4>] ip_local_deliver+0x100/0x10c

./scripts/faddr2line vmlinux slhc_uncompress+0x464/0x468 output:
 ip_fast_csum at arch/arm64/include/asm/checksum.h:40
 (inlined by) slhc_uncompress at drivers/net/slip/slhc.c:615

Adding a variable to indicate if the current rstate is initialized. If
such a packet arrives, move to toss state.

Signed-off-by: Tejaswi Tanikella <tejaswit@codeaurora.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

There are 6 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 drivers/net/slip/slhc.c | 5 +++++
 include/net/slhc_vj.h   | 1 +
 2 files changed, 6 insertions(+)

diff --git a/drivers/net/slip/slhc.c b/drivers/net/slip/slhc.c
index 27ed252..cfd81eb 100644
--- a/drivers/net/slip/slhc.c
+++ b/drivers/net/slip/slhc.c
@@ -509,6 +509,10 @@ struct slcompress *
        if(x < 0 || x > comp->rslot_limit)
            goto bad;

+       /* Check if the cstate is initialized */
+       if (!comp->rstate[x].initialized)
+           goto bad;
+
        comp->flags &=~ SLF_TOSS;
        comp->recv_current = x;
    } else {
@@ -673,6 +677,7 @@ struct slcompress *
    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;
+   cs->initialized = true;
    /* Put headers back on packet
     * Neither header checksum is recalculated
     */
diff --git a/include/net/slhc_vj.h b/include/net/slhc_vj.h
index 8716d59..8fcf890 100644
--- a/include/net/slhc_vj.h
+++ b/include/net/slhc_vj.h
@@ -127,6 +127,7 @@
  */
 struct cstate {
    byte_t  cs_this;    /* connection id number (xmit) */
+   bool    initialized;    /* true if initialized */
    struct cstate *next;    /* next in ring (xmit) */
    struct iphdr cs_ip; /* ip/tcp hdr from most recent packet */
    struct tcphdr cs_tcp;

Leave a Reply

Your email address will not be published. Required fields are marked *