get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2218775/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2218775,
    "url": "http://patchwork.ozlabs.org/api/patches/2218775/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/ubuntu-kernel/patch/20260401215950.1178116-1-tim.whisonant@canonical.com/",
    "project": {
        "id": 15,
        "url": "http://patchwork.ozlabs.org/api/projects/15/?format=api",
        "name": "Ubuntu Kernel",
        "link_name": "ubuntu-kernel",
        "list_id": "kernel-team.lists.ubuntu.com",
        "list_email": "kernel-team@lists.ubuntu.com",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260401215950.1178116-1-tim.whisonant@canonical.com>",
    "list_archive_url": null,
    "date": "2026-04-01T21:59:49",
    "name": "[SRU,J,2/2] netfilter: nft_set_pipapo: split gc into unlink and reclaim phase",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "708a4329c3f7a60eeb062f695a8f6557fc85df18",
    "submitter": {
        "id": 89903,
        "url": "http://patchwork.ozlabs.org/api/people/89903/?format=api",
        "name": "Tim Whisonant",
        "email": "tim.whisonant@canonical.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/ubuntu-kernel/patch/20260401215950.1178116-1-tim.whisonant@canonical.com/mbox/",
    "series": [
        {
            "id": 498398,
            "url": "http://patchwork.ozlabs.org/api/series/498398/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/ubuntu-kernel/list/?series=498398",
            "date": "2026-04-01T21:59:44",
            "name": "CVE-2026-23351",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498398/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2218775/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218775/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<kernel-team-bounces@lists.ubuntu.com>",
        "X-Original-To": "incoming@patchwork.ozlabs.org",
        "Delivered-To": "patchwork-incoming@legolas.ozlabs.org",
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (4096-bit key;\n unprotected) header.d=canonical.com header.i=@canonical.com\n header.a=rsa-sha256 header.s=20251003 header.b=pyS+KhBt;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ubuntu.com\n (client-ip=185.125.189.65; helo=lists.ubuntu.com;\n envelope-from=kernel-team-bounces@lists.ubuntu.com;\n receiver=patchwork.ozlabs.org)"
        ],
        "Received": [
            "from lists.ubuntu.com (lists.ubuntu.com [185.125.189.65])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fmJnJ4FX9z1xtJ\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 09:00:04 +1100 (AEDT)",
            "from localhost ([127.0.0.1] helo=lists.ubuntu.com)\n\tby lists.ubuntu.com with esmtp (Exim 4.86_2)\n\t(envelope-from <kernel-team-bounces@lists.ubuntu.com>)\n\tid 1w83bQ-0007V7-7z; Wed, 01 Apr 2026 21:59:56 +0000",
            "from smtp-relay-internal-1.internal ([10.131.114.114]\n helo=smtp-relay-internal-1.canonical.com)\n by lists.ubuntu.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.86_2) (envelope-from <tim.whisonant@canonical.com>)\n id 1w83bO-0007U0-VT\n for kernel-team@lists.ubuntu.com; Wed, 01 Apr 2026 21:59:55 +0000",
            "from mail-oa1-f71.google.com (mail-oa1-f71.google.com\n [209.85.160.71])\n (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n (No client certificate requested)\n by smtp-relay-internal-1.canonical.com (Postfix) with ESMTPS id D31743F13F\n for <kernel-team@lists.ubuntu.com>; Wed,  1 Apr 2026 21:59:54 +0000 (UTC)",
            "by mail-oa1-f71.google.com with SMTP id\n 586e51a60fabf-41c08879ba3so4925805fac.0\n for <kernel-team@lists.ubuntu.com>; Wed, 01 Apr 2026 14:59:54 -0700 (PDT)",
            "from localhost (104-6-108-11.lightspeed.frokca.sbcglobal.net.\n [104.6.108.11]) by smtp.gmail.com with ESMTPSA id\n 006d021491bc7-680a53ff717sm547584eaf.2.2026.04.01.14.59.51\n for <kernel-team@lists.ubuntu.com>\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Wed, 01 Apr 2026 14:59:52 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com;\n s=20251003; t=1775080794;\n bh=b3T2R1chy9jqRbjv9M3ko01FA7nAYk+rdJQgEBQRCYw=;\n h=From:To:Subject:Date:Message-ID:In-Reply-To:References:\n MIME-Version;\n b=pyS+KhBtWJsl5xiR5EIC/dqPA4JlaRSPqyr8cMIs6KtMrm8fhty0/MjtkGLVI1gqp\n XnXFjzP6qNCERISjM98Ij/5zOZ+BOqBJnhZOuLvS8bwRjUUShlyFlzSnbajLXehbsX\n RTHjfF0HEM9xyefo9ApS2CJY2FjzpNkVy6sE/C+G2Ztn85eslkurMMxIMXOC8XzdhG\n Glus4dvPqz5IPV5+1S/T06f3/Uy9zau/0WdbnCEAmn3Nub4dZEO/YsrwRsCdi4/Qxs\n mtbFU4DKaXCU2Yl7cB0LjKRvj34v3ljxB8pL47LC4PcOMgenDBRBTVFB8ChC1rUe93\n N2nEFxxhjhNWl5JU+RTChe2R1hsK4Zlfodi+/HP1PMdxbEP8cfmwC6E3JdIuRyI2ec\n 59NIVCx9qhX/GtvyT1EynYnWjOi9J6xsgntnGzMT1lRuPtAasQq1LeU6Dx4pfWG5Da\n OV73KjOlH/O9yeGGW184EaMKdT6XPscbY+lT/w+XbukBgeBbVEqKXtljoVirfH/CEz\n s7PrfUNYCGzMLtHyd8as4EZgsq+e2CKp9Dq9T0l7JcSmKU4V1WJGEQpleqJ5TCXRtW\n lcq+sWKQWP7e2X8q5sURDf6sj1nhVfuYHpYOwqGrXsrnL9qrqWey8UTunKwjrtTt5B\n HXl9psT2Hof698ph0REtP6jY=",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1775080793; x=1775685593;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=b3T2R1chy9jqRbjv9M3ko01FA7nAYk+rdJQgEBQRCYw=;\n b=TlhKyF82u9YJCwHjdtFUc96yWnr7l+HNEOPvD+7qrmvv7o3nyj2wDvv2BeDnr5dAlJ\n NYMs0XMd85yCkH51PnpzwAAEEKUFq6YxVMbfjtXEOeR6WL/xYKuzo8EHO+CIFjHl1jL7\n kXOTy3QnbR20liNum+M1Usv1u8SGGKoWMbn67NHwaMVPC6WF8w/+/SqCht6Mw3dgTS3U\n 3YSdNcpr6WVIaDfnIa3KA3Du+KBCfu4QuGf3orbWwweTEZGEucZojkinLScyBtz3sXS5\n wpk602t/0+moiOugWUpX36aMr5syZGPtkqFf8UPf/ck3674d7twoEeXq1GLlhTtgPk09\n ATmg==",
        "X-Gm-Message-State": "AOJu0YzmwfZU8nyS+Ro3lBP2bcsCSoGSZc+hFdRLIqYEq/DRIDaJi27C\n P7AOSkiI4oaGkdrjftJFTY8MUQfrQBHBltyiGUt3ArPdgn7xQg+KRAnFzQU2iFrKuvidfMAQUf8\n RbkqpgmK5X6JJy8PdqUmEtlTa7zGoRoydu3BD2ET4vKfH0BjDZ1e9vcu+TOvYe5kY6FuRMGFhre\n oZKNx8aMJevrPSIw==",
        "X-Gm-Gg": "ATEYQzxZyqZgpm9WiOFpsEmlthFQ5gcLhjWcHOjuF/JQdcY088TNmqSVn35kenPKCK1\n pvV5vAYDuuK8Mq85m1WHNLx5YscFC6LUlJoJ63YvW7p614rIrfOp1GJlN2SWvVokGLZCShyjbff\n dq76sASVmxG8ae3JtVTOcgWEmnAdjqdminSJ2DduRYHzqXm98rZvmAVPZxGDsEXN3fDUZZfAgjn\n hFydFXilg9xcC/HF7RJ0YPYPV6Pm5304yXDLHtsOWyYLrtEfBcmG7g4feLdkiHVhfSQBJkof6vU\n 2K/klHFe4Y/OKdqYy3qhOapYJWPHGXicKGCC60lKgMiT0TsBLnGmpakdWfa0KhAOFLiCLOpZwBv\n WmETAzPnz4EqhgOkOrWDDXSsosOM/tjSR2UjZEtRVSG/ESiJdZJdtM8AYzFDOppcjy8i7mCoS4/\n SBog==",
        "X-Received": [
            "by 2002:a05:6820:2107:b0:67e:16d8:8107 with SMTP id\n 006d021491bc7-680f9042137mr31747eaf.26.1775080793202;\n Wed, 01 Apr 2026 14:59:53 -0700 (PDT)",
            "by 2002:a05:6820:2107:b0:67e:16d8:8107 with SMTP id\n 006d021491bc7-680f9042137mr31738eaf.26.1775080792720;\n Wed, 01 Apr 2026 14:59:52 -0700 (PDT)"
        ],
        "From": "Tim Whisonant <tim.whisonant@canonical.com>",
        "To": "kernel-team@lists.ubuntu.com",
        "Subject": "[SRU][J][PATCH 2/2] netfilter: nft_set_pipapo: split gc into unlink\n and reclaim phase",
        "Date": "Wed,  1 Apr 2026 14:59:49 -0700",
        "Message-ID": "<20260401215950.1178116-1-tim.whisonant@canonical.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "In-Reply-To": "<20260401215940.1178046-1-tim.whisonant@canonical.com>",
        "References": "<20260401215940.1178046-1-tim.whisonant@canonical.com>",
        "MIME-Version": "1.0",
        "X-BeenThere": "kernel-team@lists.ubuntu.com",
        "X-Mailman-Version": "2.1.20",
        "Precedence": "list",
        "List-Id": "Kernel team discussions <kernel-team.lists.ubuntu.com>",
        "List-Unsubscribe": "<https://lists.ubuntu.com/mailman/options/kernel-team>,\n <mailto:kernel-team-request@lists.ubuntu.com?subject=unsubscribe>",
        "List-Archive": "<https://lists.ubuntu.com/archives/kernel-team>",
        "List-Post": "<mailto:kernel-team@lists.ubuntu.com>",
        "List-Help": "<mailto:kernel-team-request@lists.ubuntu.com?subject=help>",
        "List-Subscribe": "<https://lists.ubuntu.com/mailman/listinfo/kernel-team>,\n <mailto:kernel-team-request@lists.ubuntu.com?subject=subscribe>",
        "Content-Type": "text/plain; charset=\"utf-8\"",
        "Content-Transfer-Encoding": "base64",
        "Errors-To": "kernel-team-bounces@lists.ubuntu.com",
        "Sender": "\"kernel-team\" <kernel-team-bounces@lists.ubuntu.com>"
    },
    "content": "From: Florian Westphal <fw@strlen.de>\n\ncommit 9df95785d3d8302f7c066050117b04cd3c2048c2 upstream.\n\nYiming Qian reports Use-after-free in the pipapo set type:\n  Under a large number of expired elements, commit-time GC can run for a very\n  long time in a non-preemptible context, triggering soft lockup warnings and\n  RCU stall reports (local denial of service).\n\nWe must split GC in an unlink and a reclaim phase.\n\nWe cannot queue elements for freeing until pointers have been swapped.\nExpired elements are still exposed to both the packet path and userspace\ndumpers via the live copy of the data structure.\n\ncall_rcu() does not protect us: dump operations or element lookups starting\nafter call_rcu has fired can still observe the free'd element, unless the\ncommit phase has made enough progress to swap the clone and live pointers\nbefore any new reader has picked up the old version.\n\nThis a similar approach as done recently for the rbtree backend in commit\n35f83a75529a (\"netfilter: nft_set_rbtree: don't gc elements on insert\").\n\nFixes: 3c4287f62044 (\"nf_tables: Add set type for arbitrary concatenation of ranges\")\nReported-by: Yiming Qian <yimingqian591@gmail.com>\nSigned-off-by: Florian Westphal <fw@strlen.de>\nSigned-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>\n(cherry picked from commit 16f3595c0441d87dfa005c47d8f95be213afaa9e linux-6.1.y)\nCVE-2026-23351\nSigned-off-by: Tim Whisonant <tim.whisonant@canonical.com>\n---\n include/net/netfilter/nf_tables.h |  5 +++\n net/netfilter/nf_tables_api.c     |  5 ---\n net/netfilter/nft_set_pipapo.c    | 51 ++++++++++++++++++++++++++-----\n net/netfilter/nft_set_pipapo.h    |  2 ++\n 4 files changed, 50 insertions(+), 13 deletions(-)",
    "diff": "diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h\nindex 1296dbcf675ec..c5c612df73d36 100644\n--- a/include/net/netfilter/nf_tables.h\n+++ b/include/net/netfilter/nf_tables.h\n@@ -1655,6 +1655,11 @@ struct nft_trans_gc {\n \tstruct rcu_head\t\trcu;\n };\n \n+static inline int nft_trans_gc_space(const struct nft_trans_gc *trans)\n+{\n+\treturn NFT_TRANS_GC_BATCHCOUNT - trans->count;\n+}\n+\n struct nft_trans_gc *nft_trans_gc_alloc(struct nft_set *set,\n \t\t\t\t\tunsigned int gc_seq, gfp_t gfp);\n void nft_trans_gc_destroy(struct nft_trans_gc *trans);\ndiff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c\nindex 49fc22db42d62..53a9baf03a628 100644\n--- a/net/netfilter/nf_tables_api.c\n+++ b/net/netfilter/nf_tables_api.c\n@@ -9178,11 +9178,6 @@ static void nft_trans_gc_queue_work(struct nft_trans_gc *trans)\n \tschedule_work(&trans_gc_work);\n }\n \n-static int nft_trans_gc_space(struct nft_trans_gc *trans)\n-{\n-\treturn NFT_TRANS_GC_BATCHCOUNT - trans->count;\n-}\n-\n struct nft_trans_gc *nft_trans_gc_queue_async(struct nft_trans_gc *gc,\n \t\t\t\t\t      unsigned int gc_seq, gfp_t gfp)\n {\ndiff --git a/net/netfilter/nft_set_pipapo.c b/net/netfilter/nft_set_pipapo.c\nindex 12e077fb8f4e8..6ab5b59ee69cf 100644\n--- a/net/netfilter/nft_set_pipapo.c\n+++ b/net/netfilter/nft_set_pipapo.c\n@@ -1577,11 +1577,11 @@ static void nft_pipapo_gc_deactivate(struct net *net, struct nft_set *set,\n }\n \n /**\n- * pipapo_gc() - Drop expired entries from set, destroy start and end elements\n+ * pipapo_gc_scan() - Drop expired entries from set and link them to gc list\n  * @set:\tnftables API set representation\n  * @m:\t\tMatching data\n  */\n-static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)\n+static void pipapo_gc_scan(struct nft_set *set, struct nft_pipapo_match *m)\n {\n \tstruct nft_pipapo *priv = nft_set_priv(set);\n \tstruct net *net = read_pnet(&set->net);\n@@ -1594,6 +1594,8 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)\n \tif (!gc)\n \t\treturn;\n \n+\tlist_add(&gc->list, &priv->gc_head);\n+\n \twhile ((rules_f0 = pipapo_rules_same_key(m->f, first_rule))) {\n \t\tunion nft_pipapo_map_bucket rulemap[NFT_PIPAPO_MAX_FIELDS];\n \t\tconst struct nft_pipapo_field *f;\n@@ -1623,9 +1625,13 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)\n \t\tif (__nft_set_elem_expired(&e->ext, tstamp)) {\n \t\t\tpriv->dirty = true;\n \n-\t\t\tgc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC);\n-\t\t\tif (!gc)\n-\t\t\t\treturn;\n+\t\t\tif (!nft_trans_gc_space(gc)) {\n+\t\t\t\tgc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);\n+\t\t\t\tif (!gc)\n+\t\t\t\t\treturn;\n+\n+\t\t\t\tlist_add(&gc->list, &priv->gc_head);\n+\t\t\t}\n \n \t\t\tnft_pipapo_gc_deactivate(net, set, e);\n \t\t\tpipapo_drop(m, rulemap);\n@@ -1639,10 +1645,30 @@ static void pipapo_gc(struct nft_set *set, struct nft_pipapo_match *m)\n \t\t}\n \t}\n \n-\tgc = nft_trans_gc_catchall_sync(gc);\n+\tpriv->last_gc = jiffies;\n+}\n+\n+/**\n+ * pipapo_gc_queue() - Free expired elements\n+ * @set:\tnftables API set representation\n+ */\n+static void pipapo_gc_queue(struct nft_set *set)\n+{\n+\tstruct nft_pipapo *priv = nft_set_priv(set);\n+\tstruct nft_trans_gc *gc, *next;\n+\n+\t/* always do a catchall cycle: */\n+\tgc = nft_trans_gc_alloc(set, 0, GFP_KERNEL);\n \tif (gc) {\n+\t\tgc = nft_trans_gc_catchall_sync(gc);\n+\t\tif (gc)\n+\t\t\tnft_trans_gc_queue_sync_done(gc);\n+\t}\n+\n+\t/* always purge queued gc elements. */\n+\tlist_for_each_entry_safe(gc, next, &priv->gc_head, list) {\n+\t\tlist_del(&gc->list);\n \t\tnft_trans_gc_queue_sync_done(gc);\n-\t\tpriv->last_gc = jiffies;\n \t}\n }\n \n@@ -1696,6 +1722,10 @@ static void pipapo_reclaim_match(struct rcu_head *rcu)\n  *\n  * We also need to create a new working copy for subsequent insertions and\n  * deletions.\n+ *\n+ * After the live copy has been replaced by the clone, we can safely queue\n+ * expired elements that have been collected by pipapo_gc_scan() for\n+ * memory reclaim.\n  */\n static void nft_pipapo_commit(struct nft_set *set)\n {\n@@ -1703,7 +1733,7 @@ static void nft_pipapo_commit(struct nft_set *set)\n \tstruct nft_pipapo_match *new_clone, *old;\n \n \tif (time_after_eq(jiffies, priv->last_gc + nft_set_gc_interval(set)))\n-\t\tpipapo_gc(set, priv->clone);\n+\t\tpipapo_gc_scan(set, priv->clone);\n \n \tif (!priv->dirty)\n \t\treturn;\n@@ -1720,6 +1750,8 @@ static void nft_pipapo_commit(struct nft_set *set)\n \t\tcall_rcu(&old->rcu, pipapo_reclaim_match);\n \n \tpriv->clone = new_clone;\n+\n+\tpipapo_gc_queue(set);\n }\n \n static bool nft_pipapo_transaction_mutex_held(const struct nft_set *set)\n@@ -2192,6 +2224,7 @@ static int nft_pipapo_init(const struct nft_set *set,\n \n \tpriv->dirty = false;\n \n+\tINIT_LIST_HEAD(&priv->gc_head);\n \trcu_assign_pointer(priv->match, m);\n \n \treturn 0;\n@@ -2244,6 +2277,8 @@ static void nft_pipapo_destroy(const struct nft_ctx *ctx,\n \tstruct nft_pipapo_match *m;\n \tint cpu;\n \n+\tWARN_ON_ONCE(!list_empty(&priv->gc_head));\n+\n \tm = rcu_dereference_protected(priv->match, true);\n \tif (m) {\n \t\trcu_barrier();\ndiff --git a/net/netfilter/nft_set_pipapo.h b/net/netfilter/nft_set_pipapo.h\nindex 519a2e6dc206f..a99baaeb5d926 100644\n--- a/net/netfilter/nft_set_pipapo.h\n+++ b/net/netfilter/nft_set_pipapo.h\n@@ -165,6 +165,7 @@ struct nft_pipapo_match {\n  * @width:\tTotal bytes to be matched for one packet, including padding\n  * @dirty:\tWorking copy has pending insertions or deletions\n  * @last_gc:\tTimestamp of last garbage collection run, jiffies\n+ * @gc_head:\tlist of nft_trans_gc to queue up for mem reclaim\n  */\n struct nft_pipapo {\n \tstruct nft_pipapo_match __rcu *match;\n@@ -172,6 +173,7 @@ struct nft_pipapo {\n \tint width;\n \tbool dirty;\n \tunsigned long last_gc;\n+\tstruct list_head gc_head;\n };\n \n struct nft_pipapo_elem;\n",
    "prefixes": [
        "SRU",
        "J",
        "2/2"
    ]
}