From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 143ABE6529D for ; Sun, 1 Feb 2026 16:33:42 +0000 (UTC) Received: from MA0PR01CU012.outbound.protection.outlook.com (MA0PR01CU012.outbound.protection.outlook.com [40.107.57.46]) by mx.groups.io with SMTP id smtpd.msgproc02-g2.32807.1769963618263543420 for ; Sun, 01 Feb 2026 08:33:39 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@bmwtechworks.in header.s=selector1 header.b=sicb5csz; spf=pass (domain: bmwtechworks.in, ip: 40.107.57.46, mailfrom: suresh.ha@bmwtechworks.in) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=JA2wy3Till5aaKrvUSuikrohMRraZ4EC/vURm535Ds7P2RM2Wx5ZN4LRx/73y0iI3R1BMjXrnDc71p1KW+WSDlzbDsm7SWoby1JDOwF1cN1p1zSeHKWmFdBDKzA9PaznxG2yOGXJktIgcx9VZRnx26VGZV1IjneOO4rZIAm/cttNstVHh5BkZMwDSdDwD3TpM79fmSO6IiFNJX008IfnAZcg9Iu6jc3k3PYNGBdySlj9rlKMgxCOcAmxYdgA+HPd0RGoU+l+CdO/O/1J8kJAzK/oDZ7jbR0zJqarY66UxESYAM3jy+OgNVb7QAaVvmGlAQfED+cbG4PK8WJ+Yk/y0g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; 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; bh=8SIQgIB7yYuk2Eta8hqxeAVzGc8OoL5p1/DLSQGuQMk=; b=GKJyNGPobzlUCqdB+Hynegt9NRkYE4rX35h9cNOEBpC86GZ0s8QRNrDQdupqKMJZEugNwfilgLbauNcOLo/VZlN37Z0iULCGg+WffDbRuD0oabKN05mmj2rGvrdsKNMXQ59vkdutUaoxfdolksv7KCI3MmjbEuhE/HgzvO7gUb7/WT+WKf3099v1Vdqk5MhT4bHTUfDPo0SuqVqeDPJMPEDLmXdzb84TIsyK4XhNpQdX7fa6ldVY/mgaueGUEf4zcWZHdUsiNNHKeVhxQyK5EcWEqZLvNkAdjAfY6jOqQUsVlnqb8ooQ7QcQa5JStOHAQAILfHyPHrA7wMVnstj1cw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=bmwtechworks.in; dmarc=pass action=none header.from=bmwtechworks.in; dkim=pass header.d=bmwtechworks.in; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bmwtechworks.in; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=8SIQgIB7yYuk2Eta8hqxeAVzGc8OoL5p1/DLSQGuQMk=; b=sicb5cszXHEvdXE16Cb0WqQrmf6ORFE1L8I6uVB+I+XQrYRPtNicbuBAaBBkXxdTrs5kZhjnOpoLzUfE52YwWplUeB4lOIbvE7RiZKXwkjAcbe232vy3pqeqrmOd0WLRXgcvi9cw/MTAievbqg/ZQnt217nUhZU0H15dQjwHkekaaysN7l3KYoHGmA8bW57XzKU58ycsfwFUQkQTxy56tBOR2PcEVXjL7JmjdopDUzcvtjk6loTpsC9Txlgu95MM2hD6PORin4zmJGc5TpQcktkgNpuLd8SPhpV2Z1qamQuGwsGOWeSXsZhRXxSvbWvSvAFq9BuprnZ+IcPNFAQwww== Received: from MAXP287MB4240.INDP287.PROD.OUTLOOK.COM (2603:1096:a01:15e::13) by PN6P287MB5247.INDP287.PROD.OUTLOOK.COM (2603:1096:c01:302::19) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9587.12; Sun, 1 Feb 2026 16:33:30 +0000 Received: from MAXP287MB4240.INDP287.PROD.OUTLOOK.COM ([fe80::7264:345e:328b:b469]) by MAXP287MB4240.INDP287.PROD.OUTLOOK.COM ([fe80::7264:345e:328b:b469%5]) with mapi id 15.20.9587.010; Sun, 1 Feb 2026 16:33:29 +0000 From: Suresh H A To: "openembedded-core@lists.openembedded.org" CC: Daniel Turull , Peter Marko , Marta Rybczynska , Mathieu Dubois-Briand , Richard Purdie Subject: Re: [poky][scarthgap][PATCH] improve_kernel_cve_report: add script for postprocesing of kernel CVE data Thread-Topic: [poky][scarthgap][PATCH] improve_kernel_cve_report: add script for postprocesing of kernel CVE data Thread-Index: AQHciUfxwdpx2uoQDEOSkbuNDivCjLVuHNr9 Date: Sun, 1 Feb 2026 16:33:29 +0000 Message-ID: References: <20260119133103.1151201-1-suresh.ha@bmwtechworks.in> In-Reply-To: <20260119133103.1151201-1-suresh.ha@bmwtechworks.in> Accept-Language: en-IN, en-US Content-Language: en-IN X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-reactions: allow authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=bmwtechworks.in; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: MAXP287MB4240:EE_|PN6P287MB5247:EE_ x-ms-office365-filtering-correlation-id: 2bb24ddf-8980-4e99-0073-08de61afa20c x-ms-exchange-atpmessageproperties: SA x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0;ARA:13230040|376014|1800799024|366016|8096899003|7053199007|38070700021|13003099007; x-microsoft-antispam-message-info: =?us-ascii?Q?NvKiaWwd83+Mob2dpvew8CzDdsYNdh2X57cJL99vKfg1B/iOrVV+vmzTHP3Z?= =?us-ascii?Q?LPTEGhcvJBujp6IV58VTo1NNIoLur8M1EEukwtisTEbebLAb4+Fsp+g05BzP?= =?us-ascii?Q?88ozYLK6+GTU/R5k5+iZG86PwXITwpa61ja5nh3N5qFor1aScakxxTrQRQTI?= =?us-ascii?Q?VzP6/M4CAxP2EFyILRBkm4f48DX60k0OTVoGRR2SiXwY3Y8ebYRL7F4uwGCP?= =?us-ascii?Q?Q2f0LXQE1mSxYKJrIbO1REIghBAn14qRPehu9yqWatd6Pjad6ZHKayZH1n3i?= =?us-ascii?Q?+rbXcjpCcTstKaHDV0N5KZBlqvlg6rdLJzuOs9N4XIs+94gm7Cjz/YCYsScg?= =?us-ascii?Q?8hNE0l0OUgvpsh8nBW2VQTvojQZJLK15sUSi6L9NMplfHfChBDqmp5IjJJkB?= =?us-ascii?Q?liEcsdghY5YE1ertRomqTKNevn84t7XXi92NXaEuvUyEEzat8NAUi+0rPgmb?= =?us-ascii?Q?CL/ikuJFou8k6yej+vL72Jflj7m4T0dO55SAafCnEvaTNRr4SnWvjdBAoq6Z?= =?us-ascii?Q?bfXp+q/vksCBHfpTpdQv2FgXwtmkgMPC0hF1wh50o+7+B02yxSKdVY2oxhO6?= =?us-ascii?Q?32nKBv2TI8JDlnOB0EF1hp6NSpP5hsiHCebU40YYZ+AZ0CvyvwWX+Qc3gzL1?= =?us-ascii?Q?+3ZjuspCyNXf5M7jKwgTUMIuNfNwy9Y8EXibXH6LuE8OH/3P94uh3stNArii?= =?us-ascii?Q?5ATPF/V/G8yrCvozjzrAT0rNZTe6LePy/kfFwqnXMohaqGnix4dr8lvobPmi?= =?us-ascii?Q?RGgk6UVgK1/DS6aw85EdQcPj833/k4gxUJH3W0wOWbocYWwjC53Gn6My1XYz?= =?us-ascii?Q?1s6/ozryAlZF2bEPeAZYiGA51WZTHC1djC+oxY97KxSkXJW1o0WOAIfb5szT?= =?us-ascii?Q?V4cEF02eFauxMS6Tj+0y4sPhfdHix75tsKT4wBz3KoAf/1hNLHXJJllpPKzt?= =?us-ascii?Q?I5fYno3rfXdd0Xsw1iiWTDEaEQ0cdxuSQ1DtdbpmHRBBSrstlp3F6PJquXo/?= =?us-ascii?Q?8tFUZ19aepoCBt7bSCOo6OyV1qxz/z6H9opeal3RxjO+Gqg3RADRTmbyWc0I?= =?us-ascii?Q?c2Dgs1Ti47E6WIqaC7qQAY8TWllFNa86z3Ii99WHgeWRVLEhDos0iupxj8yY?= =?us-ascii?Q?PKIC9vZ70wqktv3HBr6cC8HcQ/kSY75f8GRtIfW19oqFEh+jB495cuEG7jpb?= =?us-ascii?Q?VRyDW1o6yuLlvA0D6dSpOZHEAMoKavFVwYdSgjqBsEiB3zRx7Z3QJLjTQv9s?= =?us-ascii?Q?W1WUBl78+UPd5NcdXyG0Dvw77mV72wLyGhZdUewtVSghMA9C0LOY9TIY9+Fb?= =?us-ascii?Q?sxrPMskXatN5s6xIw34yNbLXoovxjBwvL7kjv5nL1ONes2pnMcrmyLT+DgKO?= =?us-ascii?Q?ML/Sp9XVj1peeriXIgZh5eTKlM7BbSZlju8fHhLQD2PU6FJjbjL4zSVi6D9W?= =?us-ascii?Q?nBFKkFbAJZHs0XKeWXwkZZ3X9UIwXaESTvyGBl7vQ+xjfRbLFnI05DZjXg6W?= =?us-ascii?Q?5XQoWswCnmkhZMpxEYUAfVF/WmxH/HjS8gv2ptBNAG5wXP5un3Fet6vxZj1d?= =?us-ascii?Q?JM+ezD8auhOm/RZptHSx2r06LPorckXSzIKpdVFXU+plE8BBMfQuHIqFs9Cg?= =?us-ascii?Q?abZZ7C7/kJa6bRK98KIo44E=3D?= x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:MAXP287MB4240.INDP287.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(1800799024)(366016)(8096899003)(7053199007)(38070700021)(13003099007);DIR:OUT;SFP:1101; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?JxdMp5bJSXs8j6tEMXnltPJAOQR61Dc02fT4gSy3Vib87T9yxb0yICV2g85B?= =?us-ascii?Q?OpoT7ND4t7bMD6MeQhtv4/vhHib58lDIA0BnaWFr5AaUdjaY99/QXwhqJL4V?= =?us-ascii?Q?TSFIWGHN00QGE3gmnOE9UBSP+xp/8HZhM9O4sOCHu8VhWbZfyUzaA9izGyrP?= =?us-ascii?Q?rRp5+CaxdkXKajv+528uT9J4+57zvdWv5e6sOwY8rrzJXQFrmeBdCcgLdk8f?= =?us-ascii?Q?A30hbVBxQZ9EomDMQfslsxG8/O6vP1tk8DYQsnkCAL37H7M8w+cmM8RJPTj7?= =?us-ascii?Q?1onIncjc3ttFSXBrbqNlmI5E2jdIxuETmpw83cvsIxy3IU8ISLmvLBJpBnX0?= =?us-ascii?Q?vcoL1whEzY5t0oZWaEagxA27z9tZdiiM7/+Bhc1FPvzscvi6hwBnHMo5tE96?= =?us-ascii?Q?0k0NFNCC1mIbm/lnrCHZCdTFlgK3LENJoRRuSUkhsXnXsBhA/9fxk62lnsmn?= =?us-ascii?Q?r9SIXcYH178UuQXg0wiG6zl4i8mkotXyTU422kUCuKYy1Gb1Y2Xhn3WB8XME?= =?us-ascii?Q?AfFx5kkVPb8SPaVJGQnSeZ5iLCTnE+gJxtF7h6gfyZeMiXx4l3M+KKNevItZ?= =?us-ascii?Q?Oxiel+SZDMYTB/TB28ajsMRn9ZmYXKsu1YZIC0O5KZwqHyaZakJzhiXsl6OO?= =?us-ascii?Q?orzaC7TbaynbZAEzbcc16/2TxsV9PFslwx1Fm/ygJJCqKRlBLH6OzX+tivBD?= =?us-ascii?Q?C0jIyzhCioNKeMhRnL86JuL5rQWpFxr0foDpQUlCKjvCVgQZMDVoM3rc8n4g?= =?us-ascii?Q?1HYvwI0N23os0pkVsR8Tv477bSc4YCGHlE/bYRqk9Vcw4zIh1+1yRXXhHlrS?= =?us-ascii?Q?cBopGYX2LEgcseodjgLBFCSbDwGxnaKzxSnfhCJdVnnRezASaq5ep4S0dnC7?= =?us-ascii?Q?tAvinOM/gDchI0HdQ1dnvAYh2Sw1rQZdPGJUHUnPhqAFmBt76IYu2DrACcei?= =?us-ascii?Q?7feb5IrsNXmKvAf6y6VW6vmn6qXtRpccg7kyxQXS94c0rjHKzmVm1eBYFrR1?= =?us-ascii?Q?F7mmK18xjvYBX9ceA8qVjD6XvyhnxKDo2vIh6fq5APA1NpYPX6XYsHVCrq8f?= =?us-ascii?Q?7SPZah9msk3XERu+mfYH2PJcOO40pp7baNFyV1SyLazXFMpWIM+MTcZQpML5?= =?us-ascii?Q?IZjT6rs10JSq4+SI0bgNCuOsXhezVAvdsN+a9ggiX/xScYugNXiokyrLP8O9?= =?us-ascii?Q?65xYWMkviDBFFFQ2L3W4tlRMb2G8Xb+kKruJHolfiLrLuVU8Iy/RL3U4MEJi?= =?us-ascii?Q?Xd/f5RX4HlNLGKaF4hy3FdarRcEqjg/9wSscHHaCu+XAKZWSIo4pIkO7nL70?= =?us-ascii?Q?GMtXsEb+h/EFXPyekcqTC3QIrxGdIPSuHZMrkBpfZFU337TJnz4gHgt5NovS?= =?us-ascii?Q?wneMm7kq1X/OYug7OyyJR/wZNCNUnw5zN415SuNUOYdTwk0AjWCFYFRC+Fj0?= =?us-ascii?Q?DKVut10xeF76fkg15tNu6s1Cxga1WQPo3rAIzLolhkDn+hjdrZ8hYD/3TePY?= =?us-ascii?Q?QTUwgUZDBw5ogtvbmqVBeyv38XLVwnKz9Uyz6uO9zwe/Aj4tLoaJPjzove3m?= =?us-ascii?Q?SnjjiOHJPZajl1nQd0qL4F/+p2Vufr8epDGJpELfhjq2RaGveXbVZ88juVbk?= =?us-ascii?Q?EoTFKtkz6szojM9TpOo6PfHJG986MmrBcuUhpxvg6apxxm9lM+xLYZgsO80G?= =?us-ascii?Q?in/7Qw/iosgTt0EeVOYbuUCoDIfRE8r6PWkQjnytZYqDN52na58c33u1vMtu?= =?us-ascii?Q?QSzrR7ncLhMintn5RqZkJDhaz+XsEl4=3D?= Content-Type: multipart/alternative; boundary="_000_MAXP287MB42409B58ADEACA9F748E644DEE9DAMAXP287MB4240INDP_" MIME-Version: 1.0 X-OriginatorOrg: bmwtechworks.in X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: MAXP287MB4240.INDP287.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-Network-Message-Id: 2bb24ddf-8980-4e99-0073-08de61afa20c X-MS-Exchange-CrossTenant-originalarrivaltime: 01 Feb 2026 16:33:29.8470 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 970fa6fd-1031-4cc6-8c56-488f3c61cd05 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: MEgAl6KAZklIj43JVjZwbnPhhIynyQCkJdmz+kNz39TUJBhSi3n4xoWnHz963Rx4YHZgESqc91+I40SmkpGyJcHcIQOlek+c/8huRHdrKWE= X-MS-Exchange-Transport-CrossTenantHeadersStamped: PN6P287MB5247 List-Id: X-Webhook-Received: from 45-33-107-173.ip.linodeusercontent.com [45.33.107.173] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Sun, 01 Feb 2026 16:33:41 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/230338 --_000_MAXP287MB42409B58ADEACA9F748E644DEE9DAMAXP287MB4240INDP_ Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hello maintainers, Could you please let me know whether this backport is being considered, or = if any additional information or changes are required? In addition, I noticed a few other related fixes in the mainline branch whi= ch may also be relevant for scarthgap. Please let me know if you would pref= er that I submit separate backport patches for those changes as well. The fix is relevant for the scarthgap as well, and I would appreciate any g= uidance on the status of backport. Thanks, Suresh H A ________________________________ From: Suresh H A Sent: Monday, January 19, 2026 7:01:03 PM To: openembedded-core@lists.openembedded.org ; Suresh H A Cc: Daniel Turull ; Peter Marko ; Marta Rybczynska ; Mathieu Dubois-Briand = ; Richard Purdie Subject: [poky][scarthgap][PATCH] improve_kernel_cve_report: add script for= postprocesing of kernel CVE data From: Daniel Turull Adding postprocessing script to process data from linux CNA that includes m= ore accurate metadata and it is updated directly by the source. Example of enhanced CVE from a report from cve-check: { "id": "CVE-2024-26710", "status": "Ignored", "link": "https://ind01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2= F%2Fnvd.nist.gov%2Fvuln%2Fdetail%2FCVE-2024-26710&data=3D05%7C02%7Csuresh.h= a%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd10314cc68c= 56488f3c61cd05%7C0%7C0%7C639044263030909714%7CUnknown%7CTWFpbGZsb3d8eyJFbXB= 0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIj= oyfQ%3D%3D%7C0%7C%7C%7C&sdata=3DBsKNia%2BODStTgGaRUtZpglMWs7s5Tn0cSH06R%2FN= gTK0%3D&reserved=3D0", "summary": "In the Linux kernel, the following vulnerability [...]", "scorev2": "0.0", "scorev3": "5.5", "scorev4": "0.0", "modified": "2025-03-17T15:36:11.620", "vector": "LOCAL", "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H", "detail": "not-applicable-config", "description": "Source code not compiled by config. ['arch/powerpc/includ= e/asm/thread_info.h']" }, And same from a report generated with vex: { "id": "CVE-2024-26710", "status": "Ignored", "link": "https://ind01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2= F%2Fnvd.nist.gov%2Fvuln%2Fdetail%2FCVE-2024-26710&data=3D05%7C02%7Csuresh.h= a%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd10314cc68c= 56488f3c61cd05%7C0%7C0%7C639044263030930030%7CUnknown%7CTWFpbGZsb3d8eyJFbXB= 0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIj= oyfQ%3D%3D%7C0%7C%7C%7C&sdata=3DbNwat5zDiTj6qNii7ZwAO2nW%2BWr0tpn1FqDMVrT%2= FkjE%3D&reserved=3D0", "detail": "not-applicable-config", "description": "Source code not compiled by config. ['arch/powerpc/includ= e/asm/thread_info.h']" }, For unpatched CVEs, provide more context in the description: Tested with 6.12.22 kernel { "id": "CVE-2025-39728", "status": "Unpatched", "link": "https://ind01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2= F%2Fnvd.nist.gov%2Fvuln%2Fdetail%2FCVE-2025-39728&data=3D05%7C02%7Csuresh.h= a%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd10314cc68c= 56488f3c61cd05%7C0%7C0%7C639044263030942329%7CUnknown%7CTWFpbGZsb3d8eyJFbXB= 0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIj= oyfQ%3D%3D%7C0%7C%7C%7C&sdata=3D%2FbXetEZuocKcHrchGkGoLU2rKhPy605fM%2BRygKf= w10I%3D&reserved=3D0", "summary": "In the Linux kernel, the following vulnerability has been [..= .], "scorev2": "0.0", "scorev3": "0.0", "scorev4": "0.0", "modified": "2025-04-21T14:23:45.950", "vector": "UNKNOWN", "vectorString": "UNKNOWN", "detail": "version-in-range", "description": "Needs backporting (fixed from 6.12.23)" }, CC: Peter Marko CC: Marta Rybczynska Signed-off-by: Daniel Turull Signed-off-by: Mathieu Dubois-Briand Signed-off-by: Richard Purdie (cherry picked from commit e60b1759c1aea5b8f5317e46608f0a3e782ecf57) Signed-off-by: Suresh H A --- scripts/contrib/improve_kernel_cve_report.py | 467 +++++++++++++++++++ 1 file changed, 467 insertions(+) create mode 100755 scripts/contrib/improve_kernel_cve_report.py diff --git a/scripts/contrib/improve_kernel_cve_report.py b/scripts/contrib= /improve_kernel_cve_report.py new file mode 100755 index 0000000000..829cc4cd30 --- /dev/null +++ b/scripts/contrib/improve_kernel_cve_report.py @@ -0,0 +1,467 @@ +#! /usr/bin/env python3 +# +# Copyright OpenEmbedded Contributors +# +# The script uses another source of CVE information from linux-vulns +# to enrich the cve-summary from cve-check or vex. +# It can also use the list of compiled files from the kernel spdx to ignor= e CVEs +# that are not affected since the files are not compiled. +# +# It creates a new json file with updated CVE information +# +# Compiled files can be extracted adding the following in local.conf +# SPDX_INCLUDE_COMPILED_SOURCES:pn-linux-yocto =3D "1" +# +# Tested with the following CVE sources: +# - https://ind01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgi= t.kernel.org%2Fpub%2Fscm%2Flinux%2Fsecurity%2Fvulns.git&data=3D05%7C02%7Csu= resh.ha%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd1031= 4cc68c56488f3c61cd05%7C0%7C0%7C639044263030955837%7CUnknown%7CTWFpbGZsb3d8e= yJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIs= IldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3DkgOmuhM5qTAwa3AODvJoeFc6pUz%2FeTmTkSd= W1RJOiqY%3D&reserved=3D0 +# - https://ind01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgi= thub.com%2FCVEProject%2FcvelistV5&data=3D05%7C02%7Csuresh.ha%40bmwtechworks= .in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd10314cc68c56488f3c61cd05%7= C0%7C0%7C639044263030969928%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWU= sIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7= C%7C%7C&sdata=3DtYCYdFOW5WGgUSVUKSt02HMCe8ynmRzOu78YCO%2Fi2UI%3D&reserved= =3D0 +# +# Example: +# python3 ./openembedded-core/scripts/contrib/improve_kernel_cve_report.py= --spdx tmp/deploy/spdx/3.0.1/qemux86_64/recipes/recipe-linux-yocto.spdx.js= on --kernel-version 6.12.27 --datadir ./vulns +# python3 ./openembedded-core/scripts/contrib/improve_kernel_cve_report.py= --spdx tmp/deploy/spdx/3.0.1/qemux86_64/recipes/recipe-linux-yocto.spdx.js= on --datadir ./vulns --old-cve-report build/tmp/log/cve/cve-summary.json +# +# SPDX-License-Identifier: GPLv2 + +import argparse +import json +import sys +import logging +import glob +import os +import pathlib +from packaging.version import Version + +def is_linux_cve(cve_info): + '''Return true is the CVE belongs to Linux''' + if not "affected" in cve_info["containers"]["cna"]: + return False + for affected in cve_info["containers"]["cna"]["affected"]: + if not "product" in affected: + return False + if affected["product"] =3D=3D "Linux" and affected["vendor"] =3D= =3D "Linux": + return True + return False + +def get_kernel_cves(datadir, compiled_files, version): + """ + Get CVEs for the kernel + """ + cves =3D {} + + check_config =3D len(compiled_files) > 0 + + base_version =3D Version(f"{version.major}.{version.minor}") + + # Check all CVES from kernel vulns + pattern =3D os.path.join(datadir, '**', "CVE-*.json") + cve_files =3D glob.glob(pattern, recursive=3DTrue) + not_applicable_config =3D 0 + fixed_as_later_backport =3D 0 + vulnerable =3D 0 + not_vulnerable =3D 0 + for cve_file in sorted(cve_files): + cve_info =3D {} + with open(cve_file, "r", encoding=3D'ISO-8859-1') as f: + cve_info =3D json.load(f) + + if len(cve_info) =3D=3D 0: + logging.error("Not valid data in %s. Aborting", cve_file) + break + + if not is_linux_cve(cve_info): + continue + cve_id =3D os.path.basename(cve_file)[:-5] + description =3D cve_info["containers"]["cna"]["descriptions"][0]["= value"] + if cve_file.find("rejected") >=3D 0: + logging.debug("%s is rejected by the CNA", cve_id) + cves[cve_id] =3D { + "id": cve_id, + "status": "Ignored", + "detail": "rejected", + "summary": description, + "description": f"Rejected by CNA" + } + continue + if any(elem in cve_file for elem in ["review", "reverved", "testin= g"]): + continue + + is_vulnerable, first_affected, last_affected, better_match_first, = better_match_last, affected_versions =3D get_cpe_applicability(cve_info, ve= rsion) + + logging.debug("%s: %s (%s - %s) (%s - %s)", cve_id, is_vulnerable,= better_match_first, better_match_last, first_affected, last_affected) + + if is_vulnerable is None: + logging.warning("%s doesn't have good metadata", cve_id) + if is_vulnerable: + is_affected =3D True + affected_files =3D [] + if check_config: + is_affected, affected_files =3D check_kernel_compiled_file= s(compiled_files, cve_info) + + if not is_affected and len(affected_files) > 0: + logging.debug( + "%s - not applicable configuration since affected file= s not compiled: %s", + cve_id, affected_files) + cves[cve_id] =3D { + "id": cve_id, + "status": "Ignored", + "detail": "not-applicable-config", + "summary": description, + "description": f"Source code not compiled by config. {= affected_files}" + } + not_applicable_config +=3D1 + # Check if we have backport + else: + if not better_match_last: + fixed_in =3D last_affected + else: + fixed_in =3D better_match_last + logging.debug("%s needs backporting (fixed from %s)", cve_= id, fixed_in) + cves[cve_id] =3D { + "id": cve_id, + "status": "Unpatched", + "detail": "version-in-range", + "summary": description, + "description": f"Needs backporting (fixed from {fi= xed_in})" + } + vulnerable +=3D 1 + if (better_match_last and + Version(f"{better_match_last.major}.{better_match_last= .minor}") =3D=3D base_version): + fixed_as_later_backport +=3D 1 + # Not vulnerable + else: + if not first_affected: + logging.debug("%s - not known affected %s", + cve_id, + better_match_last) + cves[cve_id] =3D { + "id": cve_id, + "status": "Patched", + "detail": "version-not-in-range", + "summary": description, + "description": "No CPE match" + } + not_vulnerable +=3D 1 + continue + backport_base =3D Version(f"{better_match_last.major}.{better_= match_last.minor}") + if version < first_affected: + logging.debug('%s - fixed-version: only affects %s onwards= ', + cve_id, + first_affected) + cves[cve_id] =3D { + "id": cve_id, + "status": "Patched", + "detail": "fixed-version", + "summary": description, + "description": f"only affects {first_affected} onwards= " + } + not_vulnerable +=3D 1 + elif last_affected <=3D version: + logging.debug("%s - fixed-version: Fixed from version %s", + cve_id, + last_affected) + cves[cve_id] =3D { + "id": cve_id, + "status": "Patched", + "detail": "fixed-version", + "summary": description, + "description": f"fixed-version: Fixed from version {la= st_affected}" + } + not_vulnerable +=3D 1 + elif backport_base =3D=3D base_version: + logging.debug("%s - cpe-stable-backport: Backported in %s"= , + cve_id, + better_match_last) + cves[cve_id] =3D { + "id": cve_id, + "status": "Patched", + "detail": "cpe-stable-backport", + "summary": description, + "description": f"Backported in {better_match_last}" + } + not_vulnerable +=3D 1 + else: + logging.debug("%s - version not affected %s", cve_id, str(= affected_versions)) + cves[cve_id] =3D { + "id": cve_id, + "status": "Patched", + "detail": "version-not-in-range", + "summary": description, + "description": f"Range {affected_versions}" + } + not_vulnerable +=3D 1 + + logging.info("Total CVEs ignored due to not applicable config: %d", no= t_applicable_config) + logging.info("Total CVEs not vulnerable due version-not-in-range: %d",= not_vulnerable) + logging.info("Total vulnerable CVEs: %d", vulnerable) + + logging.info("Total CVEs already backported in %s: %s", base_version, + fixed_as_later_backport) + return cves + +def read_spdx(spdx_file): + '''Open SPDX file and extract compiled files''' + with open(spdx_file, 'r', encoding=3D'ISO-8859-1') as f: + spdx =3D json.load(f) + if "spdxVersion" in spdx: + if spdx["spdxVersion"] =3D=3D "SPDX-2.2": + return read_spdx2(spdx) + if "@graph" in spdx: + return read_spdx3(spdx) + return [] + +def read_spdx2(spdx): + ''' + Read spdx2 compiled files from spdx + ''' + cfiles =3D set() + if 'files' not in spdx: + return cfiles + for item in spdx['files']: + for ftype in item['fileTypes']: + if ftype =3D=3D "SOURCE": + filename =3D item["fileName"][item["fileName"].find("/")+1= :] + cfiles.add(filename) + return cfiles + +def read_spdx3(spdx): + ''' + Read spdx3 compiled files from spdx + ''' + cfiles =3D set() + for item in spdx["@graph"]: + if "software_primaryPurpose" not in item: + continue + if item["software_primaryPurpose"] =3D=3D "source": + filename =3D item['name'][item['name'].find("/")+1:] + cfiles.add(filename) + return cfiles + +def check_kernel_compiled_files(compiled_files, cve_info): + """ + Return if a CVE affected us depending on compiled files + """ + files_affected =3D set() + is_affected =3D False + + for item in cve_info['containers']['cna']['affected']: + if "programFiles" in item: + for f in item['programFiles']: + if f not in files_affected: + files_affected.add(f) + + if len(files_affected) > 0: + for f in files_affected: + if f in compiled_files: + logging.debug("File match: %s", f) + is_affected =3D True + return is_affected, files_affected + +def get_cpe_applicability(cve_info, v): + ''' + Check if version is affected and return affected versions + ''' + base_branch =3D Version(f"{v.major}.{v.minor}") + affected =3D [] + if not 'cpeApplicability' in cve_info["containers"]["cna"]: + return None, None, None, None, None, None + + for nodes in cve_info["containers"]["cna"]["cpeApplicability"]: + for node in nodes.values(): + vulnerable =3D False + matched_branch =3D False + first_affected =3D Version("5000") + last_affected =3D Version("0") + better_match_first =3D Version("0") + better_match_last =3D Version("5000") + + if len(node[0]['cpeMatch']) =3D=3D 0: + first_affected =3D None + last_affected =3D None + better_match_first =3D None + better_match_last =3D None + + for cpe_match in node[0]['cpeMatch']: + version_start_including =3D Version("0") + version_end_excluding =3D Version("0") + if 'versionStartIncluding' in cpe_match: + version_start_including =3D Version(cpe_match['version= StartIncluding']) + else: + version_start_including =3D Version("0") + # if versionEndExcluding is missing we are in a branch, wh= ich is not fixed. + if "versionEndExcluding" in cpe_match: + version_end_excluding =3D Version(cpe_match["versionEn= dExcluding"]) + else: + # if versionEndExcluding is missing we are in a branch= , which is not fixed. + version_end_excluding =3D Version( + f"{version_start_including.major}.{version_start_i= ncluding.minor}.5000" + ) + affected.append(f" {version_start_including}-{version_end_= excluding}") + # Detect if versionEnd is in fixed in base branch. It has = precedence over the rest + branch_end =3D Version(f"{version_end_excluding.major}.{ve= rsion_end_excluding.minor}") + if branch_end =3D=3D base_branch: + if version_start_including <=3D v < version_end_exclud= ing: + vulnerable =3D cpe_match['vulnerable'] + # If we don't match in our branch, we are not vulnerab= le, + # since we have a backport + matched_branch =3D True + better_match_first =3D version_start_including + better_match_last =3D version_end_excluding + if version_start_including <=3D v < version_end_excluding = and not matched_branch: + if version_end_excluding < better_match_last: + better_match_first =3D max(version_start_including= , better_match_first) + better_match_last =3D min(better_match_last, versi= on_end_excluding) + vulnerable =3D cpe_match['vulnerable'] + matched_branch =3D True + + first_affected =3D min(version_start_including, first_affe= cted) + last_affected =3D max(version_end_excluding, last_affected= ) + # Not a better match, we use the first and last affected inste= ad of the fake .5000 + if vulnerable and better_match_last =3D=3D Version(f"{base_bra= nch}.5000"): + better_match_last =3D last_affected + better_match_first =3D first_affected + return vulnerable, first_affected, last_affected, better_match_first, = better_match_last, affected + +def copy_data(old, new): + '''Update dictionary with new entries, while keeping the old ones''' + for k in new.keys(): + old[k] =3D new[k] + return old + +# Function taken from cve_check.bbclass. Adapted to cve fields +def cve_update(cve_data, cve, entry): + # If no entry, just add it + if cve not in cve_data: + cve_data[cve] =3D entry + return + # If we are updating, there might be change in the status + if cve_data[cve]['status'] =3D=3D "Unknown": + cve_data[cve] =3D copy_data(cve_data[cve], entry) + return + if cve_data[cve]['status'] =3D=3D entry['status']: + return + if entry['status'] =3D=3D "Unpatched" and cve_data[cve]['status'] =3D= =3D "Patched": + logging.warning("CVE entry %s update from Patched to Unpatched fro= m the scan result", cve) + cve_data[cve] =3D copy_data(cve_data[cve], entry) + return + if entry['status'] =3D=3D "Patched" and cve_data[cve]['status'] =3D=3D= "Unpatched": + logging.warning("CVE entry %s update from Unpatched to Patched fro= m the scan result", cve) + cve_data[cve] =3D copy_data(cve_data[cve], entry) + return + # If we have an "Ignored", it has a priority + if cve_data[cve]['status'] =3D=3D "Ignored": + logging.debug("CVE %s not updating because Ignored", cve) + return + # If we have an "Ignored", it has a priority + if entry['status'] =3D=3D "Ignored": + cve_data[cve] =3D copy_data(cve_data[cve], entry) + logging.debug("CVE entry %s updated from Unpatched to Ignored", cv= e) + return + logging.warning("Unhandled CVE entry update for %s %s from %s %s to %s= ", + cve, cve_data[cve]['status'], cve_data[cve]['detail'], entry['sta= tus'], entry['detail']) + +def main(): + parser =3D argparse.ArgumentParser( + description=3D"Update cve-summary with kernel compiled files and k= ernel CVE information" + ) + parser.add_argument( + "-s", + "--spdx", + help=3D"SPDX2/3 for the kernel. Needs to include compiled sources"= , + ) + parser.add_argument( + "--datadir", + type=3Dpathlib.Path, + help=3D"Directory where CVE data is", + required=3DTrue + ) + parser.add_argument( + "--old-cve-report", + help=3D"CVE report to update. (Optional)", + ) + parser.add_argument( + "--kernel-version", + help=3D"Kernel version. Needed if old cve_report is not provided (= Optional)", + type=3DVersion + ) + parser.add_argument( + "--new-cve-report", + help=3D"Output file", + default=3D"cve-summary-enhance.json" + ) + parser.add_argument( + "-D", + "--debug", + help=3D'Enable debug ', + action=3D"store_true") + + args =3D parser.parse_args() + + if args.debug: + log_level=3Dlogging.DEBUG + else: + log_level=3Dlogging.INFO + logging.basicConfig(format=3D'[%(filename)s:%(lineno)d] %(message)s', = level=3Dlog_level) + + if not args.kernel_version and not args.old_cve_report: + parser.error("either --kernel-version or --old-cve-report are need= ed") + return -1 + + # by default we don't check the compiled files, unless provided + compiled_files =3D [] + if args.spdx: + compiled_files =3D read_spdx(args.spdx) + logging.info("Total compiled files %d", len(compiled_files)) + + if args.old_cve_report: + with open(args.old_cve_report, encoding=3D'ISO-8859-1') as f: + cve_report =3D json.load(f) + else: + #If summary not provided, we create one + cve_report =3D { + "version": "1", + "package": [ + { + "name": "linux-yocto", + "version": str(args.kernel_version), + "products": [ + { + "product": "linux_kernel", + "cvesInRecord": "Yes" + } + ], + "issue": [] + } + ] + } + + for pkg in cve_report['package']: + is_kernel =3D False + for product in pkg['products']: + if product['product'] =3D=3D "linux_kernel": + is_kernel=3DTrue + if not is_kernel: + continue + + kernel_cves =3D get_kernel_cves(args.datadir, + compiled_files, + Version(pkg["version"])) + logging.info("Total kernel cves from kernel CNA: %s", len(kernel_c= ves)) + cves =3D {issue["id"]: issue for issue in pkg["issue"]} + logging.info("Total kernel before processing cves: %s", len(cves)) + + for cve in kernel_cves: + cve_update(cves, cve, kernel_cves[cve]) + + pkg["issue"] =3D [] + for cve in sorted(cves): + pkg["issue"].extend([cves[cve]]) + logging.info("Total kernel cves after processing: %s", len(pkg['is= sue'])) + + with open(args.new_cve_report, "w", encoding=3D'ISO-8859-1') as f: + json.dump(cve_report, f, indent=3D2) + + return 0 + +if __name__ =3D=3D "__main__": + sys.exit(main()) + -- 2.34.1 --_000_MAXP287MB42409B58ADEACA9F748E644DEE9DAMAXP287MB4240INDP_ Content-Type: text/html; charset="us-ascii" Content-Transfer-Encoding: quoted-printable
Hello maintainers,

Co= uld you please let me know whether this backport is being considered, or if= any additional information or changes are required? 

In= addition, I noticed a few other related fixes in the mainline branch which= may also be relevant for scarthgap. Please let me know if you would prefer that I submit separate backport pat= ches for those changes as well.

Th= e fix is relevant for the scarthgap as well, and I would appreciate any gui= dance on the status of backport.


Thanks,
Suresh H A

From: Suresh H A <Suresh= .HA@bmwtechworks.in>
Sent: Monday, January 19, 2026 7:01:03 PM
To: openembedded-core@lists.openembedded.org <openembedded-core@l= ists.openembedded.org>; Suresh H A <Suresh.HA@bmwtechworks.in>
Cc: Daniel Turull <daniel.turull@ericsson.com>; Peter Marko &l= t;peter.marko@siemens.com>; Marta Rybczynska <rybczynska@gmail.com>= ;; Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com>; Richard= Purdie <richard.purdie@linuxfoundation.org>
Subject: [poky][scarthgap][PATCH] improve_kernel_cve_report: add scr= ipt for postprocesing of kernel CVE data
 
From: Daniel Turull <daniel.turull@ericsson.com= >

Adding postprocessing script to process data from linux CNA that includes m= ore accurate metadata and it is updated directly by the source.

Example of enhanced CVE from a report from cve-check:

{
  "id": "CVE-2024-26710",
  "status": "Ignored",
  "link": "https://ind01.safelinks.protection.outlook.com/?url=3Dhttps= %3A%2F%2Fnvd.nist.gov%2Fvuln%2Fdetail%2FCVE-2024-26710&data=3D05%7C02%7= Csuresh.ha%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd1= 0314cc68c56488f3c61cd05%7C0%7C0%7C639044263030909714%7CUnknown%7CTWFpbGZsb3= d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpb= CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3DBsKNia%2BODStTgGaRUtZpglMWs7s5= Tn0cSH06R%2FNgTK0%3D&reserved=3D0",
  "summary": "In the Linux kernel, the following vulner= ability [...]",
  "scorev2": "0.0",
  "scorev3": "5.5",
  "scorev4": "0.0",
  "modified": "2025-03-17T15:36:11.620",
  "vector": "LOCAL",
  "vectorString": "CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N= /I:N/A:H",
  "detail": "not-applicable-config",
  "description": "Source code not compiled by config. [= 'arch/powerpc/include/asm/thread_info.h']"
},

And same from a report generated with vex:
{
  "id": "CVE-2024-26710",
  "status": "Ignored",
  "link": "https://ind01.safelinks.protection.outlook.com/?url=3Dhttps= %3A%2F%2Fnvd.nist.gov%2Fvuln%2Fdetail%2FCVE-2024-26710&data=3D05%7C02%7= Csuresh.ha%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd1= 0314cc68c56488f3c61cd05%7C0%7C0%7C639044263030930030%7CUnknown%7CTWFpbGZsb3= d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpb= CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3DbNwat5zDiTj6qNii7ZwAO2nW%2BWr0= tpn1FqDMVrT%2FkjE%3D&reserved=3D0",
  "detail": "not-applicable-config",
  "description": "Source code not compiled by config. [= 'arch/powerpc/include/asm/thread_info.h']"
},

For unpatched CVEs, provide more context in the description:
Tested with 6.12.22 kernel
{
  "id": "CVE-2025-39728",
  "status": "Unpatched",
  "link": "https://ind01.safelinks.protection.outlook.com/?url=3Dhttps= %3A%2F%2Fnvd.nist.gov%2Fvuln%2Fdetail%2FCVE-2025-39728&data=3D05%7C02%7= Csuresh.ha%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd1= 0314cc68c56488f3c61cd05%7C0%7C0%7C639044263030942329%7CUnknown%7CTWFpbGZsb3= d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpb= CIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3D%2FbXetEZuocKcHrchGkGoLU2rKhPy= 605fM%2BRygKfw10I%3D&reserved=3D0",
  "summary": "In the Linux kernel, the following vulner= ability has been [...],
  "scorev2": "0.0",
  "scorev3": "0.0",
  "scorev4": "0.0",
  "modified": "2025-04-21T14:23:45.950",
  "vector": "UNKNOWN",
  "vectorString": "UNKNOWN",
  "detail": "version-in-range",
  "description": "Needs backporting (fixed from 6.12.23= )"
},

CC: Peter Marko <peter.marko@siemens.com>
CC: Marta Rybczynska <rybczynska@gmail.com>
Signed-off-by: Daniel Turull <daniel.turull@ericsson.com>
Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com&= gt;
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org> (cherry picked from commit e60b1759c1aea5b8f5317e46608f0a3e782ecf57)
Signed-off-by: Suresh H A <suresh.ha@bmwtechworks.in>
---
 scripts/contrib/improve_kernel_cve_report.py | 467 ++++++++++++++++++= +
 1 file changed, 467 insertions(+)
 create mode 100755 scripts/contrib/improve_kernel_cve_report.py

diff --git a/scripts/contrib/improve_kernel_cve_report.py b/scripts/contrib= /improve_kernel_cve_report.py
new file mode 100755
index 0000000000..829cc4cd30
--- /dev/null
+++ b/scripts/contrib/improve_kernel_cve_report.py
@@ -0,0 +1,467 @@
+#! /usr/bin/env python3
+#
+# Copyright OpenEmbedded Contributors
+#
+# The script uses another source of CVE information from linux-vulns
+# to enrich the cve-summary from cve-check or vex.
+# It can also use the list of compiled files from the kernel spdx to ignor= e CVEs
+# that are not affected since the files are not compiled.
+#
+# It creates a new json file with updated CVE information
+#
+# Compiled files can be extracted adding the following in local.conf
+# SPDX_INCLUDE_COMPILED_SOURCES:pn-linux-yocto =3D "1"
+#
+# Tested with the following CVE sources:
+# - ht= tps://ind01.safelinks.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgit.kerne= l.org%2Fpub%2Fscm%2Flinux%2Fsecurity%2Fvulns.git&data=3D05%7C02%7Csures= h.ha%40bmwtechworks.in%7Cdd87cc08dfad491b4c5b08de575f1452%7C970fa6fd10314cc= 68c56488f3c61cd05%7C0%7C0%7C639044263030955837%7CUnknown%7CTWFpbGZsb3d8eyJF= bXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMCIsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIld= UIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata=3DkgOmuhM5qTAwa3AODvJoeFc6pUz%2FeTmTkS= dW1RJOiqY%3D&reserved=3D0
+# - https://ind01.safe= links.protection.outlook.com/?url=3Dhttps%3A%2F%2Fgithub.com%2FCVEProject%2= FcvelistV5&data=3D05%7C02%7Csuresh.ha%40bmwtechworks.in%7Cdd87cc08dfad4= 91b4c5b08de575f1452%7C970fa6fd10314cc68c56488f3c61cd05%7C0%7C0%7C6390442630= 30969928%7CUnknown%7CTWFpbGZsb3d8eyJFbXB0eU1hcGkiOnRydWUsIlYiOiIwLjAuMDAwMC= IsIlAiOiJXaW4zMiIsIkFOIjoiTWFpbCIsIldUIjoyfQ%3D%3D%7C0%7C%7C%7C&sdata= =3DtYCYdFOW5WGgUSVUKSt02HMCe8ynmRzOu78YCO%2Fi2UI%3D&reserved=3D0 +#
+# Example:
+# python3 ./openembedded-core/scripts/contrib/improve_kernel_cve_report.py= --spdx tmp/deploy/spdx/3.0.1/qemux86_64/recipes/recipe-linux-yocto.spdx.js= on --kernel-version 6.12.27 --datadir ./vulns
+# python3 ./openembedded-core/scripts/contrib/improve_kernel_cve_report.py= --spdx tmp/deploy/spdx/3.0.1/qemux86_64/recipes/recipe-linux-yocto.spdx.js= on --datadir ./vulns --old-cve-report build/tmp/log/cve/cve-summary.json +#
+# SPDX-License-Identifier: GPLv2
+
+import argparse
+import json
+import sys
+import logging
+import glob
+import os
+import pathlib
+from packaging.version import Version
+
+def is_linux_cve(cve_info):
+    '''Return true is the CVE belongs to Linux'''
+    if not "affected" in cve_info["container= s"]["cna"]:
+        return False
+    for affected in cve_info["containers"]["= cna"]["affected"]:
+        if not "product" in a= ffected:
+            return = False
+        if affected["product"= ] =3D=3D "Linux" and affected["vendor"] =3D=3D "Li= nux":
+            return = True
+    return False
+
+def get_kernel_cves(datadir, compiled_files, version):
+    """
+    Get CVEs for the kernel
+    """
+    cves =3D {}
+
+    check_config =3D len(compiled_files) > 0
+
+    base_version =3D Version(f"{version.major}.{versio= n.minor}")
+
+    # Check all CVES from kernel vulns
+    pattern =3D os.path.join(datadir, '**', "CVE-*.jso= n")
+    cve_files =3D glob.glob(pattern, recursive=3DTrue)
+    not_applicable_config =3D 0
+    fixed_as_later_backport =3D 0
+    vulnerable =3D 0
+    not_vulnerable =3D 0
+    for cve_file in sorted(cve_files):
+        cve_info =3D {}
+        with open(cve_file, "r&quo= t;, encoding=3D'ISO-8859-1') as f:
+            cve_inf= o =3D json.load(f)
+
+        if len(cve_info) =3D=3D 0:
+            logging= .error("Not valid data in %s. Aborting", cve_file)
+            break +
+        if not is_linux_cve(cve_info):<= br> +            continu= e
+        cve_id =3D os.path.basename(cve= _file)[:-5]
+        description =3D cve_info["= containers"]["cna"]["descriptions"][0]["value= "]
+        if cve_file.find("rejected= ") >=3D 0:
+            logging= .debug("%s is rejected by the CNA", cve_id)
+            cves[cv= e_id] =3D {
+            &n= bsp;   "id": cve_id,
+            &n= bsp;   "status": "Ignored",
+            &n= bsp;   "detail": "rejected",
+            &n= bsp;   "summary": description,
+            &n= bsp;   "description": f"Rejected by CNA"
+            }
+            continu= e
+        if any(elem in cve_file for ele= m in ["review", "reverved", "testing"]):
+            continu= e
+
+        is_vulnerable, first_affected, = last_affected, better_match_first, better_match_last, affected_versions =3D= get_cpe_applicability(cve_info, version)
+
+        logging.debug("%s: %s (%s = - %s) (%s - %s)", cve_id, is_vulnerable, better_match_first, better_ma= tch_last, first_affected, last_affected)
+
+        if is_vulnerable is None:
+            logging= .warning("%s doesn't have good metadata", cve_id)
+        if is_vulnerable:
+            is_affe= cted =3D True
+            affecte= d_files =3D []
+            if chec= k_config:
+            &n= bsp;   is_affected, affected_files =3D check_kernel_compiled_file= s(compiled_files, cve_info)
+
+            if not = is_affected and len(affected_files) > 0:
+            &n= bsp;   logging.debug(
+            &n= bsp;       "%s - not applicable configur= ation since affected files not compiled: %s",
+            &n= bsp;       cve_id, affected_files)
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;       "id": cve_id,
+            &n= bsp;       "status": "Ignored&= quot;,
+            &n= bsp;       "detail": "not-appl= icable-config",
+            &n= bsp;       "summary": description,<= br> +            &n= bsp;       "description": f"So= urce code not compiled by config. {affected_files}"
+            &n= bsp;   }
+            &n= bsp;   not_applicable_config +=3D1
+            # Check= if we have backport
+            else: +            &n= bsp;   if not better_match_last:
+            &n= bsp;       fixed_in =3D last_affected
+            &n= bsp;   else:
+            &n= bsp;       fixed_in =3D better_match_last
+            &n= bsp;   logging.debug("%s needs backporting (fixed from %s)&q= uot;, cve_id, fixed_in)
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;           "id&q= uot;: cve_id,
+            &n= bsp;           "stat= us": "Unpatched",
+            &n= bsp;           "deta= il": "version-in-range",
+            &n= bsp;           "summ= ary": description,
+            &n= bsp;           "desc= ription": f"Needs backporting (fixed from {fixed_in})"
+            &n= bsp;   }
+            &n= bsp;   vulnerable +=3D 1
+            &n= bsp;   if (better_match_last and
+            &n= bsp;       Version(f"{better_match_last.= major}.{better_match_last.minor}") =3D=3D base_version):
+            &n= bsp;       fixed_as_later_backport +=3D 1
+        # Not vulnerable
+        else:
+            if not = first_affected:
+            &n= bsp;   logging.debug("%s - not known affected %s",
+            &n= bsp;            = ;     cve_id,
+            &n= bsp;            = ;     better_match_last)
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;       "id": cve_id,
+            &n= bsp;       "status": "Patched&= quot;,
+            &n= bsp;       "detail": "version-= not-in-range",
+            &n= bsp;       "summary": description,<= br> +            &n= bsp;       "description": "No = CPE match"
+            &n= bsp;   }
+            &n= bsp;   not_vulnerable +=3D 1
+            &n= bsp;   continue
+            backpor= t_base =3D Version(f"{better_match_last.major}.{better_match_last.mino= r}")
+            if vers= ion < first_affected:
+            &n= bsp;   logging.debug('%s - fixed-version: only affects %s onwards= ',
+            &n= bsp;            = ;     cve_id,
+            &n= bsp;            = ;     first_affected)
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;       "id": cve_id,
+            &n= bsp;       "status": "Patched&= quot;,
+            &n= bsp;       "detail": "fixed-ve= rsion",
+            &n= bsp;       "summary": description,<= br> +            &n= bsp;       "description": f"on= ly affects {first_affected} onwards"
+            &n= bsp;   }
+            &n= bsp;   not_vulnerable +=3D 1
+            elif la= st_affected <=3D version:
+            &n= bsp;   logging.debug("%s - fixed-version: Fixed from version= %s",
+            &n= bsp;            = ;     cve_id,
+            &n= bsp;            = ;     last_affected)
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;       "id": cve_id,
+            &n= bsp;       "status": "Patched&= quot;,
+            &n= bsp;       "detail": "fixed-ve= rsion",
+            &n= bsp;       "summary": description,<= br> +            &n= bsp;       "description": f"fi= xed-version: Fixed from version {last_affected}"
+            &n= bsp;   }
+            &n= bsp;   not_vulnerable +=3D 1
+            elif ba= ckport_base =3D=3D base_version:
+            &n= bsp;   logging.debug("%s - cpe-stable-backport: Backported i= n %s",
+            &n= bsp;            = ;     cve_id,
+            &n= bsp;            = ;     better_match_last)
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;       "id": cve_id,
+            &n= bsp;       "status": "Patched&= quot;,
+            &n= bsp;       "detail": "cpe-stab= le-backport",
+            &n= bsp;       "summary": description,<= br> +            &n= bsp;       "description": f"Ba= ckported in {better_match_last}"
+            &n= bsp;   }
+            &n= bsp;   not_vulnerable +=3D 1
+            else: +            &n= bsp;   logging.debug("%s - version not affected %s", cv= e_id, str(affected_versions))
+            &n= bsp;   cves[cve_id] =3D {
+            &n= bsp;       "id": cve_id,
+            &n= bsp;       "status": "Patched&= quot;,
+            &n= bsp;       "detail": "version-= not-in-range",
+            &n= bsp;       "summary": description,<= br> +            &n= bsp;       "description": f"Ra= nge {affected_versions}"
+            &n= bsp;   }
+            &n= bsp;   not_vulnerable +=3D 1
+
+    logging.info("Total CVEs ignored due to not applic= able config: %d", not_applicable_config)
+    logging.info("Total CVEs not vulnerable due versio= n-not-in-range: %d", not_vulnerable)
+    logging.info("Total vulnerable CVEs: %d", vul= nerable)
+
+    logging.info("Total CVEs already backported in %s:= %s", base_version,
+            &n= bsp;       fixed_as_later_backport)
+    return cves
+
+def read_spdx(spdx_file):
+    '''Open SPDX file and extract compiled files'''
+    with open(spdx_file, 'r', encoding=3D'ISO-8859-1') as f= :
+        spdx =3D json.load(f)
+        if "spdxVersion" in s= pdx:
+            if spdx= ["spdxVersion"] =3D=3D "SPDX-2.2":
+            &n= bsp;   return read_spdx2(spdx)
+        if "@graph" in spdx:<= br> +            return = read_spdx3(spdx)
+    return []
+
+def read_spdx2(spdx):
+    '''
+    Read spdx2 compiled files from spdx
+    '''
+    cfiles =3D set()
+    if 'files' not in spdx:
+        return cfiles
+    for item in spdx['files']:
+        for ftype in item['fileTypes']:=
+            if ftyp= e =3D=3D "SOURCE":
+            &n= bsp;   filename =3D item["fileName"][item["fileNam= e"].find("/")+1:]
+            &n= bsp;   cfiles.add(filename)
+    return cfiles
+
+def read_spdx3(spdx):
+    '''
+    Read spdx3 compiled files from spdx
+    '''
+    cfiles =3D set()
+    for item in spdx["@graph"]:
+        if "software_primaryPurpos= e" not in item:
+            continu= e
+        if item["software_primaryP= urpose"] =3D=3D "source":
+            filenam= e =3D item['name'][item['name'].find("/")+1:]
+            cfiles.= add(filename)
+    return cfiles
+
+def check_kernel_compiled_files(compiled_files, cve_info):
+    """
+    Return if a CVE affected us depending on compiled files=
+    """
+    files_affected =3D set()
+    is_affected =3D False
+
+    for item in cve_info['containers']['cna']['affected']:<= br> +        if "programFiles" in = item:
+            for f i= n item['programFiles']:
+            &n= bsp;   if f not in files_affected:
+            &n= bsp;       files_affected.add(f)
+
+    if len(files_affected) > 0:
+        for f in files_affected:
+            if f in= compiled_files:
+            &n= bsp;   logging.debug("File match: %s", f)
+            &n= bsp;   is_affected =3D True
+    return is_affected, files_affected
+
+def get_cpe_applicability(cve_info, v):
+    '''
+    Check if version is affected and return affected versio= ns
+    '''
+    base_branch =3D Version(f"{v.major}.{v.minor}"= ;)
+    affected =3D []
+    if not 'cpeApplicability' in cve_info["containers&= quot;]["cna"]:
+        return None, None, None, None, = None, None
+
+    for nodes in cve_info["containers"]["cna= "]["cpeApplicability"]:
+        for node in nodes.values():
+            vulnera= ble =3D False
+            matched= _branch =3D False
+            first_a= ffected =3D Version("5000")
+            last_af= fected =3D Version("0")
+            better_= match_first =3D Version("0")
+            better_= match_last =3D Version("5000")
+
+            if len(= node[0]['cpeMatch']) =3D=3D 0:
+            &n= bsp;   first_affected =3D None
+            &n= bsp;   last_affected =3D None
+            &n= bsp;   better_match_first =3D None
+            &n= bsp;   better_match_last =3D None
+
+            for cpe= _match in node[0]['cpeMatch']:
+            &n= bsp;   version_start_including =3D Version("0")
+            &n= bsp;   version_end_excluding =3D Version("0")
+            &n= bsp;   if 'versionStartIncluding' in cpe_match:
+            &n= bsp;       version_start_including =3D Versio= n(cpe_match['versionStartIncluding'])
+            &n= bsp;   else:
+            &n= bsp;       version_start_including =3D Versio= n("0")
+            &n= bsp;   # if versionEndExcluding is missing we are in a branch, wh= ich is not fixed.
+            &n= bsp;   if "versionEndExcluding" in cpe_match:
+            &n= bsp;       version_end_excluding =3D Version(= cpe_match["versionEndExcluding"])
+            &n= bsp;   else:
+            &n= bsp;       # if versionEndExcluding is missin= g we are in a branch, which is not fixed.
+            &n= bsp;       version_end_excluding =3D Version(=
+            &n= bsp;           f"{ve= rsion_start_including.major}.{version_start_including.minor}.5000"
+            &n= bsp;       )
+            &n= bsp;   affected.append(f" {version_start_including}-{version= _end_excluding}")
+            &n= bsp;   # Detect if versionEnd is in fixed in base branch. It has = precedence over the rest
+            &n= bsp;   branch_end =3D Version(f"{version_end_excluding.major= }.{version_end_excluding.minor}")
+            &n= bsp;   if branch_end =3D=3D base_branch:
+            &n= bsp;       if version_start_including <=3D= v < version_end_excluding:
+            &n= bsp;           vulnerable= =3D cpe_match['vulnerable']
+            &n= bsp;       # If we don't match in our branch,= we are not vulnerable,
+            &n= bsp;       # since we have a backport
+            &n= bsp;       matched_branch =3D True
+            &n= bsp;       better_match_first =3D version_sta= rt_including
+            &n= bsp;       better_match_last =3D version_end_= excluding
+            &n= bsp;   if version_start_including <=3D v < version_end_excl= uding and not matched_branch:
+            &n= bsp;       if version_end_excluding < bett= er_match_last:
+            &n= bsp;           better_mat= ch_first =3D max(version_start_including, better_match_first)
+            &n= bsp;           better_mat= ch_last =3D min(better_match_last, version_end_excluding)
+            &n= bsp;           vulnerable= =3D cpe_match['vulnerable']
+            &n= bsp;           matched_br= anch =3D True
+
+            &n= bsp;   first_affected =3D min(version_start_including, first_affe= cted)
+            &n= bsp;   last_affected =3D max(version_end_excluding, last_affected= )
+            # Not a= better match, we use the first and last affected instead of the fake .5000=
+            if vuln= erable and better_match_last =3D=3D Version(f"{base_branch}.5000"= ):
+            &n= bsp;   better_match_last =3D last_affected
+            &n= bsp;   better_match_first =3D first_affected
+    return vulnerable, first_affected, last_affected, bette= r_match_first, better_match_last, affected
+
+def copy_data(old, new):
+    '''Update dictionary with new entries, while keeping th= e old ones'''
+    for k in new.keys():
+        old[k] =3D new[k]
+    return old
+
+# Function taken from cve_check.bbclass. Adapted to cve fields
+def cve_update(cve_data, cve, entry):
+    # If no entry, just add it
+    if cve not in cve_data:
+        cve_data[cve] =3D entry
+        return
+    # If we are updating, there might be change in the stat= us
+    if cve_data[cve]['status'] =3D=3D "Unknown":<= br> +        cve_data[cve] =3D copy_data(cve= _data[cve], entry)
+        return
+    if cve_data[cve]['status'] =3D=3D entry['status']:
+        return
+    if entry['status'] =3D=3D "Unpatched" and cve= _data[cve]['status'] =3D=3D "Patched":
+        logging.warning("CVE entry= %s update from Patched to Unpatched from the scan result", cve)
+        cve_data[cve] =3D copy_data(cve= _data[cve], entry)
+        return
+    if entry['status'] =3D=3D "Patched" and cve_d= ata[cve]['status'] =3D=3D "Unpatched":
+        logging.warning("CVE entry= %s update from Unpatched to Patched from the scan result", cve)
+        cve_data[cve] =3D copy_data(cve= _data[cve], entry)
+        return
+    # If we have an "Ignored", it has a priority<= br> +    if cve_data[cve]['status'] =3D=3D "Ignored":<= br> +        logging.debug("CVE %s not = updating because Ignored", cve)
+        return
+    # If we have an "Ignored", it has a priority<= br> +    if entry['status'] =3D=3D "Ignored":
+        cve_data[cve] =3D copy_data(cve= _data[cve], entry)
+        logging.debug("CVE entry %= s updated from Unpatched to Ignored", cve)
+        return
+    logging.warning("Unhandled CVE entry update for %s= %s from %s %s to %s",
+        cve, cve_data[cve]['status'], c= ve_data[cve]['detail'],  entry['status'], entry['detail'])
+
+def main():
+    parser =3D argparse.ArgumentParser(
+        description=3D"Update cve-= summary with kernel compiled files and kernel CVE information"
+    )
+    parser.add_argument(
+        "-s",
+        "--spdx",
+        help=3D"SPDX2/3 for the ke= rnel. Needs to include compiled sources",
+    )
+    parser.add_argument(
+        "--datadir",
+        type=3Dpathlib.Path,
+        help=3D"Directory where CV= E data is",
+        required=3DTrue
+    )
+    parser.add_argument(
+        "--old-cve-report", +        help=3D"CVE report to upda= te. (Optional)",
+    )
+    parser.add_argument(
+        "--kernel-version", +        help=3D"Kernel version. Ne= eded if old cve_report is not provided (Optional)",
+        type=3DVersion
+    )
+    parser.add_argument(
+        "--new-cve-report", +        help=3D"Output file",=
+        default=3D"cve-summary-enh= ance.json"
+    )
+    parser.add_argument(
+        "-D",
+        "--debug",
+        help=3D'Enable debug ',
+        action=3D"store_true"= )
+
+    args =3D parser.parse_args()
+
+    if args.debug:
+        log_level=3Dlogging.DEBUG
+    else:
+        log_level=3Dlogging.INFO
+    logging.basicConfig(format=3D'[%(filename)s:%(lineno)d]= %(message)s', level=3Dlog_level)
+
+    if not args.kernel_version and not args.old_cve_report:=
+        parser.error("either --ker= nel-version or --old-cve-report are needed")
+        return -1
+
+    # by default we don't check the compiled files, unless = provided
+    compiled_files =3D []
+    if args.spdx:
+        compiled_files =3D read_spdx(ar= gs.spdx)
+        logging.info("Total compil= ed files %d", len(compiled_files))
+
+    if args.old_cve_report:
+        with open(args.old_cve_report, = encoding=3D'ISO-8859-1') as f:
+            cve_rep= ort =3D json.load(f)
+    else:
+        #If summary not provided, we cr= eate one
+        cve_report =3D {
+            "v= ersion": "1",
+            "p= ackage": [
+            &n= bsp;   {
+            &n= bsp;       "name": "linux-yoct= o",
+            &n= bsp;       "version": str(args.kern= el_version),
+            &n= bsp;       "products": [
+            &n= bsp;           {
+            &n= bsp;            = ;   "product": "linux_kernel",
+            &n= bsp;            = ;   "cvesInRecord": "Yes"
+            &n= bsp;           }
+            &n= bsp;       ],
+            &n= bsp;       "issue": []
+            &n= bsp;   }
+            ]
+        }
+
+    for pkg in cve_report['package']:
+        is_kernel =3D False
+        for product in pkg['products']:=
+            if prod= uct['product'] =3D=3D "linux_kernel":
+            &n= bsp;   is_kernel=3DTrue
+        if not is_kernel:
+            continu= e
+
+        kernel_cves =3D get_kernel_cves= (args.datadir,
+            &n= bsp;            = ;             c= ompiled_files,
+            &n= bsp;            = ;             V= ersion(pkg["version"]))
+        logging.info("Total kernel= cves from kernel CNA: %s", len(kernel_cves))
+        cves =3D {issue["id"]= : issue for issue in pkg["issue"]}
+        logging.info("Total kernel= before processing cves: %s", len(cves))
+
+        for cve in kernel_cves:
+            cve_upd= ate(cves, cve, kernel_cves[cve])
+
+        pkg["issue"] =3D [] +        for cve in sorted(cves):
+            pkg[&qu= ot;issue"].extend([cves[cve]])
+        logging.info("Total kernel= cves after processing: %s", len(pkg['issue']))
+
+    with open(args.new_cve_report, "w", encoding= =3D'ISO-8859-1') as f:
+        json.dump(cve_report, f, indent= =3D2)
+
+    return 0
+
+if __name__ =3D=3D "__main__":
+    sys.exit(main())
+
--
2.34.1

--_000_MAXP287MB42409B58ADEACA9F748E644DEE9DAMAXP287MB4240INDP_--