crypto: scompress - increment scomp_scratch_users when already allocated
authorSabrina Dubroca <sd@queasysnail.net>
Thu, 24 Apr 2025 20:15:50 +0000 (22:15 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 25 Apr 2025 02:33:30 +0000 (10:33 +0800)
Commit ddd0a42671c0 only increments scomp_scratch_users when it was 0,
causing a panic when using ipcomp:

    Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
    KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
    CPU: 1 UID: 0 PID: 619 Comm: ping Tainted: G                 N  6.15.0-rc3-net-00032-ga79be02bba5c #41 PREEMPT(full)
    Tainted: [N]=TEST
    Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Arch Linux 1.16.3-1-1 04/01/2014
    RIP: 0010:inflate_fast+0x5a2/0x1b90
    [...]
    Call Trace:
     <IRQ>
     zlib_inflate+0x2d60/0x6620
     deflate_sdecompress+0x166/0x350
     scomp_acomp_comp_decomp+0x45f/0xa10
     scomp_acomp_decompress+0x21/0x120
     acomp_do_req_chain+0x3e5/0x4e0
     ipcomp_input+0x212/0x550
     xfrm_input+0x2de2/0x72f0
    [...]
    Kernel panic - not syncing: Fatal exception in interrupt
    Kernel Offset: disabled
    ---[ end Kernel panic - not syncing: Fatal exception in interrupt ]---

Instead, let's keep the old increment, and decrement back to 0 if the
scratch allocation fails.

Fixes: ddd0a42671c0 ("crypto: scompress - Fix scratch allocation failure handling")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
crypto/scompress.c

index 36934c78d1277ddf77c1f4d02b9874a5e1d1f763..ffeedcf20b0f1802581537bbb8d9a615c9ed09bb 100644 (file)
@@ -163,11 +163,10 @@ static int crypto_scomp_init_tfm(struct crypto_tfm *tfm)
                if (ret)
                        goto unlock;
        }
-       if (!scomp_scratch_users) {
+       if (!scomp_scratch_users++) {
                ret = crypto_scomp_alloc_scratches();
                if (ret)
-                       goto unlock;
-               scomp_scratch_users++;
+                       scomp_scratch_users--;
        }
 unlock:
        mutex_unlock(&scomp_lock);