mm: zswap: fix objcg use-after-free in entry destruction
authorJohannes Weiner <hannes@cmpxchg.org>
Tue, 30 Jan 2024 01:34:38 +0000 (20:34 -0500)
committerAndrew Morton <akpm@linux-foundation.org>
Thu, 8 Feb 2024 05:20:35 +0000 (21:20 -0800)
In the per-memcg LRU universe, LRU removal uses entry->objcg to determine
which list count needs to be decreased.  Drop the objcg reference after
updating the LRU, to fix a possible use-after-free.

Link: https://lkml.kernel.org/r/20240130013438.565167-1-hannes@cmpxchg.org
Fixes: a65b0e7607cc ("zswap: make shrinking memcg-aware")
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
Acked-by: Yosry Ahmed <yosryahmed@google.com>
Reviewed-by: Nhat Pham <nphamcs@gmail.com>
Reviewed-by: Chengming Zhou <zhouchengming@bytedance.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
mm/zswap.c

index ca25b676048ea6d0b399661e9ebca137585f8dbd..0a94b197ed32e10e49dc2e02b28217182e0cd2fe 100644 (file)
@@ -536,10 +536,6 @@ static struct zpool *zswap_find_zpool(struct zswap_entry *entry)
  */
 static void zswap_free_entry(struct zswap_entry *entry)
 {
-       if (entry->objcg) {
-               obj_cgroup_uncharge_zswap(entry->objcg, entry->length);
-               obj_cgroup_put(entry->objcg);
-       }
        if (!entry->length)
                atomic_dec(&zswap_same_filled_pages);
        else {
@@ -548,6 +544,10 @@ static void zswap_free_entry(struct zswap_entry *entry)
                atomic_dec(&entry->pool->nr_stored);
                zswap_pool_put(entry->pool);
        }
+       if (entry->objcg) {
+               obj_cgroup_uncharge_zswap(entry->objcg, entry->length);
+               obj_cgroup_put(entry->objcg);
+       }
        zswap_entry_cache_free(entry);
        atomic_dec(&zswap_stored_pages);
        zswap_update_total_size();