{"id":2222626,"url":"http://patchwork.ozlabs.org/api/1.1/patches/2222626/?format=json","web_url":"http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260413075250.281653-3-wei.fang@nxp.com/","project":{"id":2,"url":"http://patchwork.ozlabs.org/api/1.1/projects/2/?format=json","name":"Linux PPC development","link_name":"linuxppc-dev","list_id":"linuxppc-dev.lists.ozlabs.org","list_email":"linuxppc-dev@lists.ozlabs.org","web_url":"https://github.com/linuxppc/wiki/wiki","scm_url":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git","webscm_url":"https://git.kernel.org/pub/scm/linux/kernel/git/powerpc/linux.git/"},"msgid":"<20260413075250.281653-3-wei.fang@nxp.com>","date":"2026-04-13T07:52:50","name":"[net,2/2] net: enetc: fix NTMP DMA use-after-free issue","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"44ef878fd38bfb922fa3e90faaf2eb39286bc654","submitter":{"id":84380,"url":"http://patchwork.ozlabs.org/api/1.1/people/84380/?format=json","name":"Wei Fang","email":"wei.fang@nxp.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/linuxppc-dev/patch/20260413075250.281653-3-wei.fang@nxp.com/mbox/","series":[{"id":499659,"url":"http://patchwork.ozlabs.org/api/1.1/series/499659/?format=json","web_url":"http://patchwork.ozlabs.org/project/linuxppc-dev/list/?series=499659","date":"2026-04-13T07:52:48","name":"net: enetc: fix command BD ring issues","version":1,"mbox":"http://patchwork.ozlabs.org/series/499659/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2222626/comments/","check":"success","checks":"http://patchwork.ozlabs.org/api/patches/2222626/checks/","tags":{},"headers":{"Return-Path":"\n <linuxppc-dev+bounces-19668-incoming=patchwork.ozlabs.org@lists.ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linuxppc-dev@lists.ozlabs.org"],"Delivered-To":"patchwork-incoming@legolas.ozlabs.org","Authentication-Results":["legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=nxp.com header.i=@nxp.com header.a=rsa-sha256\n header.s=selector1 header.b=O6Ql6WQn;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=lists.ozlabs.org\n (client-ip=2404:9400:21b9:f100::1; helo=lists.ozlabs.org;\n envelope-from=linuxppc-dev+bounces-19668-incoming=patchwork.ozlabs.org@lists.ozlabs.org;\n receiver=patchwork.ozlabs.org)","lists.ozlabs.org;\n arc=pass smtp.remote-ip=\"2a01:111:f403:c207::3\" arc.chain=microsoft.com","lists.ozlabs.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com","lists.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=nxp.com header.i=@nxp.com header.a=rsa-sha256\n header.s=selector1 header.b=O6Ql6WQn;\n\tdkim-atps=neutral","lists.ozlabs.org;\n spf=permerror (SPF Permanent Error: Void lookup limit of 2 exceeded)\n smtp.mailfrom=nxp.com (client-ip=2a01:111:f403:c207::3;\n helo=mrwpr03cu001.outbound.protection.outlook.com;\n envelope-from=wei.fang@nxp.com; receiver=lists.ozlabs.org)","dkim=none (message not signed)\n header.d=none;dmarc=none action=none header.from=nxp.com;"],"Received":["from lists.ozlabs.org (lists.ozlabs.org\n [IPv6:2404:9400:21b9:f100::1])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fvKNr5Yv0z1yDF\n\tfor <incoming@patchwork.ozlabs.org>; Mon, 13 Apr 2026 17:51:40 +1000 (AEST)","from boromir.ozlabs.org (localhost [127.0.0.1])\n\tby lists.ozlabs.org (Postfix) with ESMTP id 4fvKNc0yQ6z2yvL;\n\tMon, 13 Apr 2026 17:51:28 +1000 (AEST)","from MRWPR03CU001.outbound.protection.outlook.com\n (mail-francesouthazlp170110003.outbound.protection.outlook.com\n [IPv6:2a01:111:f403:c207::3])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange secp256r1 server-signature RSA-PSS (2048 bits) server-digest\n SHA256)\n\t(No client certificate requested)\n\tby lists.ozlabs.org (Postfix) with ESMTPS id 4fvKNZ3Gknz2yv2\n\tfor <linuxppc-dev@lists.ozlabs.org>; Mon, 13 Apr 2026 17:51:26 +1000 (AEST)","from AM8PR04MB7284.eurprd04.prod.outlook.com (2603:10a6:20b:1dc::8)\n by DBAPR04MB7463.eurprd04.prod.outlook.com (2603:10a6:10:1ad::10) with\n Microsoft SMTP Server (version=TLS1_2,\n cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9769.15; Mon, 13 Apr\n 2026 07:51:06 +0000","from AM8PR04MB7284.eurprd04.prod.outlook.com\n ([fe80::9cd6:51bd:82b:98dc]) by AM8PR04MB7284.eurprd04.prod.outlook.com\n ([fe80::9cd6:51bd:82b:98dc%5]) with mapi id 15.20.9769.046; Mon, 13 Apr 2026\n 07:51:06 +0000"],"ARC-Seal":["i=2; a=rsa-sha256; d=lists.ozlabs.org; s=201707; t=1776066687;\n\tcv=pass;\n b=k4HrXiVGxvhBYp9MmgC2N1VM/4OuPE4MHdQCcIvgXnr8k8X7YnQxMuEX5LpgSvS7ZI9fmKOKIECr+jgtC5cgoNWLt07HbL6TFNpNFKMCkB9kQ7Yzh4NCMuAxWcomGQOfpcQOmHPsFdmRhMtVXzee1Iw2xwBHkqHYYRLXO/CMIDNasymjHLrs89lF8LRMVH/RoyNlj8X2LasZddiCkO1XQNhwIQTUBrMTmNkmJtdeIKdgxZi74OQeM0w+jl69I5M9CJJ5Et8FM6NoGwtPULm8FM5vs8GEoNSglJ5NOm6XzOqCvz899Gs/zs8J5vHvj+C6vfsvdYrruYFJlLpPm0q/ig==","i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none;\n b=slWHGO7t/DSdzFuiQVLbTOa92NWqkI21VZSZRcsJ67Z7SBsTrmsT3OjaiwGMVhfRc/Bj5U1riWPrSjEI69L58jYjJzDtg84CIYFMigPWjlGsERbuQo9LzPUvpP7RqcKxrYhIEkW+TfECu1MGtSSX8H8kQXheGPqLc37mkp1en+l79/SWgngQEeMnhw8ZMBkGD5QQE/Wm0gmREyLPPrr35EWkRFN3wTy9ICqfU/DRcQkoGUXfkBN6+xaDFDSac2uyCX3stRPIPX5aa0hFslNya2FwLguEDcFqMo5c3yTWi8wZ/dtrz0axAnEmtMSAhkIG59SCjrulmge76TX4uC4/Kw=="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=lists.ozlabs.org; s=201707;\n\tt=1776066687; c=relaxed/relaxed;\n\tbh=NVlcMmeLWEJsMVz/tTFkQ2TLrqhq+YR2GJPfI66YfDM=;\n\th=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References:\n\t Content-Type:MIME-Version;\n b=KonkG8jplXUSSwNAZ66R+tPZwWRdziuTfaM0+7TbgqKMOA03hoddz+YADzcZFxDuH365R5gDovq0cLUzzSJASIOaToSsS1pk2k2UXeplJIYsEPSwCGjzjsXFie/MdRQgsDKsEv8ERD/qrIdY4/frA7GU6d3C9oBTZhnMk9K9bbj2ZpHo6K9AQIyhcWSTJ3WF9Xq6kKWcuFm4OQI7+03U925a0T5agodyS08ZIUCv7sFMNhAAdlRE/gmnkZjDWeM+GK+1jw3tI701se6fXDybG5l+0Nk9DfdbRbcGCwxTJHas2pHtKnoW/HGmDsrrL2kT6Mm7JTQ6RY/7QOMUOSkhLg==","i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;\n s=arcselector10001;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1;\n bh=NVlcMmeLWEJsMVz/tTFkQ2TLrqhq+YR2GJPfI66YfDM=;\n b=Rk1NH9QyghZKS6GSqh75yaorWg2raWvh+j+f+7giu+P80q6rVM166kN8eUdyY32otkaDu4TDHgbYef2x8Zs05lNTjWAb5yRcaQ0mWk+URVsExdv+Shz8x46GkJ55efuQqIx/Ni9tBTvPmsU7Fe+TCHlRExmVLPzGxO+2oR5V1lQYb5OokmOnQR2oiy79uGfYBdPbjFxNXruoQpUuUCrSq5pV5a474E98XPyLJPpjY8Qz26O4C+mbvsJZEOLYjip7XEKONyPVWJ2QrQ2KVBRA3fYSKSkKtKpIShzzsWtyTpYI0XF0cTiyT3Nfcw3BEHtYRAs8azKRzwXxQg7cpRPdcw=="],"ARC-Authentication-Results":["i=2; lists.ozlabs.org;\n dmarc=pass (p=none dis=none) header.from=nxp.com; dkim=pass (2048-bit key;\n unprotected) header.d=nxp.com header.i=@nxp.com header.a=rsa-sha256\n header.s=selector1 header.b=O6Ql6WQn; dkim-atps=neutral;\n spf=permerror (client-ip=2a01:111:f403:c207::3;\n helo=mrwpr03cu001.outbound.protection.outlook.com;\n envelope-from=wei.fang@nxp.com;\n receiver=lists.ozlabs.org) smtp.mailfrom=nxp.com","i=1; mx.microsoft.com 1; spf=pass\n smtp.mailfrom=nxp.com; dmarc=pass action=none header.from=nxp.com; dkim=pass\n header.d=nxp.com; arc=none"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1;\n h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;\n bh=NVlcMmeLWEJsMVz/tTFkQ2TLrqhq+YR2GJPfI66YfDM=;\n b=O6Ql6WQnS3hxd7ZFdnBs7FpNhejziXnMIJrymV9SM3u+UOk8DmAf/IyV3m0Q0lsZD1rsWq1CkW/4VOnMJ9agimgzmtru/E/FhnrJiCeh93dlwcl27H7eaMmr6oDwZdDvtrx3BaDPx8ndaBbH1X0hMTh6uYCrbGHlp/0cUeDXQV/fi97zqaLyndHCPxQCdNFUOV8UYPVLJbYtR0hPUak1EccHEKjsPgMSTxeG5DlZxpFo5nWyIL6Krtndk8pIiMmT6J9o9oLv5zpRUjbJj+rhhp0aqIbh5hk903zJf+oCzH8cBi3dE7EjTwoPOtQx7i56GG+EB4KrL/r812b3OCfvog==","From":"Wei Fang <wei.fang@nxp.com>","To":"claudiu.manoil@nxp.com,\n\tvladimir.oltean@nxp.com,\n\txiaoning.wang@nxp.com,\n\tandrew+netdev@lunn.ch,\n\tdavem@davemloft.net,\n\tedumazet@google.com,\n\tkuba@kernel.org,\n\tpabeni@redhat.com,\n\tchleroy@kernel.org","Cc":"netdev@vger.kernel.org,\n\tlinux-kernel@vger.kernel.org,\n\timx@lists.linux.dev,\n\tlinuxppc-dev@lists.ozlabs.org,\n\tlinux-arm-kernel@lists.infradead.org","Subject":"[PATCH net 2/2] net: enetc: fix NTMP DMA use-after-free issue","Date":"Mon, 13 Apr 2026 15:52:50 +0800","Message-Id":"<20260413075250.281653-3-wei.fang@nxp.com>","X-Mailer":"git-send-email 2.34.1","In-Reply-To":"<20260413075250.281653-1-wei.fang@nxp.com>","References":"<20260413075250.281653-1-wei.fang@nxp.com>","Content-Transfer-Encoding":"8bit","Content-Type":"text/plain","X-ClientProxiedBy":"MA5P287CA0236.INDP287.PROD.OUTLOOK.COM\n (2603:1096:a01:1b1::10) To AM8PR04MB7284.eurprd04.prod.outlook.com\n (2603:10a6:20b:1dc::8)","X-Mailing-List":"linuxppc-dev@lists.ozlabs.org","List-Id":"<linuxppc-dev.lists.ozlabs.org>","List-Help":"<mailto:linuxppc-dev+help@lists.ozlabs.org>","List-Owner":"<mailto:linuxppc-dev+owner@lists.ozlabs.org>","List-Post":"<mailto:linuxppc-dev@lists.ozlabs.org>","List-Archive":"<https://lore.kernel.org/linuxppc-dev/>,\n  <https://lists.ozlabs.org/pipermail/linuxppc-dev/>","List-Subscribe":"<mailto:linuxppc-dev+subscribe@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-digest@lists.ozlabs.org>,\n  <mailto:linuxppc-dev+subscribe-nomail@lists.ozlabs.org>","List-Unsubscribe":"<mailto:linuxppc-dev+unsubscribe@lists.ozlabs.org>","Precedence":"list","MIME-Version":"1.0","X-MS-PublicTrafficType":"Email","X-MS-TrafficTypeDiagnostic":"AM8PR04MB7284:EE_|DBAPR04MB7463:EE_","X-MS-Office365-Filtering-Correlation-Id":"09f9cf77-5439-4df1-7e8a-08de99316ab6","X-MS-Exchange-SenderADCheck":"1","X-MS-Exchange-AntiSpam-Relay":"0","X-Microsoft-Antispam":"\n\tBCL:0;ARA:13230040|52116014|7416014|376014|1800799024|366016|19092799006|38350700014|56012099003|22082099003|18002099003;","X-Microsoft-Antispam-Message-Info":"\n\tq9gJKUBvfzfmAJ05O7exqnRLWDRdh7l9IiG2Ndt9f1/ZXUztRgaRbHNN2U2lnrv4pb1zt5KyK53PeVN9pTqIO8L0KxFBZxYtwFdTsYMswjqicsoJZBe0ll2O75DFiaXzttpWcxtDCF4YZJVjlb6KeQqx65W2MdzoM4fNeUK1javrbI2Z6FKj1Uz8BlQz9Zu9JZ8sCYEW55G1OtU1rcOEATkg1I4uSa9PmQVtpKLatwvGHVeHrzb4MX9mLvHSxgVN4MxggXNl0FmJcuvm7BVm9oHPSN5TKoqqDAaOa7PcyBs60Lu/A5aGCemw8ukQBmmZc7vNFWypx1KGPEm7IHbHadYCQKVcrBFTb6KlrwM1E11L07NTP+Bd5XSHUDLzix6KS194VnjW1xq9tZTOliGLEjNR9iXNSGjjza+ewLcNAHz2gSFLjhbKrfwBfkUrkygEgYmeoDkKcqIqd2ZWigIAuqafVpYOMdNBwmvoWBx9IxG0emzfMFUmtL0lLFCIg/Jv9Oki3ahpXeW9lJ2vKjvoLz2Dv5fH81sWj2dRg+D+sMcxRV/gmsoZzs7B8uOW+e0r4kDyYWoicMJJpgh6dTPOHSd6Uo8Lca/HuigUDMHHBBgD9fvuUIxLkOJUeNP51a11cvTLGHKBOYC9yIj/f84bZ4nHrm/+8owdBT4jYOhxMdr0MpVsXVDzksaCT/wFP/hoqdE7GlJz7ycIx0Uvn/+w2OSYa/7hxtJvP9yD5ikPPn2DJAa/Kfpqi6ZiztQAuJUn99wcBD8QTnZTVhDoIfJvTQtsqhuoA1g+LVdChz/Y50I=","X-Forefront-Antispam-Report":"\n\tCIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:AM8PR04MB7284.eurprd04.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230040)(52116014)(7416014)(376014)(1800799024)(366016)(19092799006)(38350700014)(56012099003)(22082099003)(18002099003);DIR:OUT;SFP:1101;","X-MS-Exchange-AntiSpam-MessageData-ChunkCount":"1","X-MS-Exchange-AntiSpam-MessageData-0":"\n jtFlF6fD/i1NxwvOyWHzDbCn10QfxyWB/CVG9P1R4gubrLYggo8iiQ2Adbn/lhanFqhPb7inF5SfEn6TIJjTeKaPqcqQOrmHZaFp1hB46vVmhk5qFursF3cMygA/uXUc8XvqVJN8eByBwjuiKbsU6Q/hLnWmkGZTOhtfrGB4FmC2sO/QQ5oV33Dit7Uth8QAbSViaAPjkDK++v2Z7TN2qz/mxq3YIZcM5WtTlyMaZGtx+RMdRjPe4UjHmoc378bICgTaXBuMyTFlEKHgiCOFkjf7hhFUaiO5moqbEdYqjkIKFaiOE2XlRjZ3vJchUIBOdbZHRiXsLg+1UEb1ubgvI7NzwuC6fYq/to7J2tPRlWzfj6ymbqswbmU/9xVQMdp4zLBWUKbuMmgqSM4jIXER+Xo+eFT4ZwPXv6Xvsa2js3iByB1Hj/oZ0N1btF6x0AP4SxPP+0DMnVg0BxkXwaMXbPsWfH8HvorjdD0S1sG1JIHdWK68FSgvWcwKSV5+/AmG12lrR1KaraPya5ww33uUynQ+zYQC0fLcD1YoioIpLZOU4vmFd50j8BNWe3+ynsw1UQhrw4yh2b6ZJ+KKOG9P2m6f+K3yjsCaM4t9e6kgkGVObossDPflAGdHEflK5Y0bBrouId73kQTZ5PIvjBEzFW8ZB1kfnE5SahqrujFIE5mu68qC+N8R19VPBBG5CyHpz6FJAdYHTYaf61N1x2zPpGyE1dPQi1krEX5a2A8HjvvGEonXJaQ7nBHUv9aQ13H/DjBs2VLid40Mhxd9kiroTV7qOYkpYkFKkJZ0D+jDUON07PHMpdGoPLTt4L6asjhOazyXkUXP9D3lKI7z6bK+lZ6TkJNkZEEzRy4Wgt2mr4+YqK0DffdXREGtHZDS9/zG+A6u0BBhiFtMRkL8U3sKD0n256EG2ayuFAjENin49KbWKZzQcEre+k2uCULR25TfugzSx0vJjeQNp0LF4P/UC+Z50mTPL6G6Y3VY6tIQVOlu8HPo04qf3qasG10nDr5dcWUfqHGHZUGrrA447dy0CevQGhavqZWIqrnQODw1iii1N5k5AD2bSUp0pvZivblfzz7XdnC8ESMbzkbICNyqyWCe5P5/eHdLa6R/94h7hJmR9Z6MzMIq3gYnyGYvDCsrXwdkbpuaHnYNKbssnLuX4AYVB8Bl1dRplUgyjVEw+w3ObH7rd3wzOMkeu0NB+a/VUMXhqperqiIhWdk/H3b/DRBFxks1ohClCPzLOgZg9ExND9WhaYX0HVkdT5tQPcweBA3PyIQYGxj8QkYVZxuAyYnxfuIATUiXTzgGbhglbx8pOAM+9Nrn2g/VDWu4Mt5HopQQK2nesW5RhKHTrpHP4kJPRSJPCncFDbbYvI196PCRiGo/9kKeXcBInN9kL70sTgEA3HOp4s9lMeR5fmhr2SX2kNLBFVwMk4GV8iSKscmcQU/yHOToFhf1kfmevxgFfOHkWsE0yA85vntGtW8Q9tFqCbTr+njYlfZ6Ry0D8kSs6MXvaoJ13rdL5eFFAHt4kuM03OfigyzmeyGBo4mJtN0i1pHUAwOf0bG1GuDjr31pu2gP6AXdLFuM6kg6ZxU4qez5ppOPle8BuMYob/yyU9VhzwBrzv6LTWyCeJPlpKZfVBovHHd3uP/+AKAR7ToOWxtHx+8SZNQleePmckD662Ox4xCtWQPnCGjUAYIAuPjyxoeFbFbG3Hdzwq8WpkQPLzyhAiSvLr3XD6loQgVTNg==","X-OriginatorOrg":"nxp.com","X-MS-Exchange-CrossTenant-Network-Message-Id":"\n 09f9cf77-5439-4df1-7e8a-08de99316ab6","X-MS-Exchange-CrossTenant-AuthSource":"AM8PR04MB7284.eurprd04.prod.outlook.com","X-MS-Exchange-CrossTenant-AuthAs":"Internal","X-MS-Exchange-CrossTenant-OriginalArrivalTime":"13 Apr 2026 07:51:05.9991\n (UTC)","X-MS-Exchange-CrossTenant-FromEntityHeader":"Hosted","X-MS-Exchange-CrossTenant-Id":"686ea1d3-bc2b-4c6f-a92c-d99c5c301635","X-MS-Exchange-CrossTenant-MailboxType":"HOSTED","X-MS-Exchange-CrossTenant-UserPrincipalName":"\n cs7LsRBhwOZHrKKHkzE77RIFmGXBC0rklh01aTQ0ExGbDvDhA2KWF5DM36uJZ0Ve56q0RqJ+EdtzpPoGkIqHvQ==","X-MS-Exchange-Transport-CrossTenantHeadersStamped":"DBAPR04MB7463","X-Spam-Status":"No, score=0.8 required=3.0 tests=ARC_SIGNED,ARC_VALID,\n\tDKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FORGED_SPF_HELO,\n\tSPF_HELO_PASS,T_SPF_PERMERROR autolearn=disabled version=4.0.1 OzLabs 8","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on lists.ozlabs.org"},"content":"The AI-generated review reported a potential DMA use-after-free issue\n[1]. If netc_xmit_ntmp_cmd() times out and returns an error, the pending\ncommand is not explicitly aborted, while ntmp_free_data_mem()\nunconditionally frees the DMA buffer. If the buffer has already been\nreallocated elsewhere, this may lead to silent memory corruption. Because\nthe hardware eventually processes the pending command and perform a DMA\nwrite of the response to the physical address of the freed buffer.\n\nTo resolve this issue, this patch does the following modifications:\n\n1. Convert cbdr->ring_lock from a spinlock to a mutex\n\nThe lock was originally a spinlock in case NTMP operations might be\ninvoked from atomic context. After downstream support for all NTMP\ntables, no such usage has materialized. A mutex lock is now required\nbecause the driver now needs to reclaim used BDs and release associated\nDMA memory within the lock's context, while dma_free_coherent() might\nsleep.\n\n2. Introduce software command BD (struct netc_swcbd)\n\nThe hardware write-back overwrites the addr and len fields of the BD,\nso the driver cannot rely on the hardware BD to free the associated DMA\nmemory. The driver now maintains a software shadow BD storing the DMA\nbuffer pointer, DMA address, and size. And netc_xmit_ntmp_cmd() only\nreclaims older BDs when the number of used BDs reaches\nNETC_CBDR_CLEAN_WORK (16). The software BD enables correct DMA memory\nrelease. With this, struct ntmp_dma_buf and ntmp_free_data_mem() are no\nlonger needed and are removed.\n\nThese changes eliminate the DMA use-after-free condition and ensure safe\nand consistent BD reclamation and DMA buffer lifecycle management.\n\nFixes: 4701073c3deb (\"net: enetc: add initial netc-lib driver to support NTMP\")\nLink: https://lore.kernel.org/netdev/20260403011729.1795413-1-kuba@kernel.org/ # [1]\nSigned-off-by: Wei Fang <wei.fang@nxp.com>\n---\n drivers/net/ethernet/freescale/enetc/ntmp.c   | 158 ++++++++++--------\n .../ethernet/freescale/enetc/ntmp_private.h   |   8 +-\n include/linux/fsl/ntmp.h                      |   9 +-\n 3 files changed, 93 insertions(+), 82 deletions(-)","diff":"diff --git a/drivers/net/ethernet/freescale/enetc/ntmp.c b/drivers/net/ethernet/freescale/enetc/ntmp.c\nindex 1b1ff0446d0a..3efc65443113 100644\n--- a/drivers/net/ethernet/freescale/enetc/ntmp.c\n+++ b/drivers/net/ethernet/freescale/enetc/ntmp.c\n@@ -7,6 +7,7 @@\n #include <linux/dma-mapping.h>\n #include <linux/fsl/netc_global.h>\n #include <linux/iopoll.h>\n+#include <linux/vmalloc.h>\n \n #include \"ntmp_private.h\"\n \n@@ -42,6 +43,12 @@ int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev,\n \tif (!cbdr->addr_base)\n \t\treturn -ENOMEM;\n \n+\tcbdr->swcbd = vcalloc(cbd_num, sizeof(struct netc_swcbd));\n+\tif (!cbdr->swcbd) {\n+\t\tdma_free_coherent(dev, size, cbdr->addr_base, cbdr->dma_base);\n+\t\treturn -ENOMEM;\n+\t}\n+\n \tcbdr->dma_size = size;\n \tcbdr->bd_num = cbd_num;\n \tcbdr->regs = *regs;\n@@ -52,7 +59,7 @@ int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev,\n \tcbdr->addr_base_align = PTR_ALIGN(cbdr->addr_base,\n \t\t\t\t\t  NTMP_BASE_ADDR_ALIGN);\n \n-\tspin_lock_init(&cbdr->ring_lock);\n+\tmutex_init(&cbdr->ring_lock);\n \n \tcbdr->next_to_use = netc_read(cbdr->regs.pir);\n \tcbdr->next_to_clean = netc_read(cbdr->regs.cir) & NETC_CBDRCIR_INDEX;\n@@ -71,10 +78,25 @@ int ntmp_init_cbdr(struct netc_cbdr *cbdr, struct device *dev,\n }\n EXPORT_SYMBOL_GPL(ntmp_init_cbdr);\n \n+static void ntmp_free_data_mem(struct device *dev, struct netc_swcbd *swcbd)\n+{\n+\tdma_free_coherent(dev, swcbd->size + NTMP_DATA_ADDR_ALIGN,\n+\t\t\t  swcbd->buf, swcbd->dma);\n+}\n+\n void ntmp_free_cbdr(struct netc_cbdr *cbdr)\n {\n \t/* Disable the Control BD Ring */\n \tnetc_write(cbdr->regs.mr, 0);\n+\n+\tfor (int i = 0; i < cbdr->bd_num; i++) {\n+\t\tstruct netc_swcbd *swcbd = &cbdr->swcbd[i];\n+\n+\t\tif (swcbd->dma)\n+\t\t\tntmp_free_data_mem(cbdr->dev, swcbd);\n+\t}\n+\n+\tvfree(cbdr->swcbd);\n \tdma_free_coherent(cbdr->dev, cbdr->dma_size, cbdr->addr_base,\n \t\t\t  cbdr->dma_base);\n \tmemset(cbdr, 0, sizeof(*cbdr));\n@@ -94,24 +116,28 @@ static union netc_cbd *ntmp_get_cbd(struct netc_cbdr *cbdr, int index)\n \n static void ntmp_clean_cbdr(struct netc_cbdr *cbdr)\n {\n-\tunion netc_cbd *cbd;\n-\tint i;\n+\tint i = cbdr->next_to_clean;\n \n-\ti = cbdr->next_to_clean;\n \twhile ((netc_read(cbdr->regs.cir) & NETC_CBDRCIR_INDEX) != i) {\n-\t\tcbd = ntmp_get_cbd(cbdr, i);\n+\t\tunion netc_cbd *cbd = ntmp_get_cbd(cbdr, i);\n+\t\tstruct netc_swcbd *swcbd = &cbdr->swcbd[i];\n+\n+\t\tntmp_free_data_mem(cbdr->dev, swcbd);\n+\t\tmemset(swcbd, 0, sizeof(*swcbd));\n \t\tmemset(cbd, 0, sizeof(*cbd));\n \t\ti = (i + 1) % cbdr->bd_num;\n \t}\n \n+\tdma_wmb();\n \tcbdr->next_to_clean = i;\n }\n \n-static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)\n+static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd,\n+\t\t\t      struct netc_swcbd *swcbd)\n {\n \tunion netc_cbd *cur_cbd;\n \tstruct netc_cbdr *cbdr;\n-\tint i, err;\n+\tint i, err, used_bds;\n \tu16 status;\n \tu32 val;\n \n@@ -120,14 +146,21 @@ static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)\n \t */\n \tcbdr = &user->ring[0];\n \n-\tspin_lock_bh(&cbdr->ring_lock);\n+\tmutex_lock(&cbdr->ring_lock);\n \n-\tif (unlikely(!ntmp_get_free_cbd_num(cbdr)))\n+\tused_bds = cbdr->bd_num - ntmp_get_free_cbd_num(cbdr);\n+\tif (unlikely(used_bds >= NETC_CBDR_CLEAN_WORK)) {\n \t\tntmp_clean_cbdr(cbdr);\n+\t\tif (unlikely(!ntmp_get_free_cbd_num(cbdr))) {\n+\t\t\terr = -EBUSY;\n+\t\t\tgoto cbdr_unlock;\n+\t\t}\n+\t}\n \n \ti = cbdr->next_to_use;\n \tcur_cbd = ntmp_get_cbd(cbdr, i);\n \t*cur_cbd = *cbd;\n+\tcbdr->swcbd[i] = *swcbd;\n \tdma_wmb();\n \n \t/* Update producer index of both software and hardware */\n@@ -135,10 +168,9 @@ static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)\n \tcbdr->next_to_use = i;\n \tnetc_write(cbdr->regs.pir, i);\n \n-\terr = read_poll_timeout_atomic(netc_read, val,\n-\t\t\t\t       (val & NETC_CBDRCIR_INDEX) == i,\n-\t\t\t\t       NETC_CBDR_DELAY_US, NETC_CBDR_TIMEOUT,\n-\t\t\t\t       true, cbdr->regs.cir);\n+\terr = read_poll_timeout(netc_read, val, (val & NETC_CBDRCIR_INDEX) == i,\n+\t\t\t\tNETC_CBDR_DELAY_US, NETC_CBDR_TIMEOUT,\n+\t\t\t\ttrue, cbdr->regs.cir);\n \tif (unlikely(err))\n \t\tgoto cbdr_unlock;\n \n@@ -155,36 +187,28 @@ static int netc_xmit_ntmp_cmd(struct ntmp_user *user, union netc_cbd *cbd)\n \t\tdev_err(user->dev, \"Command BD error: 0x%04x\\n\", status);\n \t}\n \n-\tntmp_clean_cbdr(cbdr);\n-\tdma_wmb();\n-\n cbdr_unlock:\n-\tspin_unlock_bh(&cbdr->ring_lock);\n+\tmutex_unlock(&cbdr->ring_lock);\n \n \treturn err;\n }\n \n-static int ntmp_alloc_data_mem(struct ntmp_dma_buf *data, void **buf_align)\n+static int ntmp_alloc_data_mem(struct device *dev, struct netc_swcbd *swcbd,\n+\t\t\t       void **buf_align)\n {\n \tvoid *buf;\n \n-\tbuf = dma_alloc_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,\n-\t\t\t\t &data->dma, GFP_KERNEL);\n+\tbuf = dma_alloc_coherent(dev, swcbd->size + NTMP_DATA_ADDR_ALIGN,\n+\t\t\t\t &swcbd->dma, GFP_KERNEL);\n \tif (!buf)\n \t\treturn -ENOMEM;\n \n-\tdata->buf = buf;\n+\tswcbd->buf = buf;\n \t*buf_align = PTR_ALIGN(buf, NTMP_DATA_ADDR_ALIGN);\n \n \treturn 0;\n }\n \n-static void ntmp_free_data_mem(struct ntmp_dma_buf *data)\n-{\n-\tdma_free_coherent(data->dev, data->size + NTMP_DATA_ADDR_ALIGN,\n-\t\t\t  data->buf, data->dma);\n-}\n-\n static void ntmp_fill_request_hdr(union netc_cbd *cbd, dma_addr_t dma,\n \t\t\t\t  int len, int table_id, int cmd,\n \t\t\t\t  int access_method)\n@@ -235,37 +259,36 @@ static int ntmp_delete_entry_by_id(struct ntmp_user *user, int tbl_id,\n \t\t\t\t   u8 tbl_ver, u32 entry_id, u32 req_len,\n \t\t\t\t   u32 resp_len)\n {\n-\tstruct ntmp_dma_buf data = {\n-\t\t.dev = user->dev,\n+\tstruct netc_swcbd swcbd = {\n \t\t.size = max(req_len, resp_len),\n \t};\n \tstruct ntmp_req_by_eid *req;\n \tunion netc_cbd cbd;\n \tint err;\n \n-\terr = ntmp_alloc_data_mem(&data, (void **)&req);\n+\terr = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);\n \tif (err)\n \t\treturn err;\n \n \tntmp_fill_crd_eid(req, tbl_ver, 0, 0, entry_id);\n-\tntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(req_len, resp_len),\n+\tntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(req_len, resp_len),\n \t\t\t      tbl_id, NTMP_CMD_DELETE, NTMP_AM_ENTRY_ID);\n \n-\terr = netc_xmit_ntmp_cmd(user, &cbd);\n+\terr = netc_xmit_ntmp_cmd(user, &cbd, &swcbd);\n \tif (err)\n \t\tdev_err(user->dev,\n \t\t\t\"Failed to delete entry 0x%x of %s, err: %pe\",\n \t\t\tentry_id, ntmp_table_name(tbl_id), ERR_PTR(err));\n \n-\tntmp_free_data_mem(&data);\n-\n \treturn err;\n }\n \n static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,\n-\t\t\t\t  u32 len, struct ntmp_req_by_eid *req,\n-\t\t\t\t  dma_addr_t dma, bool compare_eid)\n+\t\t\t\t  struct ntmp_req_by_eid *req,\n+\t\t\t\t  struct netc_swcbd *swcbd,\n+\t\t\t\t  bool compare_eid)\n {\n+\tu32 len = NTMP_LEN(sizeof(*req), swcbd->size);\n \tstruct ntmp_cmn_resp_query *resp;\n \tint cmd = NTMP_CMD_QUERY;\n \tunion netc_cbd cbd;\n@@ -277,8 +300,9 @@ static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,\n \t\tcmd = NTMP_CMD_QU;\n \n \t/* Request header */\n-\tntmp_fill_request_hdr(&cbd, dma, len, tbl_id, cmd, NTMP_AM_ENTRY_ID);\n-\terr = netc_xmit_ntmp_cmd(user, &cbd);\n+\tntmp_fill_request_hdr(&cbd, swcbd->dma, len, tbl_id, cmd,\n+\t\t\t      NTMP_AM_ENTRY_ID);\n+\terr = netc_xmit_ntmp_cmd(user, &cbd, swcbd);\n \tif (err) {\n \t\tdev_err(user->dev,\n \t\t\t\"Failed to query entry 0x%x of %s, err: %pe\\n\",\n@@ -306,15 +330,14 @@ static int ntmp_query_entry_by_id(struct ntmp_user *user, int tbl_id,\n int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,\n \t\t\tstruct maft_entry_data *maft)\n {\n-\tstruct ntmp_dma_buf data = {\n-\t\t.dev = user->dev,\n+\tstruct netc_swcbd swcbd = {\n \t\t.size = sizeof(struct maft_req_add),\n \t};\n \tstruct maft_req_add *req;\n \tunion netc_cbd cbd;\n \tint err;\n \n-\terr = ntmp_alloc_data_mem(&data, (void **)&req);\n+\terr = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);\n \tif (err)\n \t\treturn err;\n \n@@ -323,15 +346,13 @@ int ntmp_maft_add_entry(struct ntmp_user *user, u32 entry_id,\n \treq->keye = maft->keye;\n \treq->cfge = maft->cfge;\n \n-\tntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),\n+\tntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(swcbd.size, 0),\n \t\t\t      NTMP_MAFT_ID, NTMP_CMD_ADD, NTMP_AM_ENTRY_ID);\n-\terr = netc_xmit_ntmp_cmd(user, &cbd);\n+\terr = netc_xmit_ntmp_cmd(user, &cbd, &swcbd);\n \tif (err)\n \t\tdev_err(user->dev, \"Failed to add MAFT entry 0x%x, err: %pe\\n\",\n \t\t\tentry_id, ERR_PTR(err));\n \n-\tntmp_free_data_mem(&data);\n-\n \treturn err;\n }\n EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);\n@@ -339,33 +360,27 @@ EXPORT_SYMBOL_GPL(ntmp_maft_add_entry);\n int ntmp_maft_query_entry(struct ntmp_user *user, u32 entry_id,\n \t\t\t  struct maft_entry_data *maft)\n {\n-\tstruct ntmp_dma_buf data = {\n-\t\t.dev = user->dev,\n+\tstruct netc_swcbd swcbd = {\n \t\t.size = sizeof(struct maft_resp_query),\n \t};\n \tstruct maft_resp_query *resp;\n \tstruct ntmp_req_by_eid *req;\n \tint err;\n \n-\terr = ntmp_alloc_data_mem(&data, (void **)&req);\n+\terr = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);\n \tif (err)\n \t\treturn err;\n \n \tntmp_fill_crd_eid(req, user->tbl.maft_ver, 0, 0, entry_id);\n-\terr = ntmp_query_entry_by_id(user, NTMP_MAFT_ID,\n-\t\t\t\t     NTMP_LEN(sizeof(*req), data.size),\n-\t\t\t\t     req, data.dma, true);\n+\terr = ntmp_query_entry_by_id(user, NTMP_MAFT_ID, req, &swcbd, true);\n \tif (err)\n-\t\tgoto end;\n+\t\treturn err;\n \n \tresp = (struct maft_resp_query *)req;\n \tmaft->keye = resp->keye;\n \tmaft->cfge = resp->cfge;\n \n-end:\n-\tntmp_free_data_mem(&data);\n-\n-\treturn err;\n+\treturn 0;\n }\n EXPORT_SYMBOL_GPL(ntmp_maft_query_entry);\n \n@@ -379,8 +394,8 @@ EXPORT_SYMBOL_GPL(ntmp_maft_delete_entry);\n int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,\n \t\t\t   int count)\n {\n-\tstruct ntmp_dma_buf data = {.dev = user->dev};\n \tstruct rsst_req_update *req;\n+\tstruct netc_swcbd swcbd;\n \tunion netc_cbd cbd;\n \tint err, i;\n \n@@ -388,8 +403,8 @@ int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,\n \t\t/* HW only takes in a full 64 entry table */\n \t\treturn -EINVAL;\n \n-\tdata.size = struct_size(req, groups, count);\n-\terr = ntmp_alloc_data_mem(&data, (void **)&req);\n+\tswcbd.size = struct_size(req, groups, count);\n+\terr = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);\n \tif (err)\n \t\treturn err;\n \n@@ -399,24 +414,22 @@ int ntmp_rsst_update_entry(struct ntmp_user *user, const u32 *table,\n \tfor (i = 0; i < count; i++)\n \t\treq->groups[i] = (u8)(table[i]);\n \n-\tntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(data.size, 0),\n+\tntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(swcbd.size, 0),\n \t\t\t      NTMP_RSST_ID, NTMP_CMD_UPDATE, NTMP_AM_ENTRY_ID);\n \n-\terr = netc_xmit_ntmp_cmd(user, &cbd);\n+\terr = netc_xmit_ntmp_cmd(user, &cbd, &swcbd);\n \tif (err)\n \t\tdev_err(user->dev, \"Failed to update RSST entry, err: %pe\\n\",\n \t\t\tERR_PTR(err));\n \n-\tntmp_free_data_mem(&data);\n-\n \treturn err;\n }\n EXPORT_SYMBOL_GPL(ntmp_rsst_update_entry);\n \n int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)\n {\n-\tstruct ntmp_dma_buf data = {.dev = user->dev};\n \tstruct ntmp_req_by_eid *req;\n+\tstruct netc_swcbd swcbd;\n \tunion netc_cbd cbd;\n \tint err, i;\n \tu8 *group;\n@@ -425,21 +438,21 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)\n \t\t/* HW only takes in a full 64 entry table */\n \t\treturn -EINVAL;\n \n-\tdata.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +\n-\t\t    RSST_CFGE_DATA_SIZE(count);\n-\terr = ntmp_alloc_data_mem(&data, (void **)&req);\n+\tswcbd.size = NTMP_ENTRY_ID_SIZE + RSST_STSE_DATA_SIZE(count) +\n+\t\t     RSST_CFGE_DATA_SIZE(count);\n+\terr = ntmp_alloc_data_mem(user->dev, &swcbd, (void **)&req);\n \tif (err)\n \t\treturn err;\n \n \t/* Set the request data buffer */\n \tntmp_fill_crd_eid(req, user->tbl.rsst_ver, 0, 0, 0);\n-\tntmp_fill_request_hdr(&cbd, data.dma, NTMP_LEN(sizeof(*req), data.size),\n+\tntmp_fill_request_hdr(&cbd, swcbd.dma, NTMP_LEN(sizeof(*req), swcbd.size),\n \t\t\t      NTMP_RSST_ID, NTMP_CMD_QUERY, NTMP_AM_ENTRY_ID);\n-\terr = netc_xmit_ntmp_cmd(user, &cbd);\n+\terr = netc_xmit_ntmp_cmd(user, &cbd, &swcbd);\n \tif (err) {\n \t\tdev_err(user->dev, \"Failed to query RSST entry, err: %pe\\n\",\n \t\t\tERR_PTR(err));\n-\t\tgoto end;\n+\t\treturn err;\n \t}\n \n \tgroup = (u8 *)req;\n@@ -447,10 +460,7 @@ int ntmp_rsst_query_entry(struct ntmp_user *user, u32 *table, int count)\n \tfor (i = 0; i < count; i++)\n \t\ttable[i] = group[i];\n \n-end:\n-\tntmp_free_data_mem(&data);\n-\n-\treturn err;\n+\treturn 0;\n }\n EXPORT_SYMBOL_GPL(ntmp_rsst_query_entry);\n \ndiff --git a/drivers/net/ethernet/freescale/enetc/ntmp_private.h b/drivers/net/ethernet/freescale/enetc/ntmp_private.h\nindex 7a53db8740db..5ae6f8b92700 100644\n--- a/drivers/net/ethernet/freescale/enetc/ntmp_private.h\n+++ b/drivers/net/ethernet/freescale/enetc/ntmp_private.h\n@@ -13,6 +13,7 @@\n #define NTMP_EID_REQ_LEN\t8\n #define NETC_CBDR_BD_NUM\t256\n #define NETC_CBDRCIR_INDEX\tGENMASK(9, 0)\n+#define NETC_CBDR_CLEAN_WORK\t16\n \n union netc_cbd {\n \tstruct {\n@@ -55,13 +56,6 @@ union netc_cbd {\n \t} resp_hdr; /* NTMP Response Message Header Format */\n };\n \n-struct ntmp_dma_buf {\n-\tstruct device *dev;\n-\tsize_t size;\n-\tvoid *buf;\n-\tdma_addr_t dma;\n-};\n-\n struct ntmp_cmn_req_data {\n \t__le16 update_act;\n \tu8 dbg_opt;\ndiff --git a/include/linux/fsl/ntmp.h b/include/linux/fsl/ntmp.h\nindex 916dc4fe7de3..83a449b4d6ec 100644\n--- a/include/linux/fsl/ntmp.h\n+++ b/include/linux/fsl/ntmp.h\n@@ -31,6 +31,12 @@ struct netc_tbl_vers {\n \tu8 rsst_ver;\n };\n \n+struct netc_swcbd {\n+\tvoid *buf;\n+\tdma_addr_t dma;\n+\tsize_t size;\n+};\n+\n struct netc_cbdr {\n \tstruct device *dev;\n \tstruct netc_cbdr_regs regs;\n@@ -44,9 +50,10 @@ struct netc_cbdr {\n \tvoid *addr_base_align;\n \tdma_addr_t dma_base;\n \tdma_addr_t dma_base_align;\n+\tstruct netc_swcbd *swcbd;\n \n \t/* Serialize the order of command BD ring */\n-\tspinlock_t ring_lock;\n+\tstruct mutex ring_lock;\n };\n \n struct ntmp_user {\n","prefixes":["net","2/2"]}