From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91FE140926C; Fri, 21 Aug 2026 19:53:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342021; cv=none; b=eL5UmItAB0fI/RL2SB9v8n9T73CVanjDaDVb3RrRn5nGj6MUGtvWwix9BQ+ppN5n23nDGTSq5ZXGZapgzOwntosj1pcsIhFuF3eUt1fy5dYxqs2CgjGDCQhiA/bPxvJiIqbdLi01G6wBMu/mEeNHY75FEWySU0kft3yb9Z0JixA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342021; c=relaxed/simple; bh=CXyGtsG81Jje362NCcX1DJbpQJ04vztCnyVvNnO2UEk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mNcLlmMahWwcdHLQIHlMdp+ImC+yCHVt/QJVh7X8/RNNp/zEqRWkeIdiODtadOUp2v/hxKQ2/Az2IybXJdvSdojsCReQcyM9uKE+LkNlKruv+rtdM6+OTgLrVEeW8pVFSbt2t6nKEi15sTWHcdp1f2f0RY1c3FyV8P2T4W8wgr8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=TIoNWO2p; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="TIoNWO2p" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVYr22363665; Fri, 21 Aug 2026 19:53:10 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=nr3NDJBPuN6JMZiT2 70FS3PTS8cjMVDUb7jnJwSlxDk=; b=TIoNWO2pXEQQcx41cG6G1cZc6AsIDSIGn Wb6VvrB85FB8kZ7ovAwdGGphjCJid3rnhHlEMn+Bp+fuTnGJrejFhF3yRm52cKs6 iICVYtlLYoxdjgFpfaqbXio70MXg605Ob2kmx2RGVvkoMg6zaoaXxa5RWvVoDHRA aBNy6a9FV+bX43A1EbVxh8uxl88u3UQef8cwBrEcFCakVw38nVNHx/M+T3gD1ux3 nVlbUNg/xLQ5YYYgYh4qGvd9jJDYcFPtk3i4fqcOW/3/iB2CzI9ctwtNG7BoxRoM tNo4KG7NDYekoZIgt3rGOS6iihYsx0xyA8TE/UTkbyrI6jtDMa3zw== Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0uxke-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfGQ8006048; Fri, 21 Aug 2026 19:53:09 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g34ngxff6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr5pE41746866 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:05 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 60A1220040; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1D6652004E; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song , Dylan Hatch Subject: [RFC PATCH v2 01/24] unwind_user: Add generic and arch-specific headers to MAINTAINERS Date: Fri, 21 Aug 2026 21:52:36 +0200 Message-ID: <20260821195259.2688377-2-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=MthiLWae c=1 sm=1 tr=0 ts=6a88aca6 cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=1XWaLZrsAAAA:8 a=meVymXHHAAAA:8 a=bzoO1hpTG78L7GYmDxgA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-ORIG-GUID: SDI9-EQ6q2zXx7KhuSOxwYIW8s8LHpr7 X-Proofpoint-GUID: 98p9ebAjyeYBcw4dCaW3l22uQLA9C8rx X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX+KHyiTHHWc6k r+4czlToVkZUn3bf6sW7iYZsjct9bCLlG873nuru3BwZ7k6bNmOKbUaR7bue+bOGwRf1rQo2LwQ TSWWOfngO6F0Lj2kHBe6/Gj2Jf+PxmQ= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX7f8sPk2P6Kmm BMmgb58gY2DWezemeHzZ+82U0mQB9iY9/0Rk2t80YXZraB6ezuryEV9Phe/uJBaolOWp1sqfQd3 MY7gM/Vawl6ulEcjl+nGyJCcNuQGDMEyRwnf8FRqXnT9Jm5UKFPaZsn2UcC7OaYpiWnKko4TgEW CGObfbw9FJg5K+MZZeK/G+OeQQrlMpRHyJp0+Oj5ElbxfO7cq0h3ArtWJHGq1Td9dpfBUuAcuGx BfZOEMbDduIjjTsbT9dr66MtxPacdnrImE8PL6O+lvJpAqBwRXxqL8eJXOAiZeZ3KMldmkg8oPm jfGV9x61TQHMkDxs8K+ARuvSrfBNHswYQUMmTaVBlbV4WEm/bJsz6LsIksXjbFwUDXAf0J/nSt7 qMWusBx1fgOfgnJGX7NX+O9y08Ru1AGdygjLVqTLh5KKNkEUIjoYcYNbdzHmPr0mL2STgn08mLD cJB2rfV6QWBkotTWgfg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 impostorscore=0 bulkscore=0 phishscore=0 clxscore=1011 spamscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Commit 71753c6ed2bf ("unwind_user: Add user space unwinding API with frame pointer support") introduced include/asm-generic/unwind_user.h without adding it to MAINTAINERS, as well as any future arch-specific versions such as the one added by commit 49cf34c0815f ("unwind_user/x86: Enable frame pointer unwinding on x86") which introduced arch/x86/include/asm/unwind_user.h. Suggested-by: Dylan Hatch Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v16 00/20] unwind_deferred: Implement sframe handling" series: https://lore.kernel.org/all/20260521142546.3908498-2-jremus@linux.ibm.c= om/ MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8014b9f8253e..e5738a250d63 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28201,6 +28201,8 @@ USERSPACE STACK UNWINDING M: Josh Poimboeuf M: Steven Rostedt S: Maintained +F: arch/*/include/asm/unwind_user.h +F: include/asm-generic/unwind_user.h F: include/linux/unwind*.h F: kernel/unwind/ =20 --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 18989411A04; Fri, 21 Aug 2026 19:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342029; cv=none; b=nCh2CxCN/tRmtmFOJRxPKIu5JBO6AwURm5sPOhoMfaXFWPplRGksOyBfsWIPvMGcwWeu6l6v7WhYvfNkJU5JZDp16UiUi//ds9AJmku5xGdCjwuUnd9WKisvr3s3DPx4uMZZBZQrcmA+QHlhQ/4PbnIVrIGJXE9D9PRFcO56CHg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342029; c=relaxed/simple; bh=uHi5IOcGGygfGL5thWHRKIwx88fWG7DAaRDICca0tMs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=O0XYwwhJZZSTr0znqKm2hiIIdy8wa/KojV4/4/PuR6wE8mxRVhza4BG1UtuOtugSUIpOdjaapP52jybVmOZB0VzkGYqrGgIjrZojSHU3xA/i7OvPXTRbxGUnpch1ezDs0Nw0xwY38MOl/+rXlBG/GT+YkqI421bazIKG2gz26sE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=j0AsUOwd; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="j0AsUOwd" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVc1Q1237144; Fri, 21 Aug 2026 19:53:11 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=vrh5RBbBhCeKqV2rA nv4MPSnT7EeQLGUnEJ73SuzaIY=; b=j0AsUOwd7sKagcWYT52cBPtHfQbSGj4r6 fvN4mVc2OM/ad51q6hXKtj/H1Z8XEo2jiCbmU/Fu+xcXdz8yw6XFCUbChMm5YCYP jl8Uin4lI1TSCiFoCYJwk/V+LeYg71LHGEdy4aTH8eV06GpsC2BS8QzhM1KPowV5 yMoPudx8pQ7Liu8s6hzE4CSMCA9bXWCJDQT3lytCNZ1N/xWg2W4K9Bl60o651jh8 xnU/CtDRPiF3JNHH+X3TjJLcJGfLZk+VUFyF0QWAZ0q0DYv0EJtADq6ifJ7AV9Yv FmOP5ZYCMfHrJTYL6gHpRaC6M2JbxfnEy8LsKQOOhMCNlyYjli5ow== Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu2kr04-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfMOS021134; Fri, 21 Aug 2026 19:53:09 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ekpnxt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr5pp41746868 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:05 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A4F5320040; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6571E20043; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 02/24] unwind_user: Stop when reaching an outermost frame Date: Fri, 21 Aug 2026 21:52:37 +0200 Message-ID: <20260821195259.2688377-3-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=AdqB2XXG c=1 sm=1 tr=0 ts=6a88aca7 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pGLkceISAAAA:8 a=_1qlYuAciRtwIPuEvDgA:9 X-Proofpoint-GUID: 0cDuk0xmKFQnbzzqAfQDY6swoHXWnBkF X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX/wdTe+ho5TvF 3NJTVBEVQMkjvsH3LtpI/3Es2Misdqnj4cuj0xE+v2cJqkFGHDoKybw8VvtvvGlO3Cp6CUFIS5h Zv+tEnl8HCNgfQDDkAx7ee3y7+Y46Z1udAdP1FC9tcuKtegpYcxjSt+CZS4DM3B4zNRzI6BdiST bWUZA8/TgE2eVX1UH8l9or9w9inaH/jESHbo0jgrac/iINgR/zTJ94zkLBjU9gF+ZzwTcgzdOya c+SV+e7JYOZ6maMNn7SDx/34fNldlFqMkm0fcXFJCshKXMQNu6iKtXYfOS/wDL9PtFyV+O8jKBe p2vnG6r5ip137v9jRLI4wF/3i5ewgiaRvG0+SSvECkNVtjDeZb48IitxthKVdWLCGR19oV+8bG7 ir/h2TBu33zsPeslzweB76sFxRm4zhjyQsRf2Zm9Rx6de2zvu7MyC2WAyevPETn38C3Xqv2Tw5j CnOfK3N3L1lTSxLcrRQ== X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX1s4UY+Dwp0J5 HHoNfbBzykp7/qLKNFwgj+HeLMURVAxOtj0uEchxbMkpToQacbgDBQwxO02LOk9+ULqwjKY4nbH P614W35Qtbf6cr6l0iPr5WoCeOjElXA= X-Proofpoint-ORIG-GUID: R9ZlvTLoT11pr4ui7G1Ybppm5xH2cl_C X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 suspectscore=0 malwarescore=0 impostorscore=0 adultscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Add an indication for an outermost frame to the unwind user frame structure and stop unwinding when reaching an outermost frame. This will be used by unwind user sframe, as SFrame may represent an undefined return address as indication for an outermost frame. Reviewed-by: Indu Bhagat Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v16 00/20] unwind_deferred: Implement sframe handling" series: https://lore.kernel.org/all/20260521142546.3908498-9-jremus@linux.ibm.c= om/ arch/x86/include/asm/unwind_user.h | 6 ++++-- include/linux/unwind_user_types.h | 1 + kernel/unwind/user.c | 6 ++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index 6e469044e4de..2dfb5ef11e36 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -23,13 +23,15 @@ static inline int unwind_user_word_size(struct pt_regs = *regs) .cfa_off =3D 2*(ws), \ .ra_off =3D -1*(ws), \ .fp_off =3D -2*(ws), \ - .use_fp =3D true, + .use_fp =3D true, \ + .outermost =3D false, =20 #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \ .cfa_off =3D 1*(ws), \ .ra_off =3D -1*(ws), \ .fp_off =3D 0, \ - .use_fp =3D false, + .use_fp =3D false, \ + .outermost =3D false, =20 static inline bool unwind_user_at_function_start(struct pt_regs *regs) { diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 412729a269bc..4fc3dd9b4e29 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -30,6 +30,7 @@ struct unwind_user_frame { s32 ra_off; s32 fp_off; bool use_fp; + bool outermost; }; =20 struct unwind_user_state { diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 90ab3c1a205e..28091ece830c 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -31,6 +31,12 @@ static int unwind_user_next_common(struct unwind_user_st= ate *state, { unsigned long cfa, fp, ra; =20 + /* Stop unwinding when reaching an outermost frame. */ + if (frame->outermost) { + state->done =3D true; + return 0; + } + /* Get the Canonical Frame Address (CFA) */ if (frame->use_fp) { if (state->fp < state->sp) --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5781C3FFFAB; Fri, 21 Aug 2026 19:53:36 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342019; cv=none; b=a9dmgf1x/ZEaAfrutTqzREskP4KRNRId0qXoHcwmwRRgKDObQnOt+nYgllsyJGHEFcXTz/D/MKm0LIY0yEv0CfM4pXHH4AU0cF/9fZb9tgIbpodj3GuNdgWrgJCfJYkS0NHp+ZR6+xyDvYAcUrKkJZw8j4wWG1DCl+IwxSfLdY4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342019; c=relaxed/simple; bh=URzcqcKildsNvgSpR2lLGV/p+z/i7pvGxHXc8UvWV84=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=akMTv/yU0bZO7K8G0DZ8B+i8pSNRKx5UaMp9jy4NLzXPbkfr5oVkA1j0Zgw9y719mtUpi47BIcUfQEs4KaanFPu7Hf5YPnQmSicV9L6irAmHsp0umYZs9M3KbI8fEclfbqBzQj7iETbVfDmRji9YFXjtLR6HDHL+kohfGESriw0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=UdFWgLSt; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="UdFWgLSt" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVhMQ491833; Fri, 21 Aug 2026 19:53:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=gD+wy2WOXKDmawHxG A2GRaC0ZcIOI/WUyr9zsMyBQes=; b=UdFWgLStueFS5PXYCMV9eD6Iad2hYvcnI wgesUwNYBqb3CSG0Tlb0K7WP831mG7bcWufuKPhvpLXZjsjw9PUpfELQzfaUWND+ AtrvTOsKdaljuck2eqqEcdBzEdBfOXO201newke6XqDWKp5vjV8+mgii0d3dN26y DRCO4KP6dDN6GUml68XbJ/DOg0430QNOfUcymPskpXfMbFw0JNXrqMnqoF700+5T H97vBklZ7AVhBPXyWKuftUBKsMzTw1QTJW15MR12LWQut62I8R6jXQ3ftf6kTiGC iUgB1aFrv+sjhKuWpBb6YoI2kAiL0uQDwhEuR/iv9539Wb7W+QlrQ== Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0kvcp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfMOT021134; Fri, 21 Aug 2026 19:53:10 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ekpnxv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr6Pi49086762 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:06 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EA44620040; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A9B9E2004B; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 03/24] unwind_user: Enable archs that pass RA in a register Date: Fri, 21 Aug 2026 21:52:38 +0200 Message-ID: <20260821195259.2688377-4-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-ORIG-GUID: CsQ34D-wem0TFAaS_C18ZH87z5nSDW8m X-Proofpoint-GUID: U1jlYB3oJKNvknEFnfPVXj96BpSbcWEZ X-Authority-Analysis: v=2.4 cv=RoX16imK c=1 sm=1 tr=0 ts=6a88aca7 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pGLkceISAAAA:8 a=lmaF1edk6S-LLGGX4wsA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXxWWo8rletH68 AXc47pnN5fvhjc/oYbDdU3JICndl8rvxRHeJiqRAudV/mcJ5/dtWr/K0pvZ9JmriIPWRAWXvUiI nc4DdE8QW80OZp9JuMhIXWN4ZMRlKTA= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX1oj2n87d0V1A +jZVS4c278t5RkTtkKDj9QZE+YF6HcPvsee3umuIOiuNnTjB2LOf6PTCtOx4dKejbF/3iJUG4Xz TYKALpZThMwZSs93GMJXPTG1kWbkSHBPOLjl6aKrMXJW5Et/U2AIrphQbDZFexq1cDQ46MFUudD fsCwiTvIrNGnc1FRiRQW2POqp3K8Mdrx/1m7HKvxmXhGzsz6a27g1ShzMM31ctwhIDqB0zBpVYS KW9qRg8nvceZgNfiIxOw6VOwmAn1k3RUrMB1BCaA/ERxIEF4eUhPXWxHT27S4s4HSb4vviW/BjE huoYsajcwysNx3a6UdXzwOSWFB2QJCBHNeLVnCUY4JDIkWLtHf0IG1M/Qww579Zon/TFZGyOc1t cU+db5nWsFdci11S566pKZ5BbypAKjM1hpext2u7GibG6sXnjEuykk9q35IxFVn7wnn+YkHqmxU hzU0uiSxVjfVa0RX84A== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 suspectscore=0 malwarescore=0 adultscore=0 clxscore=1015 phishscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Not all architectures/ABIs pass the return address (RA) on the stack on function entry, like x86-64 does due to its CALL instruction pushing the RA onto the stack. Architectures/ABIs, such as s390, also do not require the RA to be saved on the stack in the function prologue. In particular, the RA may never be saved to the stack at all, such as in leaf functions. Unwinding must therefore not assume the presence of a RA saved on stack for the topmost frame. Treat a RA offset from CFA of zero as indication that the RA is not saved (on the stack). For the topmost frame treat it as indication that the RA is in the link/RA register, such as on arm64 and s390, and obtain it from there. For non-topmost frames treat it as error, as the RA must be saved. Additionally allow the SP to be unchanged in the topmost frame, for architectures where SP at function entry =3D=3D SP at call site, such as arm64 and s390. Note that treating a RA offset from CFA of zero as indication that the RA is not saved on the stack additionally allows for architectures, such as s390, where the frame pointer (FP) may be saved without the RA being saved as well. Provided that such architectures represent this in SFrame by encoding the "missing" RA offset using a padding RA offset with a value of zero. Reviewed-by: Indu Bhagat Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v16 00/20] unwind_deferred: Implement sframe handling" series: https://lore.kernel.org/all/20260521142546.3908498-14-jremus@linux.ibm.= com/ include/linux/unwind_user.h | 10 ++++++++++ kernel/unwind/user.c | 20 ++++++++++++++++---- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index 64618618febd..941cef652435 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -23,6 +23,16 @@ static inline bool unwind_user_at_function_start(struct = pt_regs *regs) #define unwind_user_at_function_start unwind_user_at_function_start #endif =20 +#ifndef unwind_user_get_ra_reg +static inline int unwind_user_get_ra_reg(unsigned long *val) +{ + pr_debug("%s (%d): %s() not implemented\n", + current->comm, current->pid, __func__); + return -EINVAL; +} +#define unwind_user_get_ra_reg unwind_user_get_ra_reg +#endif + int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries); =20 #endif /* _LINUX_UNWIND_USER_H */ diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 28091ece830c..f8a97d4167f0 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -2,6 +2,9 @@ /* * Generic interfaces for unwinding user space */ + +#define pr_fmt(fmt) "unwind_user: " fmt + #include #include #include @@ -47,8 +50,12 @@ static int unwind_user_next_common(struct unwind_user_st= ate *state, } cfa +=3D frame->cfa_off; =20 - /* Make sure that stack is not going in wrong direction */ - if (cfa <=3D state->sp) + /* + * Make sure that stack is not going in wrong direction. Allow SP + * to be unchanged for the topmost frame, by subtracting topmost, + * which is either 0 or 1. + */ + if (cfa <=3D state->sp - state->topmost) return -EINVAL; =20 /* Make sure that the address is word aligned */ @@ -56,8 +63,13 @@ static int unwind_user_next_common(struct unwind_user_st= ate *state, return -EINVAL; =20 /* Get the Return Address (RA) */ - if (get_user_word(&ra, cfa, frame->ra_off, state->ws)) - return -EINVAL; + if (frame->ra_off) { + if (get_user_word(&ra, cfa, frame->ra_off, state->ws)) + return -EINVAL; + } else { + if (!state->topmost || unwind_user_get_ra_reg(&ra)) + return -EINVAL; + } =20 /* Get the Frame Pointer (FP) */ if (frame->fp_off && get_user_word(&fp, cfa, frame->fp_off, state->ws)) --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CE68240F72C; Fri, 21 Aug 2026 19:53:45 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342028; cv=none; b=XMaEdRChi0q3MFWR+JTvAZ0LRYUQtC49ym6kEJySORtwnz+yShYnsuv6s2/Z6L2mNfRG97jYTFz/+ndcEhBLLAkacTRrsl+BRm5Kf0FibZiMAaocFvu4RE/WKGNAWYGxLO8wcCORVpt+EEKaddaKPlHA7cZXiJXgl+K67skd2mk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342028; c=relaxed/simple; bh=+QQyByo4jRu3q83Fet4sn4qipXTG+C9lCtCzCGQstiA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=vB81k0XWqeRMrtppwi1Se3N9jEZ9gA5BriqmAVSkmPdoakHzQ+woRFcNvvX9/cRGpuirTbCrMjneaZqUM0rLoyfkfmtr/6GBH/CCSWraoZqbuAoRIAVq+rC64kH2BxXkFEQB5FpCRNZIeJ5Wltupge7iaI6J50mwaxNJze1utHs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=aY29g3W4; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="aY29g3W4" Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVaTa2387443; Fri, 21 Aug 2026 19:53:11 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Cyy3ouORVdz0AUfik DQRYaQeXKHSUi1nQaQygdWUwpo=; b=aY29g3W4Jkpg6VvGGTszYSOb8TNC9/MTb OgS4Reo0Glo7nfoPcR4U15lwk1/HXKGaRF6HE6Tu4U05NRJgDvIxpSpOWDk84VBJ OFEopEdosF37yAohal2QTchAkv14xocqU0jIXFMHkXkt8vB9m//7jmH6u7E8V7yR o3q2zMxlA1bjYJ7M0dK7EAHHHovyOHI9CbFoyH7HbZPCSrkMi+AzynwTvG06R6s1 445TGYTGOBusdRw1kpyThkHyzHbbnCDhV8kGXZnd9qFm0M0v/GulmSq4JqkyS00H 0H3mCCrurP33Isk/YD9ojTPNc5wD1SXX6x0arGkwiFb1ziSeNGOeg== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4knrq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfKY2023504; Fri, 21 Aug 2026 19:53:10 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g32twpraj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr6SD37880300 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:06 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 434DC2004D; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F00E720043; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:05 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 04/24] unwind_user: Flexible FP/RA recovery rules Date: Fri, 21 Aug 2026 21:52:39 +0200 Message-ID: <20260821195259.2688377-5-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=CpuPtH4D c=1 sm=1 tr=0 ts=6a88aca7 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pGLkceISAAAA:8 a=ZPQ1DpjoKQCSDTLUZ9wA:9 X-Proofpoint-ORIG-GUID: RFdNlOL23WL85Qr1CA0s36Ns3096NQas X-Proofpoint-GUID: MHzCOk0TZ-DLd80RH_QggY9siDk5Qamj X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX4GxQtO6w8A4Z boQNGSaiEl7WbLicc+mSAa3W3VL3xRuKneRqSsSYV/f6dmnlZJdpasKUmDPQDDLpqT9oFbYHkdh 5fG0lXAQCMDaGPv0ZTqWVoJyxB+exWM= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX8AYdFc6m2mcb FXILWrzRSk9m41DapWpoNZ7zuKwxxcAAkqN9r0aRV/zkyA8/eiZSI4+1zDc56uTV1GORi3hiPPn tDHnETHGjRn2gS7LQivbay5bg4VMfC3jOOSYPMhD4azkHIFGcT01JJi3meyD9pj61tX1tQQsIEx pYrB6DWrO0tBXcKob5H07nSIM7ftT3dG3E0QWCgH0oOHLzye49GVAJUQ5SpInd0//38KVmRMOTb ZEXDInKSwtlQpGyyZkmHbx2F0nOyni31ezv2GNhvTnHI8Aj+t781ueve5WRv2z3x8zqsPkEdRxC Iz2BbAd8V1+OjjiNX8O3ZbtFA8CcHYFotgTUeGiS4Y+we2LN5Ph0bxUdbX6BTrPZb2vQN2jczak IHnh3gGLC5YTWmsPk7UieVmP0MYAxrtcMPM0nowjaA2jBiauKaIUWrlGIE27ApIjIMNPGmGqobO TKu6P7lqIJUDh5RGaRQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 adultscore=0 bulkscore=0 malwarescore=0 phishscore=0 lowpriorityscore=0 spamscore=0 clxscore=1015 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" To enable support for SFrame V3 flexible FDEs with a subsequent patch, add support for the following flexible frame pointer (FP) and return address (RA) recovery rules: FP/RA =3D *(CFA + offset) FP/RA =3D register + offset FP/RA =3D *(register + offset) Note that FP/RA recovery rules that use arbitrary register contents are only valid when in the topmost frame, as their contents are otherwise unknown. This also enables unwinding of user space for architectures, such as s390, that may save the frame pointer (FP) and/or return address (RA) in other registers, for instance when in a leaf function. Reviewed-by: Indu Bhagat Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v16 00/20] unwind_deferred: Implement sframe handling" series: https://lore.kernel.org/all/20260521142546.3908498-15-jremus@linux.ibm.= com/ arch/x86/include/asm/unwind_user.h | 21 +++++++-- include/linux/unwind_user.h | 10 +++++ include/linux/unwind_user_types.h | 23 +++++++++- kernel/unwind/user.c | 70 +++++++++++++++++++++++++++--- 4 files changed, 111 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index 2dfb5ef11e36..9c3417be4283 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -21,15 +21,26 @@ static inline int unwind_user_word_size(struct pt_regs = *regs) =20 #define ARCH_INIT_USER_FP_FRAME(ws) \ .cfa_off =3D 2*(ws), \ - .ra_off =3D -1*(ws), \ - .fp_off =3D -2*(ws), \ + .ra =3D { \ + .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ + .offset =3D -1*(ws), \ + }, \ + .fp =3D { \ + .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ + .offset =3D -2*(ws), \ + }, \ .use_fp =3D true, \ .outermost =3D false, =20 #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \ .cfa_off =3D 1*(ws), \ - .ra_off =3D -1*(ws), \ - .fp_off =3D 0, \ + .ra =3D { \ + .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ + .offset =3D -1*(ws), \ + }, \ + .fp =3D { \ + .rule =3D UNWIND_USER_RULE_RETAIN,\ + }, \ .use_fp =3D false, \ .outermost =3D false, =20 @@ -41,4 +52,6 @@ static inline bool unwind_user_at_function_start(struct p= t_regs *regs) =20 #endif /* CONFIG_HAVE_UNWIND_USER_FP */ =20 +#include + #endif /* _ASM_X86_UNWIND_USER_H */ diff --git a/include/linux/unwind_user.h b/include/linux/unwind_user.h index 941cef652435..b2b1c2572fed 100644 --- a/include/linux/unwind_user.h +++ b/include/linux/unwind_user.h @@ -33,6 +33,16 @@ static inline int unwind_user_get_ra_reg(unsigned long *= val) #define unwind_user_get_ra_reg unwind_user_get_ra_reg #endif =20 +#ifndef unwind_user_get_reg +static inline int unwind_user_get_reg(unsigned long *val, unsigned int reg= num) +{ + pr_debug("%s (%d): %s(%u) not implemented\n", + current->comm, current->pid, __func__, regnum); + return -EINVAL; +} +#define unwind_user_get_reg unwind_user_get_reg +#endif + int unwind_user(struct unwind_stacktrace *trace, unsigned int max_entries); =20 #endif /* _LINUX_UNWIND_USER_H */ diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 4fc3dd9b4e29..1b5db76e886a 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -25,10 +25,29 @@ struct unwind_stacktrace { unsigned long *entries; }; =20 +#define UNWIND_USER_RULE_DEREF BIT(31) + +enum unwind_user_rule { + UNWIND_USER_RULE_RETAIN, /* entity =3D entity */ + UNWIND_USER_RULE_CFA_OFFSET, /* entity =3D CFA + offset */ + UNWIND_USER_RULE_REG_OFFSET, /* entity =3D register + offset */ + /* DEREF variants */ + UNWIND_USER_RULE_CFA_OFFSET_DEREF =3D /* entity =3D *(CFA + offset) */ + UNWIND_USER_RULE_CFA_OFFSET | UNWIND_USER_RULE_DEREF, + UNWIND_USER_RULE_REG_OFFSET_DEREF =3D /* entity =3D *(register + offset) = */ + UNWIND_USER_RULE_REG_OFFSET | UNWIND_USER_RULE_DEREF, +}; + +struct unwind_user_rule_data { + enum unwind_user_rule rule; + s32 offset; + unsigned int regnum; +}; + struct unwind_user_frame { s32 cfa_off; - s32 ra_off; - s32 fp_off; + struct unwind_user_rule_data ra; + struct unwind_user_rule_data fp; bool use_fp; bool outermost; }; diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index f8a97d4167f0..f5d68e86d72b 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -11,6 +11,17 @@ #include #include =20 +#ifdef CONFIG_DYNAMIC_DEBUG + +#define dbg_once(fmt, ...) \ + pr_debug_once("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) + +#else /* !CONFIG_DYNAMIC_DEBUG */ + +#define dbg_once(args...) no_printk(args) + +#endif /* !CONFIG_DYNAMIC_DEBUG */ + #define for_each_user_frame(state) \ for (unwind_user_start(state); !(state)->done; unwind_user_next(state)) =20 @@ -63,22 +74,67 @@ static int unwind_user_next_common(struct unwind_user_s= tate *state, return -EINVAL; =20 /* Get the Return Address (RA) */ - if (frame->ra_off) { - if (get_user_word(&ra, cfa, frame->ra_off, state->ws)) - return -EINVAL; - } else { + switch (frame->ra.rule) { + case UNWIND_USER_RULE_RETAIN: if (!state->topmost || unwind_user_get_ra_reg(&ra)) return -EINVAL; + break; + case UNWIND_USER_RULE_CFA_OFFSET: + /* + * RA =3D CFA + offset does not make sense. + * A return address cannot legitimately be a stack address. + */ + dbg_once("UNWIND_USER_RULE_CFA_OFFSET invalid for RA\n"); + return -EINVAL; + case UNWIND_USER_RULE_CFA_OFFSET_DEREF: + ra =3D cfa + frame->ra.offset; + break; + case UNWIND_USER_RULE_REG_OFFSET: + case UNWIND_USER_RULE_REG_OFFSET_DEREF: + if (!state->topmost || unwind_user_get_reg(&ra, frame->ra.regnum)) + return -EINVAL; + ra +=3D frame->ra.offset; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; } + if (frame->ra.rule & UNWIND_USER_RULE_DEREF && + get_user_word(&ra, ra, 0, state->ws)) + return -EINVAL; =20 /* Get the Frame Pointer (FP) */ - if (frame->fp_off && get_user_word(&fp, cfa, frame->fp_off, state->ws)) + switch (frame->fp.rule) { + case UNWIND_USER_RULE_RETAIN: + fp =3D state->fp; + break; + case UNWIND_USER_RULE_CFA_OFFSET: + /* + * FP =3D CFA + offset is currently not used for FP + * (e.g. SFrame cannot represent this rule). + */ + dbg_once("UNWIND_USER_RULE_CFA_OFFSET unsupported for FP\n"); + return -EINVAL; + case UNWIND_USER_RULE_CFA_OFFSET_DEREF: + fp =3D cfa + frame->fp.offset; + break; + case UNWIND_USER_RULE_REG_OFFSET: + case UNWIND_USER_RULE_REG_OFFSET_DEREF: + if (!state->topmost || unwind_user_get_reg(&fp, frame->fp.regnum)) + return -EINVAL; + fp +=3D frame->fp.offset; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; + } + if (frame->fp.rule & UNWIND_USER_RULE_DEREF && + get_user_word(&fp, fp, 0, state->ws)) return -EINVAL; =20 state->ip =3D ra; state->sp =3D cfa; - if (frame->fp_off) - state->fp =3D fp; + state->fp =3D fp; state->topmost =3D false; return 0; } --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6343842125A; Fri, 21 Aug 2026 19:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342028; cv=none; b=ngJGM/09hyxWlRVM5ilS3kx82ApmoTEOVmUAOVOekKO3o0hZreIPUGutD7GeiKv9zQrZy1ZXMvdnuOudgtRCvjFsJOWyrp67SEsD+iIEzybHH9RwrrYvnJu/D+PG2lRNmtBuelyi053ek7L4eLuXWljjSn2oh0+5WYVb3qf+Rv8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342028; c=relaxed/simple; bh=pxvnkWjyvllmDpNuTjBidERmsTqRP+y+9EN7+vcXhiY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pq11V3btJqvYMhEaE3mmoFsGM6K8vQF9dQxeDWByx5ut9WJpJHD2tqmmnZfAkAsv14z+356sX9eDWJ5UlP19/7Oms+cqf8yXHFYGjap7rxtwCgEpUXXmXkpf6w1iNWDJ/8nd0P8k+vFSEzioZ+n1Cr14qbePZy1VxrDgRlitrVg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=NdIlQRu/; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="NdIlQRu/" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVjBw1237461; Fri, 21 Aug 2026 19:53:21 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=OutS/vKpuqD7JZiOr 99VKYen3/kOqOdagaSdljOjgy0=; b=NdIlQRu/4PthyVsqP3+CGi7t/1HkR+DJg Ozi8jpoKyFzVrrInkiZXoIE424b6+SFPlzQe4Wv1NVOugx0+u0jUYsOmpZh+gxVt aO/wlR+8XMFYeqi71mvSSUAi6W+Kz2pt3uptl6K5W0e3RWEdpSVKuBsqoGwvaL8y RargMfrxeiykKtex+lrjrdVNEPPXOEmHNB2PJCo9iPS3PIJNVedkpN7fuCjv45oN Qx+XqDKzZ60W5+W1reIiiO9IPayKhFE8MTcv3hQA4VuctiEJyILtyCwUmBuJLpfW /s9XB3mpvONdL/sLMViWojJT70ZOdWFm/WaA2QZyxn43RfdZZhxrw== Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu2kr1c-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:20 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfI9R021072; Fri, 21 Aug 2026 19:53:19 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ekpnys-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:19 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr60Z46137670 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:06 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8562020040; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 481022004E; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 05/24] unwind_user: Flexible CFA recovery rules Date: Fri, 21 Aug 2026 21:52:40 +0200 Message-ID: <20260821195259.2688377-6-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=AdqB2XXG c=1 sm=1 tr=0 ts=6a88acb0 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pGLkceISAAAA:8 a=IqD6mcJyx09DUBNVDg4A:9 X-Proofpoint-GUID: lLxlrY8gj3mfUTUoUEGao8MhjkwExcyd X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX8Lh9yUaIeOJu xVnlERrOrFCrmuvd4MtHM6CqO60dCb11u2xHFZeglfHDG9VRT2ItznnX0jgAtDDzqx+IKGWRN12 jWpbOC+RzBf+HwIlnXgbMc/WJCtuHzjcMuO/vv/XQac1SWExX7RtLrnfXfrcSgdSWnNAgyFSPVi mgEqm1ku7qq4qRjSQWBLPT9W28Quk02J61SbzihDt0lMpTbdlWbnXocwIrsYgpsG94AuBCPkRaj ywAdbDT3R2WoVCSJ6oYN3wfMdha855m+SNo9hHTEJzUqAsnJoQLGt+CgrzAkg2OjNPGiJYTbely 2VqyD4+g2LIfgXEG7ItL0Vvj6rmEaIjMmLJjO3WHa0jgQ0v3uydzP0jtwxFygmQ+BEMr30k3sk3 BDCA9OT/C6oSCe/UmAp8p69Te4Gdr7Fu27ARcGzdFxgOBzZpzEsAytc2+mW2t1YXh4Z97v6HJHE FQ44hPpVDY5zUaobynA== X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX1VsN+SodhfZK O2F6dGbrYwuLGSb4vDhhx/wzGBrxQhkSLWhDGucLSl5KSLvchq2s/4HMQLH8IZpaRwzruebb7Iy Vq6bTAd0aNi7zDxvaHi87RXMQbt06Fg= X-Proofpoint-ORIG-GUID: dLuG5Fx5nv_AFLS0cvVlqu_zhdwyNics X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 suspectscore=0 malwarescore=0 impostorscore=0 adultscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" To enable support for SFrame V3 flexible FDEs with a subsequent patch, add support for the following flexible Canonical Frame Address (CFA) recovery rules: CFA =3D SP + offset CFA =3D *(SP + offset) CFA =3D FP + offset CFA =3D *(FP + offset) CFA =3D register + offset CFA =3D *(register + offset) Note that CFA recovery rules that use arbitrary register contents are only valid when in the topmost frame, as their contents are otherwise unknown. Reviewed-by: Indu Bhagat Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v16 00/20] unwind_deferred: Implement sframe handling" series: https://lore.kernel.org/all/20260521142546.3908498-16-jremus@linux.ibm.= com/ arch/x86/include/asm/unwind_user.h | 12 ++++++++---- include/linux/unwind_user_types.h | 22 ++++++++++++++++++++-- kernel/unwind/user.c | 24 ++++++++++++++++++++---- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index 9c3417be4283..f38f7c5ff1de 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -20,7 +20,10 @@ static inline int unwind_user_word_size(struct pt_regs *= regs) #ifdef CONFIG_HAVE_UNWIND_USER_FP =20 #define ARCH_INIT_USER_FP_FRAME(ws) \ - .cfa_off =3D 2*(ws), \ + .cfa =3D { \ + .rule =3D UNWIND_USER_CFA_RULE_FP_OFFSET,\ + .offset =3D 2*(ws), \ + }, \ .ra =3D { \ .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ .offset =3D -1*(ws), \ @@ -29,11 +32,13 @@ static inline int unwind_user_word_size(struct pt_regs = *regs) .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ .offset =3D -2*(ws), \ }, \ - .use_fp =3D true, \ .outermost =3D false, =20 #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \ - .cfa_off =3D 1*(ws), \ + .cfa =3D { \ + .rule =3D UNWIND_USER_CFA_RULE_SP_OFFSET,\ + .offset =3D 1*(ws), \ + }, \ .ra =3D { \ .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ .offset =3D -1*(ws), \ @@ -41,7 +46,6 @@ static inline int unwind_user_word_size(struct pt_regs *r= egs) .fp =3D { \ .rule =3D UNWIND_USER_RULE_RETAIN,\ }, \ - .use_fp =3D false, \ .outermost =3D false, =20 static inline bool unwind_user_at_function_start(struct pt_regs *regs) diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 1b5db76e886a..670ac860ae76 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -27,6 +27,25 @@ struct unwind_stacktrace { =20 #define UNWIND_USER_RULE_DEREF BIT(31) =20 +enum unwind_user_cfa_rule { + UNWIND_USER_CFA_RULE_SP_OFFSET, /* CFA =3D SP + offset */ + UNWIND_USER_CFA_RULE_FP_OFFSET, /* CFA =3D FP + offset */ + UNWIND_USER_CFA_RULE_REG_OFFSET, /* CFA =3D register + offset */ + /* DEREF variants */ + UNWIND_USER_CFA_RULE_SP_OFFSET_DEREF =3D /* CFA =3D *(SP + offset) */ + UNWIND_USER_CFA_RULE_SP_OFFSET | UNWIND_USER_RULE_DEREF, + UNWIND_USER_CFA_RULE_FP_OFFSET_DEREF =3D /* CFA =3D *(FP + offset) */ + UNWIND_USER_CFA_RULE_FP_OFFSET | UNWIND_USER_RULE_DEREF, + UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF =3D /* CFA =3D *(register + offset)= */ + UNWIND_USER_CFA_RULE_REG_OFFSET | UNWIND_USER_RULE_DEREF, +}; + +struct unwind_user_cfa_rule_data { + enum unwind_user_cfa_rule rule; + s32 offset; + unsigned int regnum; +}; + enum unwind_user_rule { UNWIND_USER_RULE_RETAIN, /* entity =3D entity */ UNWIND_USER_RULE_CFA_OFFSET, /* entity =3D CFA + offset */ @@ -45,10 +64,9 @@ struct unwind_user_rule_data { }; =20 struct unwind_user_frame { - s32 cfa_off; + struct unwind_user_cfa_rule_data cfa; struct unwind_user_rule_data ra; struct unwind_user_rule_data fp; - bool use_fp; bool outermost; }; =20 diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index f5d68e86d72b..9df5040df9b3 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -52,14 +52,30 @@ static int unwind_user_next_common(struct unwind_user_s= tate *state, } =20 /* Get the Canonical Frame Address (CFA) */ - if (frame->use_fp) { + switch (frame->cfa.rule) { + case UNWIND_USER_CFA_RULE_SP_OFFSET: + case UNWIND_USER_CFA_RULE_SP_OFFSET_DEREF: + cfa =3D state->sp; + break; + case UNWIND_USER_CFA_RULE_FP_OFFSET: + case UNWIND_USER_CFA_RULE_FP_OFFSET_DEREF: if (state->fp < state->sp) return -EINVAL; cfa =3D state->fp; - } else { - cfa =3D state->sp; + break; + case UNWIND_USER_CFA_RULE_REG_OFFSET: + case UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF: + if (!state->topmost || unwind_user_get_reg(&cfa, frame->cfa.regnum)) + return -EINVAL; + break; + default: + WARN_ON_ONCE(1); + return -EINVAL; } - cfa +=3D frame->cfa_off; + cfa +=3D frame->cfa.offset; + if (frame->cfa.rule & UNWIND_USER_RULE_DEREF && + get_user_word(&cfa, cfa, 0, state->ws)) + return -EINVAL; =20 /* * Make sure that stack is not going in wrong direction. Allow SP --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 62CCB40756E; Fri, 21 Aug 2026 19:54:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342091; cv=none; b=Gr4B945/Fv+HF6eX/7eV54c+eJHBkZRC8KPhSEbO6CgcBJJSYSY5lo4zOQFbhNNG1T5Isw1Z7RNdpeftw2fyXZNSGqEGqxNXkLCmcJKwCRGNCKeJ0yFvz7PPL/s5rCGonDTM7bBC96aDNsT4xLbi7N+Kpw2edmxQTw/UBmJbKrE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342091; c=relaxed/simple; bh=VxkjHAblvepLIgb9AXIOQ4663CYXn8d6zZ9kO2Cgr1c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=C6nhrBc0iCQptjAW617mqsB7kwJRWQRCfS11DrCDj93/NLYcOdYT9dGIMWFbnFz5W72flL7Ewqa3Mms8qCB/siUCGk8/U9U3eVXtuLSEbLV2XqAYo00CuakfKYYyh7PDjfDax+B2bACAGcG6s+KuTj9nXfkLciZNeq05/YxN0+E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=Ik6Z6Eca; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="Ik6Z6Eca" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVxiZ2253909; Fri, 21 Aug 2026 19:53:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=vy5v0kow8OvVBCKPE knTW3YVcH8+BOGq/wDD2Ax/0dc=; b=Ik6Z6EcagM4Th2wGIyhUWPm6WCZVvOJXD GFAk/4ZKbPCVUKNf7cLbMtN16ekl5NlRCI66wn4JVI1iid78IXHfKoTVVIjiudFP bfSHfMLCcVgd0xSilp9GSnPS4qj5TpCdaLe6Jps5b7KeE+n3XrwSXmPBI1qLx0Xz HkJXn4YyXUggHE/VgwxS4QYXQZUDcyRHyVoKatPM+NLD+KpQymbk47N6fEmzgTKp CefyrOpHmD6iIFKklcoKvYgpaPdYFej8dCjsBs92vZUB90yBmL0tK97zbXlO3Trf 68A6w1T3jro+7JmCA3gpMns1HkLacKpTyObsnKH3/eRgaaKdsRQaw== Received: from ppma13.dal12v.mail.ibm.com (dd.9e.1632.ip4.static.sl-reverse.com [50.22.158.221]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4krka-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from pps.filterd (ppma13.dal12v.mail.ibm.com [127.0.0.1]) by ppma13.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfG0Z006045; Fri, 21 Aug 2026 19:53:10 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g34ngxffa-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr6UE46137672 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:07 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C721C2004D; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 89ED620043; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 06/24] unwind_user: Enable archs that define CFA = SP_callsite + offset Date: Fri, 21 Aug 2026 21:52:41 +0200 Message-ID: <20260821195259.2688377-7-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX9FBsFAHQQGz2 N9gv4AKq5AX16Zd6I3vSIabgnEmTfLOzPrSVZBJpFomPfP4zo83JrfdX1ucT08nWIZvdjdj7j6G BJM2jfsXJE02TnmtC8mH2uQ1TmYGqV4= X-Proofpoint-GUID: EAk8b7H0yYpoYcv3I855zQw9brKikp8S X-Proofpoint-ORIG-GUID: efydjJzZ6feBGaRhEFylPmhj4xk-CtEz X-Authority-Analysis: v=2.4 cv=RPmD2Yi+ c=1 sm=1 tr=0 ts=6a88aca8 cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=ejlfquudVdD-DdDf6fkA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX194aGO/+JiKM LnIsfSROUvjuAHAJ2I2PpvNtq0L3yaYaHfdSHcnrfEPDm1RX24yG2WY7lxcGmzFZkF9cPh/92Qv Au7O/L8wMrX4PRGm4PicIJATuc/z4rRoWKS4cEj5hrpXlK8Ds3eJD/g6c2tDcclXklSG+/5ayIM goXURhAibpr0iVWilQsjCHjwXI9wJ7d5P812ae2sZ5LPQC6CS8AHXQ/a+WAceJn9tSuw8cYOLoB QfDJiaFrk9FyiHHuz6XQ9CDTlbNadWJH70pgkY/85lzN+9gH7jDyGcoOwANs4fX5QeKr3CrDBBy M7F1U5vWJDtU9VbZnItqeZy1bqTdT5udp60KC214hkfz23BTCqj+00k5vIjaYwnKOQyVFsQljCx YiYwbf1G1W7QFCtvluPW50Uvr5ykx/gKYrSIKP8jj5fS7UXLFTBxuhO9E/rIjZuOOlaW8fkolGH mQfaK5kT/WLsOheI+DA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 adultscore=0 spamscore=0 priorityscore=1501 bulkscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Most architectures define their CFA as the value of the stack pointer (SP) at the call site in the previous frame, as suggested by the DWARF standard. Therefore the SP at call site can be unwound using an implicitly assumed value offset from CFA rule with an offset of zero: .cfi_val_offset , 0 As a result the SP at call site computes as follows: SP =3D CFA Enable unwinding of user space for architectures, such as s390, which define their CFA as the value of the SP at the call site in the previous frame with an offset. Do so by enabling architectures to override the default SP value offset from CFA of zero with an architecture-specific one: .cfi_val_offset , offset So that the SP at call site computes as follows: SP =3D CFA + offset Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v4 00/12] s390: SFrame user space unwinding" series and adjusted to .eh_frame: https://lore.kernel.org/all/20260127151926.2805123-6-jremus@linux.ibm.c= om/ arch/x86/include/asm/unwind_user.h | 2 ++ include/linux/unwind_user_types.h | 1 + kernel/unwind/user.c | 11 ++++++----- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index f38f7c5ff1de..c96645c824d1 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -32,6 +32,7 @@ static inline int unwind_user_word_size(struct pt_regs *r= egs) .rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF,\ .offset =3D -2*(ws), \ }, \ + .sp_off =3D 0, \ .outermost =3D false, =20 #define ARCH_INIT_USER_FP_ENTRY_FRAME(ws) \ @@ -46,6 +47,7 @@ static inline int unwind_user_word_size(struct pt_regs *r= egs) .fp =3D { \ .rule =3D UNWIND_USER_RULE_RETAIN,\ }, \ + .sp_off =3D 0, \ .outermost =3D false, =20 static inline bool unwind_user_at_function_start(struct pt_regs *regs) diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 670ac860ae76..4da058096259 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -67,6 +67,7 @@ struct unwind_user_frame { struct unwind_user_cfa_rule_data cfa; struct unwind_user_rule_data ra; struct unwind_user_rule_data fp; + s32 sp_off; bool outermost; }; =20 diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 9df5040df9b3..830c620fe453 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -43,7 +43,7 @@ get_user_word(unsigned long *word, unsigned long base, in= t off, unsigned int ws) static int unwind_user_next_common(struct unwind_user_state *state, const struct unwind_user_frame *frame) { - unsigned long cfa, fp, ra; + unsigned long cfa, sp, fp, ra; =20 /* Stop unwinding when reaching an outermost frame. */ if (frame->outermost) { @@ -77,16 +77,17 @@ static int unwind_user_next_common(struct unwind_user_s= tate *state, get_user_word(&cfa, cfa, 0, state->ws)) return -EINVAL; =20 + /* Get the Stack Pointer (SP) */ + sp =3D cfa + frame->sp_off; /* * Make sure that stack is not going in wrong direction. Allow SP * to be unchanged for the topmost frame, by subtracting topmost, * which is either 0 or 1. */ - if (cfa <=3D state->sp - state->topmost) + if (sp <=3D state->sp - state->topmost) return -EINVAL; - /* Make sure that the address is word aligned */ - if (cfa & (state->ws - 1)) + if (sp & (state->ws - 1)) return -EINVAL; =20 /* Get the Return Address (RA) */ @@ -149,7 +150,7 @@ static int unwind_user_next_common(struct unwind_user_s= tate *state, return -EINVAL; =20 state->ip =3D ra; - state->sp =3D cfa; + state->sp =3D sp; state->fp =3D fp; state->topmost =3D false; return 0; --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91DA342BC3A; Fri, 21 Aug 2026 19:53:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342032; cv=none; b=qVcgrdmNKPmj7EiA242vtYvWRyNtSYpebwHRt7IgVCyAx/b2B3yuVGL3uJUbCJ7yJgfCVJYf7kXOcnYzElRRgOUBVmVtU2IPL7P5ttpjBkIUu6wOemPyFtZXrUBFb/79lo/LFI04wrVeXHwQEb9zGP7azLThWH+cbar5WOt5yOU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342032; c=relaxed/simple; bh=jyKcTd/kpV54h9Hy59OQuFjCYkzCdrb9oBE70SGGnQo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aIy6v/VouqjXk5AkIaDC87MdP4WFbA95QRcJHVyH+Fbo207Ng56CMQ50PVtG5l/z49EaOsoERctBjkHT8hfI3ppS3YyQx2XcC5XMP9nE67UPB7oDj+buuO9OBOtU+mkXsh7RiIMhlcTmJ8H8t7VTM6z6Ojo1L6M/zcMXAVhrU0g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=CobCQ6sm; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="CobCQ6sm" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVeYx2363796; Fri, 21 Aug 2026 19:53:12 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=j+wEbXZq/n+IhPUNd E1WSrq7I0dPA9QUfGyBzZcW9pY=; b=CobCQ6smd3zC4mBkFKcVi0kwZoWHDM0hS SGMA5DKTJ9sSBndUvhMS4eYwIE23AVnwGqrLSOI05GYnvezY7lgk5V8bGst1kq/D sBUzwJmpE+crZlVPBc33WafcNDilssGb0XKk5p9bGPN8CoA0JJVp+DXfyMDNrzEJ vq1QAKjG1Ddno1nNzsLvA8mZlzTFX5NQkUu1pRJRPdlvSnlFM7KDcbsRrQERMJo1 0zKytnMNTUF6J7NxumU4gIUav7TkXRT+1OsrUrPngci0BltIZaANqLV1SlFjeN9W lJ3tCSf+S8Es21jOXfVtJnXbpgjVQ52vrn/e/8o/yHIE/WVV+lJUw== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0uxkq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfKU9008731; Fri, 21 Aug 2026 19:53:11 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354yxdwb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr7at45154634 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:07 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 21CE52004B; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CF4792004E; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:06 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 07/24] unwind_user/eh_frame: Add support for reading .eh_frame_hdr section Date: Fri, 21 Aug 2026 21:52:42 +0200 Message-ID: <20260821195259.2688377-8-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=MthiLWae c=1 sm=1 tr=0 ts=6a88aca8 cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=meVymXHHAAAA:8 a=SzVkBJ_cOz4MhcCxlBAA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-ORIG-GUID: jEoAe7cfRj1X6HO5mqUaDfdo1LbQOC4q X-Proofpoint-GUID: DBRTnkmGeT5zVgu34pKHiGG6Wtlh34og X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX/TvzHU1t0u/i AxKIrUWHhsQHcUWwVeb9de5WE2/bg1G4ptzcowqVMNpbFb1KYXRGgjNPwMVY/3LwDcc/Yv23don znvGymzU5p92DC80AWhxN15qPPADGKY= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX9W/cQxxRPyPD G9kx8KaKXJ7U9QZsFd9aqqcCQ9hlt4/ShojZH08nz6+1prZbGwsnFfprGsRJmzQcUgW2jQF252C hYNUySJGbv+pj1R9FkzPookpKswHXB+oIoh+ZYDZ/l+AJyYo6EeyQL27KO7WjuBtcFU6CcFNqr6 nm/6P9Mbn7ycNgz/T1CT0N1VINfnxeFRTkqO99e0Ukk45MQOkNxTBx8vmmI98sxAGF8QMJwoyVk an8vrAXezWLYU06Dj27RRQv9c5NgH4I4cjdzM970clfjQzWAfpBsh2s/x8FG3F31xbbd5M5XRjz 14Jooe/mRvVS2sHE+aclqppWZk13g79yhYiXgZyh0KW9v7El6Fgbp8BDBFKXR+g8w8WHUhLSa5C BE61TOuaCIb+EIB+FRGsAn+dzF/1kQirarDD8k+VlbwgogYTP9PHiLPDhShFnNGxoGtYVCbrsLc +GjJYbh6zO9ex7ndSQQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 impostorscore=0 bulkscore=0 phishscore=0 clxscore=1015 spamscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" In preparation for unwinding user space stacks with .eh_frame, add basic unwind user eh_frame infrastructure and support for reading the .eh_frame_hdr section. The .eh_frame_hdr section provides a binary search table for efficient lookup of Frame Description Entries (FDEs) in the .eh_frame section based on instruction pointer (IP). eh_frame_add_section() reads the .eh_frame_hdr section and unconditionally returns an error, so it is not very useful yet. A subsequent patch will improve that. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- Notes (jremus): Changes in RFC v2: - read_encoded_pointer(): Enable DW_EH_PE_absptr in combination with relative application flags (e.g. DW_EH_PE_pcrel). (Sashiko AI) - eh_frame_read_header(): Fix binary search table bounds check. (Sashiko AI) - UNSAFE_GET_USER_INC(): Improve overflow check. MAINTAINERS | 1 + arch/Kconfig | 3 + include/linux/eh_frame.h | 45 +++++ kernel/unwind/Makefile | 3 +- kernel/unwind/eh_frame.c | 366 +++++++++++++++++++++++++++++++++++++++ kernel/unwind/eh_frame.h | 30 ++++ 6 files changed, 447 insertions(+), 1 deletion(-) create mode 100644 include/linux/eh_frame.h create mode 100644 kernel/unwind/eh_frame.c create mode 100644 kernel/unwind/eh_frame.h diff --git a/MAINTAINERS b/MAINTAINERS index e5738a250d63..f19f5bb87f00 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28203,6 +28203,7 @@ M: Steven Rostedt S: Maintained F: arch/*/include/asm/unwind_user.h F: include/asm-generic/unwind_user.h +F: include/linux/eh_frame.h F: include/linux/unwind*.h F: kernel/unwind/ =20 diff --git a/arch/Kconfig b/arch/Kconfig index fa7507ac8e13..60542d5e5731 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -486,6 +486,9 @@ config HAVE_HARDLOCKUP_DETECTOR_ARCH config UNWIND_USER bool =20 +config HAVE_UNWIND_USER_EH_FRAME + bool + config HAVE_UNWIND_USER_FP bool select UNWIND_USER diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h new file mode 100644 index 000000000000..aaac2dd663d5 --- /dev/null +++ b/include/linux/eh_frame.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_EH_FRAME_H +#define _LINUX_EH_FRAME_H + +#ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME + +struct eh_frame_section { + unsigned long eh_frame_hdr_start; + unsigned long eh_frame_hdr_end; + unsigned long text_start; + unsigned long text_end; + + /* .eh_frame_hdr information */ + unsigned long eh_frame_start; + unsigned long eh_frame_vma_end; + unsigned long binary_search_table_start; + unsigned long binary_search_table_end; + unsigned long fde_count; + u8 binary_search_table_enc; +}; + +extern int eh_frame_add_section(unsigned long eh_frame_hdr_start, + unsigned long eh_frame_hdr_end, + unsigned long text_start, + unsigned long text_end); +extern int eh_frame_remove_section(unsigned long eh_frame_hdr_start); + +#else /* !CONFIG_HAVE_UNWIND_USER_EH_FRAME */ + +static inline int eh_frame_add_section(unsigned long eh_frame_hdr_start, + unsigned long eh_frame_hdr_end, + unsigned long text_start, + unsigned long text_end) +{ + return -ENOSYS; +} + +static inline int eh_frame_remove_section(unsigned long eh_frame_hdr_start) +{ + return -ENOSYS; +} + +#endif /* CONFIG_HAVE_UNWIND_USER_EH_FRAME */ + +#endif /* _LINUX_EH_FRAME_H */ diff --git a/kernel/unwind/Makefile b/kernel/unwind/Makefile index eae37bea54fd..2d97e2625d8a 100644 --- a/kernel/unwind/Makefile +++ b/kernel/unwind/Makefile @@ -1 +1,2 @@ - obj-$(CONFIG_UNWIND_USER) +=3D user.o deferred.o + obj-$(CONFIG_UNWIND_USER) +=3D user.o deferred.o + obj-$(CONFIG_HAVE_UNWIND_USER_EH_FRAME) +=3D eh_frame.o diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c new file mode 100644 index 000000000000..f25a0923e315 --- /dev/null +++ b/kernel/unwind/eh_frame.c @@ -0,0 +1,366 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Userspace eh_frame access functions + */ + +#define pr_fmt(fmt) "eh_frame: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "eh_frame.h" + +#define dbg(fmt, ...) \ + pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) + +#define UNSAFE_GET_USER_INC(to, from, end, label) \ +({ \ + typeof(to) __to; \ + if (sizeof(__to) > end - from) \ + return -EINVAL; \ + unsafe_get_user(__to, (typeof(to) __user *)from, label); \ + from +=3D sizeof(__to); \ + to =3D __to; \ +}) + +static __always_inline int read_uleb128(unsigned long *addr, unsigned long= end, + unsigned long *value) +{ + unsigned long cur =3D *addr; + unsigned long result =3D 0; + int shift =3D 0; + u8 byte; + + do { + if (shift >=3D BITS_PER_LONG) + return -EINVAL; + + UNSAFE_GET_USER_INC(byte, cur, end, Efault); + result |=3D (unsigned long)(byte & 0x7f) << shift; + shift +=3D 7; + } while (byte & 0x80); + + *value =3D result; + *addr =3D cur; + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int read_sleb128(unsigned long *addr, unsigned long= end, + long *value) +{ + unsigned long cur =3D *addr; + long result =3D 0; + int shift =3D 0; + u8 byte; + + do { + if (shift >=3D BITS_PER_LONG) + return -EINVAL; + + UNSAFE_GET_USER_INC(byte, cur, end, Efault); + result |=3D (long)(byte & 0x7f) << shift; + shift +=3D 7; + } while (byte & 0x80); + + /* Sign extend if necessary */ + if (shift < BITS_PER_LONG && (byte & 0x40)) + result |=3D -(1L << shift); + + *value =3D result; + *addr =3D cur; + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int encoded_pointer_size(u8 encoding) +{ + u8 format =3D DW_EH_PE_format(encoding); + + switch (format) { + case DW_EH_PE_absptr: + return sizeof(unsigned long); + case DW_EH_PE_udata2: + case DW_EH_PE_sdata2: + return 2; + case DW_EH_PE_udata4: + case DW_EH_PE_sdata4: + return 4; + case DW_EH_PE_udata8: + case DW_EH_PE_sdata8: + return 8; + case DW_EH_PE_uleb128: + case DW_EH_PE_sleb128: + /* Variable length */ + return 0; + default: + return 0; + } +} + +static __always_inline int read_encoded_pointer(struct eh_frame_section *s= ec, + unsigned long *addr, + unsigned long end, + u8 encoding, + unsigned long *value) +{ + unsigned long cur =3D *addr; + u8 format =3D DW_EH_PE_format(encoding); + u8 application =3D DW_EH_PE_application(encoding); + unsigned long result; + int ret; + + if (encoding =3D=3D DW_EH_PE_omit) + return -EINVAL; + + /* Determine base address based on application */ + switch (application) { + case 0: + /* Absolute */ + result =3D 0; + break; + case DW_EH_PE_pcrel: + result =3D *addr; + break; + case DW_EH_PE_datarel: + result =3D sec->eh_frame_hdr_start; + break; + case DW_EH_PE_textrel: + result =3D sec->text_start; + break; + case DW_EH_PE_funcrel: + case DW_EH_PE_aligned: + return -EOPNOTSUPP; + default: + return -EINVAL; + } + + /* Read value based on format */ + switch (format) { + case DW_EH_PE_absptr: { + unsigned long tmp; + UNSAFE_GET_USER_INC(tmp, cur, end, Efault); + result +=3D tmp; + break; + } + case DW_EH_PE_uleb128: { + unsigned long tmp; + ret =3D read_uleb128(&cur, end, &tmp); + if (ret) + return ret; + result +=3D tmp; + break; + } + case DW_EH_PE_udata2: { + u16 tmp16; + UNSAFE_GET_USER_INC(tmp16, cur, end, Efault); + result +=3D tmp16; + break; + } + case DW_EH_PE_udata4: { + u32 tmp32; + UNSAFE_GET_USER_INC(tmp32, cur, end, Efault); + result +=3D tmp32; + break; + } + case DW_EH_PE_udata8: { + u64 tmp64; + UNSAFE_GET_USER_INC(tmp64, cur, end, Efault); + result +=3D tmp64; + break; + } + case DW_EH_PE_sleb128: { + long stmp; + ret =3D read_sleb128(&cur, end, &stmp); + if (ret) + return ret; + result +=3D stmp; + break; + } + case DW_EH_PE_sdata2: { + s16 stmp16; + UNSAFE_GET_USER_INC(stmp16, cur, end, Efault); + result +=3D stmp16; + break; + } + case DW_EH_PE_sdata4: { + s32 stmp32; + UNSAFE_GET_USER_INC(stmp32, cur, end, Efault); + result +=3D stmp32; + break; + } + case DW_EH_PE_sdata8: { + s64 stmp64; + UNSAFE_GET_USER_INC(stmp64, cur, end, Efault); + result +=3D stmp64; + break; + } + default: + return -EINVAL; + } + + /* Indirect (dereference) - should not occur */ + if (encoding & DW_EH_PE_indirect) + return -EOPNOTSUPP; + + *value =3D result; + *addr =3D cur; + return 0; + +Efault: + return -EFAULT; +} + +static void free_section(struct eh_frame_section *sec) +{ + kfree(sec); +} + +static int eh_frame_read_header(struct eh_frame_section *sec) +{ + struct mm_struct *mm =3D current->mm; + void __user *eh_frame_hdr =3D (void __user *)sec->eh_frame_hdr_start; + unsigned long cur =3D sec->eh_frame_hdr_start, end =3D sec->eh_frame_hdr_= end; + unsigned long eh_frame_start, eh_frame_vma_end, table_start, table_end; + u8 version, eh_frame_ptr_enc, fde_count_enc, table_enc; + unsigned long fde_count; + int entry_size; + int ret; + + /* + * Unaligned access to .eh_frame[_hdr] fields using + * unsafe_get_user() via UNSAFE_GET_USER_INC() + */ + BUILD_BUG_ON(!IS_ENABLED(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)); + + scoped_user_read_access_size(eh_frame_hdr, end - sec->eh_frame_hdr_start, + Efault) { + /* Read version */ + UNSAFE_GET_USER_INC(version, cur, end, Efault); + if (version !=3D 1) + return -EINVAL; + + /* Read encoding information */ + UNSAFE_GET_USER_INC(eh_frame_ptr_enc, cur, end, Efault); + UNSAFE_GET_USER_INC(fde_count_enc, cur, end, Efault); + UNSAFE_GET_USER_INC(table_enc, cur, end, Efault); + + /* .eh_frame_hdr without binary search table is not supported */ + if (fde_count_enc =3D=3D DW_EH_PE_omit || table_enc =3D=3D DW_EH_PE_omit) + return -EINVAL; + + /* Read pointer to .eh_frame */ + ret =3D read_encoded_pointer(sec, &cur, end, + eh_frame_ptr_enc, &eh_frame_start); + if (ret) + return ret; + + /* Read FDE count */ + ret =3D read_encoded_pointer(sec, &cur, end, + fde_count_enc, &fde_count); + if (ret) + return ret; + + /* Determine binary search table start and end */ + table_start =3D cur; + entry_size =3D 2 * encoded_pointer_size(table_enc); + if (!entry_size) + return -EINVAL; + if (fde_count > (end - table_start) / entry_size) + return -EINVAL; + table_end =3D table_start + fde_count * entry_size; + } + + scoped_guard(mmap_read_lock, mm) { + struct vm_area_struct *eh_frame_vma; + + eh_frame_vma =3D vma_lookup(mm, eh_frame_start); + if (!eh_frame_vma) { + dbg("bad eh_frame address (0x%lx)\n", eh_frame_start); + return -EINVAL; + } + eh_frame_vma_end =3D eh_frame_vma->vm_end; + } + + sec->eh_frame_start =3D eh_frame_start; + sec->eh_frame_vma_end =3D eh_frame_vma_end; + sec->binary_search_table_start =3D table_start; + sec->binary_search_table_end =3D table_end; + sec->binary_search_table_enc =3D table_enc; + sec->fde_count =3D fde_count; + + return 0; + +Efault: + return -EFAULT; +} + +int eh_frame_add_section(unsigned long eh_frame_hdr_start, + unsigned long eh_frame_hdr_end, + unsigned long text_start, + unsigned long text_end) +{ + struct mm_struct *mm =3D current->mm; + struct eh_frame_section *sec; + int ret; + + if (eh_frame_hdr_start >=3D eh_frame_hdr_end || text_start >=3D text_end)= { + dbg("invalid eh_frame/text address\n"); + return -EINVAL; + } + + scoped_guard(mmap_read_lock, mm) { + struct vm_area_struct *eh_frame_hdr_vma, *text_vma; + + eh_frame_hdr_vma =3D vma_lookup(mm, eh_frame_hdr_start); + if (!eh_frame_hdr_vma || eh_frame_hdr_end > eh_frame_hdr_vma->vm_end) { + dbg("bad eh_frame_hdr address (0x%lx - 0x%lx)\n", + eh_frame_hdr_start, eh_frame_hdr_end); + return -EINVAL; + } + + text_vma =3D vma_lookup(mm, text_start); + if (!text_vma || + !(text_vma->vm_flags & VM_EXEC) || + text_end > text_vma->vm_end) { + dbg("bad text address (0x%lx - 0x%lx)\n", + text_start, text_end); + return -EINVAL; + } + } + + sec =3D kzalloc(sizeof(*sec), GFP_KERNEL_ACCOUNT); + if (!sec) + return -ENOMEM; + + sec->eh_frame_hdr_start =3D eh_frame_hdr_start; + sec->eh_frame_hdr_end =3D eh_frame_hdr_end; + sec->text_start =3D text_start; + sec->text_end =3D text_end; + + ret =3D eh_frame_read_header(sec); + if (ret) + goto err_free; + + /* TODO nowhere to store it yet - just free it and return an error */ + ret =3D -ENOSYS; + +err_free: + free_section(sec); + return ret; +} + +int eh_frame_remove_section(unsigned long eh_frame_hdr_start) +{ + return -ENOSYS; +} diff --git a/kernel/unwind/eh_frame.h b/kernel/unwind/eh_frame.h new file mode 100644 index 000000000000..77eda5376dfb --- /dev/null +++ b/kernel/unwind/eh_frame.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#ifndef _EH_FRAME_H +#define _EH_FRAME_H + +/* DWARF exception header pointer encodings */ +#define DW_EH_PE_omit 0xff +/* Formats */ +#define DW_EH_PE_absptr 0x00 +#define DW_EH_PE_uleb128 0x01 +#define DW_EH_PE_udata2 0x02 +#define DW_EH_PE_udata4 0x03 +#define DW_EH_PE_udata8 0x04 +#define DW_EH_PE_sleb128 0x09 +#define DW_EH_PE_sdata2 0x0a +#define DW_EH_PE_sdata4 0x0b +#define DW_EH_PE_sdata8 0x0c +/* Applications */ +#define DW_EH_PE_pcrel 0x10 +#define DW_EH_PE_textrel 0x20 +#define DW_EH_PE_datarel 0x30 +#define DW_EH_PE_funcrel 0x40 +#define DW_EH_PE_aligned 0x50 +/* Flags */ +#define DW_EH_PE_indirect 0x80 + +/* Helpers for DWARF exception header pointer encodings */ +#define DW_EH_PE_format(encoding) ((encoding) & 0x0f) +#define DW_EH_PE_application(encoding) ((encoding) & 0x70) + +#endif /* _EH_FRAME_H */ --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D48EA40F750; Fri, 21 Aug 2026 19:54:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342099; cv=none; b=Kwwqek9Vbse4AJIRyt/FgundSlQC71mnt81WctuTdsvN6Sp1+lfgi8gpzwQgK9boXFBOiS/pAmgQdkuOHuKy9FFtkVyRirPodfMPspAnI/kZRAYcO21Gp7NdC834hQDYk3KWCfEZhS6cAArUF883bblqVGwPcI6TZC5kIqJN1tI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342099; c=relaxed/simple; bh=Qic6tZo8dpzXnnNo0Q+j0ZFItm0ie2g/DHNovuqs3W8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=HjGiJN2DINomDxhqO6SAgBSmWK3WlqMEVVNY+PueilFPSbO4VguQJ5B0nuXRpaJIFb8irCWC6RSqYiq1KIhmrvlLp4ZHiZ7neHUb3KzDEDBwTc2wvnKeDhle9LX5QBaWGMBaUQKf8nIRPDhuB0zBcA5IflwK4sFW7YVCbnmWxvE= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=KfFaVDIX; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="KfFaVDIX" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVYr32363665; Fri, 21 Aug 2026 19:53:13 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=vNICQd0UftvHB9ldO irCCMEFxhzAhr23NSdN+vt2OTo=; b=KfFaVDIXpgbUhIufE73OJFH2Dd3r4UcoN e0qOZauVkhdet6ocnKsYKpqYVmRqebs+d0TgmCLkTVLjZUokmQaD1xtJKqlZXD1q 8a6jOdvqU/gRkM4yCBfoblt6CI6oCZNIC1SwYrMHWjwIlckkeI2HijrruLA5o32O XtryKL56u0NvUiQNOn0ExcuINK5EMiAdgyKygmuQQMbfvPpn3AhuILy+gUGAOJf/ q9xF56b8JZ9keDXGxbXAR/aECqGGT81ydJRWXHAiPfrNPcOtLo9aeCglDwmnepCw +TXpp9K/IivyBnqI24dfCDtupQbE7g58ltuXzyv/ozXdYtc3BEiOA== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0uxks-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfNE8020636; Fri, 21 Aug 2026 19:53:11 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eqpupc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr7SA45154636 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:07 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6C49620040; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 268C82004D; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 08/24] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree Date: Fri, 21 Aug 2026 21:52:43 +0200 Message-ID: <20260821195259.2688377-9-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=MthiLWae c=1 sm=1 tr=0 ts=6a88aca8 cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=O9OvWtXlmRKlQNak06kA:9 X-Proofpoint-ORIG-GUID: 5CT6L7o0fB-Z1z-_49XVsCNeW5Cuy0l1 X-Proofpoint-GUID: bJLXSuhHLLoeZRKbnFQ_54uQglss9TFN X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXyq6JG32NR1tI vDW0RopSH9lggYmZR6mJmuZGfW9EfsXzlyxnQD2UExjoXp0Nmj9fr3gc/I5g9bA8VbAPTXbPLre CN80Yu/Joiiw7CiCCnv2WAA7sUYOz8s= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX3OpNQkwkvA7t ekuctLGkiYGYIg5Sv6ffvna0g9daoD3qdMKyejoIa9CojzAgnIf0gj49OmCu3DTw3y7gdO0ihCr tjPofiEvwgDKt1L+TYDGI8dbG8Fjfhf490JNCrEwOUGhp77FPNytNcpuIZWUd1lM1q+3lyTJRf7 xB0oUkdZfDncfgK7OfaKshmQrx5Rm1hHC7/2UXzkhJ7TDlVY8M3ENldlt80s7LEiJIxsW5n9DTI oEXu6NSEyb+U0PDNm6Q5EH8SL4fKBjl6OYXOldkQifVNJ84tqgQkK1IrIU/lXp1gE1jqDTtrDH+ RrY7STXnpuT4ELvHkyJ5YA8JhmLQjCTEEpp84cOYz3w5ubqKkwBvUJCx7xjprI51EPFqGed8a3y P/W7J60gF0ud5ika8fdjo7kEwJzys3yjxWeDzaFnof1uFXfty+nlnaU+kl+4VVp0wWYUER7hVRa fLPOVHz5la+dH1CYkGQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 impostorscore=0 bulkscore=0 phishscore=0 clxscore=1015 spamscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Associate .eh_frame_hdr sections with their mm by adding them to a per-mm maple tree which is indexed by the corresponding text address range. A single .eh_frame_hdr section can be associated with multiple text ranges. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- Notes (jremus): Changes in RFC v2: - INIT_MM_EH_FRAME and mm_init_eh_frame(): Use MT_FLAGS_USE_RCU to enable concurrent eh_frame_mt read and write access. (Sashiko AI) - eh_frame_remove_section(): Fix ABA problem by using the advanced maple tree API to hold the internal spinlock while iterating over the eh_frame_mt and removing the eh_frame section(s). (Sashiko AI) arch/x86/include/asm/mmu.h | 2 +- include/linux/eh_frame.h | 22 ++++++++++++ include/linux/mm_types.h | 3 ++ kernel/fork.c | 10 ++++++ kernel/unwind/eh_frame.c | 70 ++++++++++++++++++++++++++++++++++++-- mm/init-mm.c | 2 ++ 6 files changed, 105 insertions(+), 4 deletions(-) diff --git a/arch/x86/include/asm/mmu.h b/arch/x86/include/asm/mmu.h index 0fe9c569d171..227a32899a59 100644 --- a/arch/x86/include/asm/mmu.h +++ b/arch/x86/include/asm/mmu.h @@ -87,7 +87,7 @@ typedef struct { .context =3D { \ .ctx_id =3D 1, \ .lock =3D __MUTEX_INITIALIZER(mm.context.lock), \ - } + }, =20 void leave_mm(void); #define leave_mm leave_mm diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h index aaac2dd663d5..c4279ee77c13 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -2,9 +2,14 @@ #ifndef _LINUX_EH_FRAME_H #define _LINUX_EH_FRAME_H =20 +#include +#include + #ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME =20 struct eh_frame_section { + struct rcu_head rcu; + unsigned long eh_frame_hdr_start; unsigned long eh_frame_hdr_end; unsigned long text_start; @@ -19,14 +24,29 @@ struct eh_frame_section { u8 binary_search_table_enc; }; =20 +#define EH_FRAME_MT_FLAGS (MT_FLAGS_USE_RCU) + +#define INIT_MM_EH_FRAME .eh_frame_mt =3D MTREE_INIT(eh_frame_mt, EH_FRAME= _MT_FLAGS), +extern void eh_frame_free_mm(struct mm_struct *mm); + extern int eh_frame_add_section(unsigned long eh_frame_hdr_start, unsigned long eh_frame_hdr_end, unsigned long text_start, unsigned long text_end); extern int eh_frame_remove_section(unsigned long eh_frame_hdr_start); =20 +static inline bool current_has_eh_frame(void) +{ + struct mm_struct *mm =3D current->mm; + + return mm && !mtree_empty(&mm->eh_frame_mt); +} + #else /* !CONFIG_HAVE_UNWIND_USER_EH_FRAME */ =20 +#define INIT_MM_EH_FRAME +static inline void eh_frame_free_mm(struct mm_struct *mm) {} + static inline int eh_frame_add_section(unsigned long eh_frame_hdr_start, unsigned long eh_frame_hdr_end, unsigned long text_start, @@ -40,6 +60,8 @@ static inline int eh_frame_remove_section(unsigned long e= h_frame_hdr_start) return -ENOSYS; } =20 +static inline bool current_has_eh_frame(void) { return false; } + #endif /* CONFIG_HAVE_UNWIND_USER_EH_FRAME */ =20 #endif /* _LINUX_EH_FRAME_H */ diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index b18c2b2e7d2c..ac51d6212e86 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -1404,6 +1404,9 @@ struct mm_struct { #ifdef CONFIG_MM_ID mm_id_t mm_id; #endif /* CONFIG_MM_ID */ +#ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME + struct maple_tree eh_frame_mt; +#endif } __randomize_layout; =20 /* diff --git a/kernel/fork.c b/kernel/fork.c index f0e2e131a9a5..dab67d2eb096 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -111,6 +111,7 @@ #include #include #include +#include #include =20 #include @@ -738,6 +739,7 @@ void __mmdrop(struct mm_struct *mm) mm_pasid_drop(mm); mm_destroy_cid(mm); percpu_counter_destroy_many(mm->rss_stat, NR_MM_COUNTERS); + eh_frame_free_mm(mm); =20 free_mm(mm); } @@ -1082,6 +1084,13 @@ static void mmap_init_lock(struct mm_struct *mm) #endif } =20 +static void mm_init_eh_frame(struct mm_struct *mm) +{ +#ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME + mt_init_flags(&mm->eh_frame_mt, EH_FRAME_MT_FLAGS); +#endif +} + static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct = *p) { mt_init_flags(&mm->mm_mt, MM_MT_FLAGS); @@ -1109,6 +1118,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm= , struct task_struct *p) mm->pmd_huge_pte =3D NULL; #endif mm_init_uprobes_state(mm); + mm_init_eh_frame(mm); hugetlb_count_init(mm); futex_mm_init(mm); =20 diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index f25a0923e315..8cf19c5298fd 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -19,6 +19,8 @@ #define dbg(fmt, ...) \ pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) =20 +DEFINE_STATIC_SRCU(eh_frame_srcu); + #define UNSAFE_GET_USER_INC(to, from, end, label) \ ({ \ typeof(to) __to; \ @@ -310,6 +312,7 @@ int eh_frame_add_section(unsigned long eh_frame_hdr_sta= rt, unsigned long text_start, unsigned long text_end) { + struct maple_tree *eh_frame_mt =3D ¤t->mm->eh_frame_mt; struct mm_struct *mm =3D current->mm; struct eh_frame_section *sec; int ret; @@ -352,15 +355,76 @@ int eh_frame_add_section(unsigned long eh_frame_hdr_s= tart, if (ret) goto err_free; =20 - /* TODO nowhere to store it yet - just free it and return an error */ - ret =3D -ENOSYS; + ret =3D mtree_insert_range(eh_frame_mt, sec->text_start, sec->text_end - = 1, + sec, GFP_KERNEL_ACCOUNT); + if (ret) { + dbg("mtree_insert_range failed: text=3D%lx-%lx\n", + sec->text_start, sec->text_end); + goto err_free; + } + + return 0; =20 err_free: free_section(sec); return ret; } =20 +static void eh_frame_free_srcu(struct rcu_head *rcu) +{ + struct eh_frame_section *sec =3D container_of(rcu, struct eh_frame_sectio= n, rcu); + + free_section(sec); +} + +static int __eh_frame_remove_section(struct ma_state *mas, + struct eh_frame_section *sec) +{ + if (mas_erase(mas) !=3D sec) { + dbg("mas_erase failed: text=3D%lx\n", sec->text_start); + return -EINVAL; + } + + call_srcu(&eh_frame_srcu, &sec->rcu, eh_frame_free_srcu); + + return 0; +} + int eh_frame_remove_section(unsigned long eh_frame_hdr_start) { - return -ENOSYS; + struct mm_struct *mm =3D current->mm; + struct eh_frame_section *sec; + MA_STATE(mas, &mm->eh_frame_mt, 0, 0); + bool found =3D false; + int ret =3D 0; + + guard(srcu)(&eh_frame_srcu); + + mtree_lock(&mm->eh_frame_mt); + mas_for_each(&mas, sec, ULONG_MAX) { + if (sec->eh_frame_hdr_start =3D=3D eh_frame_hdr_start) { + found =3D true; + ret |=3D __eh_frame_remove_section(&mas, sec); + } + } + mtree_unlock(&mm->eh_frame_mt); + + if (!found || ret) + return -EINVAL; + + return 0; +} + +void eh_frame_free_mm(struct mm_struct *mm) +{ + struct eh_frame_section *sec; + unsigned long index =3D 0; + + if (!mm) + return; + + mt_for_each(&mm->eh_frame_mt, sec, index, ULONG_MAX) + free_section(sec); + + mtree_destroy(&mm->eh_frame_mt); } diff --git a/mm/init-mm.c b/mm/init-mm.c index 3e792aad7626..25c26341fc4f 100644 --- a/mm/init-mm.c +++ b/mm/init-mm.c @@ -11,6 +11,7 @@ #include #include #include +#include #include =20 #ifndef INIT_MM_CONTEXT @@ -48,6 +49,7 @@ struct mm_struct init_mm =3D { #endif .flexible_array =3D MM_STRUCT_FLEXIBLE_ARRAY_INIT, INIT_MM_CONTEXT(init_mm) + INIT_MM_EH_FRAME }; =20 void setup_initial_init_mm(void *start_code, void *end_code, --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4E57240E8FC; Fri, 21 Aug 2026 19:53:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342018; cv=none; b=XbsA9rz6nhTjbSXqGwY7enQYFl5SRqB+cMZVIjs2P0teZhdITYfsPObDIV2C5dk/V/hxSvKcxoEVmxN6y624OPjKIi8XbEeiMnTnZ43PwuwpRcvhALoDK0t740tYWproK3J0gLp3duXrLczwjkiL3JFrJEgFJ8UmnvPpIT4Tbk4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342018; c=relaxed/simple; bh=Y81X+/taywb2Wa4DK6zd8yFN76ZMNg68bVkUlRBnKok=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=FVZT0qCDg7o8Ul9hVQt5pTh4Vc/zijFG5cN/p86xANxtl35yQFXQ/uQ3hVOhdKtzchaE8XWKFptTDIiTXz74QTQTTLvxm9DqqZhPFpc3E9AN9Zgzdwb/RbE7Z4Qndh3IVY3Zjj2qM+gzgzMlqrf1/v+6EkG4JfEpJ9mtsmGU+zs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=SWKUeCT6; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="SWKUeCT6" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIViSm1237447; Fri, 21 Aug 2026 19:53:14 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Kxj8BHi0rL2QVVWaC kIPMfvBQBWz+yrzEKqsHUXnnOY=; b=SWKUeCT6Xo+P9sVgKFQVe4GIqqb9VSo7e L/UThWuRng8V7iSfXGQWAACnrNwDoq0jEwMnQkknXa+3NB0FeUrhF30ZfBQAtOyj tHVrQXV6WrvKNfqrXFpER748q6mroCIg4pVwTEPHHOqjolRG1rZUlxbGeGRm/7mq 97wnd/iNp64YEpoeRCBIrN+OdMiyUOdelR4m2Xosk3Aj5i7wMuKKOv15pab0ObAa 6OSt6Qbep3otqKItizbMv37xYk5xdbY7QefG8PHxKLwyyssgRWYqWzd39K1fIYLn P7k3d7iuQcGP7jtXmRMWaWff+vRISrkCvQiF+sg8GPNBpHcUY00bQ== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu2kr0f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfU17023603; Fri, 21 Aug 2026 19:53:12 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g32twprau-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr7nt46006640 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:08 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C188A20040; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7168820043; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 09/24] unwind_user/eh_frame: Add support for reading .eh_frame section Date: Fri, 21 Aug 2026 21:52:44 +0200 Message-ID: <20260821195259.2688377-10-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=AdqB2XXG c=1 sm=1 tr=0 ts=6a88aca9 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VnNF1IyMAAAA:8 a=VwQbUJbxAAAA:8 a=meVymXHHAAAA:8 a=dqtD-XaBwNUOBDEPy-kA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-GUID: gz5V1gDHJ4AViJh0PPTNciHgZUHB6M1F X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX+UEhxfNFDIJn v4YJKLE2LX5P1tIy+jRVT1e3LJFEhmQ0jGsOabvJ9/hNSkluBaXt/hIOY9hmbRLSSPaSFe20kot BesI9FiV/ufcBMJonZsD9bIqVKRb0kBIK0lbAV5sU+w25osNzthvauIJs/11UH3sIzAw4dcdKOY kwOsipDMwLhET7Gp/peNWLxYhTBDj1nYGmH5gnt2X4tsI+JFhrxFn2UjBQR6SiZB1qorfJKJp/2 gmQ5N3Z+L8ZxFB3VBaqzW0hhteZ18lRmK+q6L5FyrFLBN+sJqC/kf2f9bWzNMDOM6rqPmcUTxW5 RQA1pGG0SofpvXrub7+OmW5/rfPZgmgz4XIT74i3kFXwmlDHEJmhtwmMIX5sfLVMtbdOG42tUQF +O5qR1Xp+kqBl0ixxKNzBLw63G6B/ZK/Ot7ZrZ8kx5D5w4P25qT+bkPBrnKtKrbIEwWtKyb9ZXF VDnq00ZcHPJqwznEN1w== X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX87wS0zYTIskX jHJFjtPu/7XU3k06tDwDOodXCSDsScQrimGLsKFebRfi3oSwt8OMKSXxYcA5Kv9al+IXJqAosFZ GewWOW0DOOqoRgUJ0dZy8jjhLAjS3D0= X-Proofpoint-ORIG-GUID: LXyNGTTaJ1sSmfd7Uv-uoWSCS2o4lJ11 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 suspectscore=0 malwarescore=0 impostorscore=0 adultscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" In preparation for using .eh_frame to unwind user space stacks, add an eh_frame_find() interface for finding the .eh_frame[_hdr] information associated with a given text address. The implementation parses DWARF Call Frame Information (CFI) from the .eh_frame section, including: - Common Information Entries (CIEs) that define default unwinding rules, - Frame Description Entries (FDEs) that describe unwinding for specific function address ranges, and - DWARF CFI instructions that specify how to restore registers. For performance, use user_read_access_begin() and the corresponding unsafe_*() accessors. Note that use of pr_debug() in uaccess-enabled regions would break noinstr validation, so there aren't any debug messages yet. That will be added in a subsequent commit. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- Notes (jremus): Changes in RFC v2: - Reduce maximum state stack depth to 1 (EH_FRAME_MAX_STATE_STACK). - Limit FDE length to 32768 (EH_FRAME_MAX_FDE_LENGTH). - Limit number of CFI instructions processed to 16.384 (EH_FRAME_CFI_INSN_LIMIT) to prevent an infinite loop, in case of a logic error that would enable malicious .eh_frame to make the cursor go backwards (e.g. due to an overflow). (Sashiko AI) [cc1plus FDE with 13.888 CFI insns] - __read_fde(): Do not allow function-relative encoding when reading PC begin (function start address) and PC range (function size) to fix use of uninitialized function start address. (Sashiko AI) - read_encoded_pointer(): Drop support for function-relative encoding, as it is no longer used. - DW_CFA_offset: Read offset into unsigned long. (Sashiko AI) - Add support for DW_CFA_restore_extended. - DW_CFA_def_cfa_{offset[_sf]|register}: Reject if CFA rule is not CFA_REG_OFFSET to ensure the unchanged part of the rule is initialized. (Sashiko AI) - Improve CIE/FDE augmentation data length overflow checks. - __do_cfi_insn(): Use check_mul_overflow() to check for overflow in multiplications with CIE data alignment factor. (Sashiko AI) - DW_CFA_restore[_extended]: Restore to CIE state. (Sashiko AI) MAINTAINERS | 2 + include/asm-generic/Kbuild | 1 + include/asm-generic/unwind_user_eh_frame.h | 51 ++ include/linux/eh_frame.h | 7 + kernel/unwind/eh_frame.c | 988 ++++++++++++++++++++- kernel/unwind/eh_frame.h | 38 + kernel/unwind/eh_frame_debug.h | 19 + 7 files changed, 1103 insertions(+), 3 deletions(-) create mode 100644 include/asm-generic/unwind_user_eh_frame.h create mode 100644 kernel/unwind/eh_frame_debug.h diff --git a/MAINTAINERS b/MAINTAINERS index f19f5bb87f00..d5f46f26996f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -28202,7 +28202,9 @@ M: Josh Poimboeuf M: Steven Rostedt S: Maintained F: arch/*/include/asm/unwind_user.h +F: arch/*/include/asm/unwind_user_eh_frame.h F: include/asm-generic/unwind_user.h +F: include/asm-generic/unwind_user_eh_frame.h F: include/linux/eh_frame.h F: include/linux/unwind*.h F: kernel/unwind/ diff --git a/include/asm-generic/Kbuild b/include/asm-generic/Kbuild index 15df9dcb42a5..bd031eb6adc4 100644 --- a/include/asm-generic/Kbuild +++ b/include/asm-generic/Kbuild @@ -62,6 +62,7 @@ mandatory-y +=3D topology.h mandatory-y +=3D trace_clock.h mandatory-y +=3D uaccess.h mandatory-y +=3D unwind_user.h +mandatory-y +=3D unwind_user_eh_frame.h mandatory-y +=3D vermagic.h mandatory-y +=3D vga.h mandatory-y +=3D video.h diff --git a/include/asm-generic/unwind_user_eh_frame.h b/include/asm-gener= ic/unwind_user_eh_frame.h new file mode 100644 index 000000000000..da238557605b --- /dev/null +++ b/include/asm-generic/unwind_user_eh_frame.h @@ -0,0 +1,51 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_GENERIC_UNWIND_USER_EH_FRAME_H +#define _ASM_GENERIC_UNWIND_USER_EH_FRAME_H + +#ifndef EH_FRAME_MAX_CIE_LENGTH +#define EH_FRAME_MAX_CIE_LENGTH 128 +#endif + +#ifndef EH_FRAME_MAX_FDE_LENGTH +#define EH_FRAME_MAX_FDE_LENGTH 32768 +#endif + +#ifndef EH_FRAME_MAX_AUGSTR_LENGTH +#define EH_FRAME_MAX_AUGSTR_LENGTH 16 +#endif + +#ifndef EH_FRAME_MAX_STATE_STACK +#define EH_FRAME_MAX_STATE_STACK 1 +#endif + +#ifndef EH_FRAME_MAX_CODE_ALIGN +#define EH_FRAME_MAX_CODE_ALIGN 8 +#endif + +#ifndef EH_FRAME_MIN_DATA_ALIGN +#define EH_FRAME_MIN_DATA_ALIGN -8 +#endif + +#ifndef EH_FRAME_MAX_DATA_ALIGN +#define EH_FRAME_MAX_DATA_ALIGN -1 +#endif + +#ifndef EH_FRAME_CFI_INSN_LIMIT +#define EH_FRAME_CFI_INSN_LIMIT 16384 +#endif + +#ifndef EH_FRAME_SP_VAL_OFFSET +/* Most archs/ABIs define CFA as SP at call site, so that SP =3D CFA + 0 */ +#define EH_FRAME_SP_VAL_OFFSET 0 +#endif + +#ifndef eh_frame_reject_sp_rule +static inline bool eh_frame_reject_sp_rule(void) +{ + return true; +} +#define eh_frame_reject_sp_rule eh_frame_reject_sp_rule +#endif + +#endif /* _ASM_GENERIC_UNWIND_USER_EH_FRAME_H */ + diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h index c4279ee77c13..740316b19df3 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -4,6 +4,7 @@ =20 #include #include +#include =20 #ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME =20 @@ -34,6 +35,7 @@ extern int eh_frame_add_section(unsigned long eh_frame_hd= r_start, unsigned long text_start, unsigned long text_end); extern int eh_frame_remove_section(unsigned long eh_frame_hdr_start); +extern int eh_frame_find(unsigned long ip, struct unwind_user_frame *frame= ); =20 static inline bool current_has_eh_frame(void) { @@ -60,6 +62,11 @@ static inline int eh_frame_remove_section(unsigned long = eh_frame_hdr_start) return -ENOSYS; } =20 +static inline int eh_frame_find(unsigned long ip, struct unwind_user_frame= *frame) +{ + return -ENOSYS; +} + static inline bool current_has_eh_frame(void) { return false; } =20 #endif /* CONFIG_HAVE_UNWIND_USER_EH_FRAME */ diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 8cf19c5298fd..21f40805b417 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -13,14 +13,85 @@ #include #include #include +#include =20 #include "eh_frame.h" - -#define dbg(fmt, ...) \ - pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) +#include "eh_frame_debug.h" + +/* Register state for CFI interpreter */ +enum eh_frame_cfa_rule { + CFA_UNDEFINED, /* unrecoverable */ + CFA_REG_OFFSET, /* CFA =3D reg + offset */ +}; + +enum eh_frame_reg_rule { + REG_UNDEFINED_IMPLICIT, /* reg =3D reg */ + REG_UNDEFINED_EXPLICIT, /* unrecoverable; RA: outermost frame */ + REG_SAME_VALUE, /* reg =3D reg; TODO: reset to CIE initial CFI */ + REG_OFFSET, /* reg =3D *(CFA + offset) */ + REG_VAL_OFFSET, /* reg =3D CFA + offset */ + REG_REGISTER, /* reg =3D other_reg */ +}; + +enum eh_frame_reg_index { + FP_IDX, /* frame pointer (FP) */ + RA_IDX, /* return address (RA) */ + NR_REGS +}; + +struct eh_frame_reg_state { + /* CFA recovery rule */ + enum eh_frame_cfa_rule cfa_rule; + unsigned long cfa_regnum; + long cfa_offset; + + /* FP and RA recovery rules (SP uses implicit recovery) */ + enum eh_frame_reg_rule reg_rule[NR_REGS]; + unsigned long reg_regnum[NR_REGS]; + long reg_offset[NR_REGS]; +}; + +struct eh_frame_cfi_context { + struct eh_frame_reg_state state; + struct eh_frame_reg_state stack[EH_FRAME_MAX_STATE_STACK]; + struct eh_frame_reg_state cie_state; + int stack_depth; + bool cie; +}; + +struct eh_frame_cie { + unsigned long cfi_insn_start; + unsigned long cfi_insn_end; + int data_align; + unsigned int code_align; + u8 fde_addr_enc; /* from CIE 'R' augmentation */ + bool aug_data_present; /* from CIE 'z' augmentation */ + bool signal_frame; /* from CIE 'S' augmentation */ +}; + +struct eh_frame_fde { + unsigned long func_addr; + unsigned long func_size; + unsigned long cfi_insn_start; + unsigned long cfi_insn_end; + + struct eh_frame_cie cie; /* referenced CIE*/ +}; =20 DEFINE_STATIC_SRCU(eh_frame_srcu); =20 +#define GET_USER_INC(to, from, end) \ +({ \ + typeof(to) __to; \ + int ret; \ + if (from + sizeof(__to) > end) \ + return -EINVAL; \ + ret =3D get_user(__to, (typeof(to) __user *)from); \ + from +=3D sizeof(__to); \ + to =3D __to; \ + ret; \ +}) + #define UNSAFE_GET_USER_INC(to, from, end, label) \ ({ \ typeof(to) __to; \ @@ -223,6 +294,917 @@ static __always_inline int read_encoded_pointer(struc= t eh_frame_section *sec, return -EFAULT; } =20 +static __always_inline int __read_cie(struct eh_frame_section *sec, + unsigned long cie_addr, + struct eh_frame_cie *cie) +{ + void __user *cie_ptr =3D (void __user *)cie_addr; + unsigned long cur =3D cie_addr, end; + u32 length, cie_id; + u8 version; + char aug_str[EH_FRAME_MAX_AUGSTR_LENGTH]; + int aug_idx; + unsigned long code_align; + long data_align; + u8 ra_reg; + bool aug_data_present =3D false; + unsigned long aug_data_len, aug_data_end; + u8 fde_addr_enc =3D DW_EH_PE_absptr; + bool signal_frame =3D false; + int ret; + + /* Read CIE length */ + ret =3D GET_USER_INC(length, cur, sec->eh_frame_vma_end); + if (ret) + return ret; + if (!length || length =3D=3D EH_FRAME_DWARF64_LENGTH || length > EH_FRAME= _MAX_CIE_LENGTH) + return -EINVAL; + end =3D cie_addr + 4 + length; + if (end < cie_addr || end > sec->eh_frame_vma_end) + return -EFAULT; + + scoped_user_read_access_size(cie_ptr, 4 + length, Efault) { + /* Read CIE_ID (must be 0 for CIE; FDE otherwise) */ + UNSAFE_GET_USER_INC(cie_id, cur, end, Efault); + if (cie_id !=3D EH_FRAME_CIE_ID) + return -EINVAL; + + /* Read version */ + UNSAFE_GET_USER_INC(version, cur, end, Efault); + if (version !=3D 1) + return -EOPNOTSUPP; + + /* Read augmentation string */ + for (aug_idx =3D 0; aug_idx < sizeof(aug_str); aug_idx++) { + UNSAFE_GET_USER_INC(aug_str[aug_idx], cur, end, Efault); + if (aug_str[aug_idx] =3D=3D '\0') + break; + } + if (aug_idx >=3D sizeof(aug_str)) + return -EINVAL; + + /* Read code alignment factor */ + ret =3D read_uleb128(&cur, end, &code_align); + if (ret) + return ret; + if (!code_align || code_align > EH_FRAME_MAX_CODE_ALIGN) + return -EINVAL; + + /* Read data alignment factor */ + ret =3D read_sleb128(&cur, end, &data_align); + if (ret) + return ret; + if (!data_align || (data_align < EH_FRAME_MIN_DATA_ALIGN || + data_align > EH_FRAME_MAX_DATA_ALIGN)) + return -EINVAL; + + /* Read return address register number */ + UNSAFE_GET_USER_INC(ra_reg, cur, end, Efault); + if (ra_reg !=3D EH_FRAME_REG_RA) + return -EOPNOTSUPP; + + /* Parse augmentation string and read augmentation data if present */ + aug_data_end =3D cur; + for (aug_idx =3D 0; aug_str[aug_idx]; aug_idx++) { + switch (aug_str[aug_idx]) { + case 'z': + /* Augmentation data present - must be first character */ + if (aug_idx !=3D 0) + return -EINVAL; + aug_data_present =3D true; + ret =3D read_uleb128(&cur, end, &aug_data_len); + if (ret) + return ret; + aug_data_end =3D cur + aug_data_len; + if (aug_data_end < cur || aug_data_end > end) + return -EINVAL; + break; + case 'L': { + /* LSDA encoding - skip */ + u8 lsda_enc; + if (!aug_data_present) + return -EINVAL; + UNSAFE_GET_USER_INC(lsda_enc, cur, aug_data_end, Efault); + break; + } + case 'P': { + /* Personality encoding and routine - skip */ + u8 personality_enc; + unsigned long personality_rtn; + if (!aug_data_present) + return -EINVAL; + UNSAFE_GET_USER_INC(personality_enc, cur, aug_data_end, Efault); + /* + * Clear indirect flag to avoid user read from + * arbitrary address; still skip field. + */ + personality_enc &=3D ~DW_EH_PE_indirect; + ret =3D read_encoded_pointer(sec, &cur, aug_data_end, + personality_enc, &personality_rtn); + if (ret) + return ret; + break; + } + case 'R': + /* FDE encoding */ + if (!aug_data_present) + return -EINVAL; + UNSAFE_GET_USER_INC(fde_addr_enc, cur, aug_data_end, Efault); + break; + case 'S': + /* Signal frame */ + signal_frame =3D true; + break; + default: + /* Unknown augmentation */ + return -EOPNOTSUPP; + } + } + if (cur !=3D aug_data_end) + return -EINVAL; + } + + cie->code_align =3D code_align; + cie->data_align =3D data_align; + cie->fde_addr_enc =3D fde_addr_enc; + cie->aug_data_present =3D aug_data_present; + cie->signal_frame =3D signal_frame; + cie->cfi_insn_start =3D cur; + cie->cfi_insn_end =3D end; + + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int __read_fde(struct eh_frame_section *sec, + unsigned long fde_addr, + struct eh_frame_fde *fde) +{ + void __user *fde_ptr =3D (void __user *)fde_addr; + unsigned long cur =3D fde_addr, end; + u32 length, cie_offset; + unsigned long cie_addr, func_addr, func_size; + u8 range_enc; + int ret; + + /* Read FDE length */ + ret =3D GET_USER_INC(length, cur, sec->eh_frame_vma_end); + if (ret) + return ret; + if (!length || length =3D=3D EH_FRAME_DWARF64_LENGTH || length > EH_FRAME= _MAX_FDE_LENGTH) + return -EINVAL; + end =3D fde_addr + 4 + length; + if (end < fde_addr || end > sec->eh_frame_vma_end) + return -EFAULT; + + scoped_user_read_access_size(fde_ptr, 4 + length, Efault) { + /* Read CIE pointer (offset from current position) */ + UNSAFE_GET_USER_INC(cie_offset, cur, end, Efault); + cie_addr =3D cur - 4 - cie_offset; + if (cie_addr + EH_FRAME_CIE_MIN_LENGTH > fde_addr) + return -EINVAL; + if (cie_addr < sec->eh_frame_start) + return -EINVAL; + } + + /* Read the CIE to populate alignment factors, RA register, and FDE encod= ing */ + ret =3D __read_cie(sec, cie_addr, &fde->cie); + if (ret) + return ret; + + scoped_user_read_access_size(fde_ptr, 4 + length, Efault) { + /* Read PC begin (function start address) */ + ret =3D read_encoded_pointer(sec, &cur, end, fde->cie.fde_addr_enc, &fun= c_addr); + if (ret) + return ret; + if (func_addr < sec->text_start || func_addr >=3D sec->text_end) + return -EINVAL; + + + /* Read PC range (function size) using PE format only */ + range_enc =3D DW_EH_PE_format(fde->cie.fde_addr_enc); + ret =3D read_encoded_pointer(sec, &cur, end, range_enc, &func_size); + if (ret) + return ret; + if (func_addr + func_size < func_addr || func_addr + func_size > sec->te= xt_end) + return -EINVAL; + + /* Skip augmentation data if present */ + if (fde->cie.aug_data_present) { + unsigned long aug_data_len; + unsigned long aug_data_end; + + ret =3D read_uleb128(&cur, end, &aug_data_len); + if (ret) + return ret; + aug_data_end =3D cur + aug_data_len; + if (aug_data_end < cur || aug_data_end > end) + return -EINVAL; + cur =3D aug_data_end; + } + } + + fde->func_addr =3D func_addr; + fde->func_size =3D func_size; + fde->cfi_insn_start =3D cur; + fde->cfi_insn_end =3D end; + + return 0; + +Efault: + return -EFAULT; +} + + +static __always_inline int __find_fde(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) +{ + void __user *table_start_ptr; + unsigned long table_size; + u8 table_enc; + int entry_size; + unsigned long low, high; + unsigned long found_cur =3D 0, found_func_addr; + unsigned long fde_addr; + int ret; + + if (!sec->fde_count) + return -ENOENT; + + table_enc =3D sec->binary_search_table_enc; + entry_size =3D 2 * encoded_pointer_size(table_enc); + if (!entry_size) + return -EINVAL; + + table_start_ptr =3D (void __user *)sec->binary_search_table_start; + table_size =3D sec->binary_search_table_end - sec->binary_search_table_st= art; + scoped_user_read_access_size(table_start_ptr, table_size, Efault) { + /* + * Binary search in .eh_frame_hdr table using half-open + * interval [low, high) to avoid underflow of high if + * target IP is lower than first entry. + */ + low =3D 0; + high =3D sec->fde_count; + while (low < high) { + unsigned long mid, cur, func_addr; + + mid =3D low + ((high - low) / 2); + cur =3D sec->binary_search_table_start + mid * entry_size; + + /* Read function start address from table */ + ret =3D read_encoded_pointer(sec, &cur, sec->binary_search_table_end, + table_enc, &func_addr); + if (ret) + return ret; + + if (ip >=3D func_addr) { + found_cur =3D cur; + found_func_addr =3D func_addr; + low =3D mid + 1; + } else { + high =3D mid; + } + } + + if (!found_cur) + return -ENOENT; + + /* Read FDE address from table */ + ret =3D read_encoded_pointer(sec, &found_cur, sec->binary_search_table_e= nd, + table_enc, &fde_addr); + if (ret) + return ret; + if (fde_addr < sec->eh_frame_start) + return -EINVAL; + } + + ret =3D __read_fde(sec, fde_addr, fde); + if (ret) + return ret; + if (found_func_addr !=3D fde->func_addr) + return -EINVAL; + + /* Make sure it is not a gap */ + if (ip < fde->func_addr || ip >=3D fde->func_addr + fde->func_size) + return -ENOENT; + + return 0; + +Efault: + return -EFAULT; +} + +/* Helper to convert DWARF register number to index (FP=3D0, RA=3D1) */ +static inline int reg_to_index(unsigned int reg) +{ + if (reg =3D=3D EH_FRAME_REG_FP) + return 0; + if (reg =3D=3D EH_FRAME_REG_RA) + return 1; + return -1; +} + +static __always_inline int __do_cfi_insn(struct eh_frame_section *sec, + struct eh_frame_fde *fde, + unsigned long *cur_ptr, + unsigned long end, + unsigned long *ip_ptr, + unsigned long target_ip, + struct eh_frame_cfi_context *ctx) +{ + unsigned long cur =3D *cur_ptr; + unsigned long ip =3D *ip_ptr; + u8 opcode; + int ret; + + UNSAFE_GET_USER_INC(opcode, cur, end, Efault); + + switch (DW_CFA_opcode(opcode)) { + case DW_CFA_advance_loc: { + unsigned long offset =3D DW_CFA_operand(opcode) * fde->cie.code_align; + + ip +=3D offset; + break; + } + + case DW_CFA_offset: { + u8 reg =3D DW_CFA_operand(opcode); + unsigned long _offset; + long offset; + int idx; + + ret =3D read_uleb128(&cur, end, &_offset); + if (ret) + return ret; + if (check_mul_overflow(_offset, fde->cie.data_align, &offset)) + return -EINVAL; + + if (reg =3D=3D EH_FRAME_REG_SP && eh_frame_reject_sp_rule()) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) { + ctx->state.reg_rule[idx] =3D REG_OFFSET; + ctx->state.reg_offset[idx] =3D offset; + } + break; + } + + case DW_CFA_restore: { + u8 reg =3D DW_CFA_operand(opcode); + int idx; + + if (ctx->cie) + return -EINVAL; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) + ctx->state.reg_rule[idx] =3D ctx->cie_state.reg_rule[idx]; + break; + } + + case 0: /* Extended opcodes */ + switch (opcode) { + case DW_CFA_nop: + break; + + case DW_CFA_advance_loc1: { + unsigned long offset; + u8 delta; + + UNSAFE_GET_USER_INC(delta, cur, end, Efault); + offset =3D delta * fde->cie.code_align; + ip +=3D offset; + break; + } + + case DW_CFA_advance_loc2: { + unsigned long offset; + u16 delta; + + UNSAFE_GET_USER_INC(delta, cur, end, Efault); + offset =3D delta * fde->cie.code_align; + ip +=3D offset; + break; + } + + case DW_CFA_advance_loc4: { + unsigned long offset; + u32 delta; + + UNSAFE_GET_USER_INC(delta, cur, end, Efault); + offset =3D delta * fde->cie.code_align; + ip +=3D offset; + break; + } + + case DW_CFA_def_cfa: { + unsigned long reg, offset; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_uleb128(&cur, end, &offset); + if (ret) + return ret; + + if (offset > LONG_MAX) + return -EOPNOTSUPP; + + ctx->state.cfa_rule =3D CFA_REG_OFFSET; + ctx->state.cfa_regnum =3D reg; + ctx->state.cfa_offset =3D offset; + break; + } + + case DW_CFA_def_cfa_sf: { + unsigned long reg; + long offset; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_sleb128(&cur, end, &offset); + if (ret) + return ret; + if (check_mul_overflow(offset, fde->cie.data_align, &offset)) + return -EINVAL; + + ctx->state.cfa_rule =3D CFA_REG_OFFSET; + ctx->state.cfa_regnum =3D reg; + ctx->state.cfa_offset =3D offset; + break; + } + + case DW_CFA_def_cfa_register: { + unsigned long reg; + + if (ctx->state.cfa_rule !=3D CFA_REG_OFFSET) + return -EINVAL; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + + ctx->state.cfa_regnum =3D reg; + break; + } + + case DW_CFA_def_cfa_offset: { + unsigned long offset; + + if (ctx->state.cfa_rule !=3D CFA_REG_OFFSET) + return -EINVAL; + + ret =3D read_uleb128(&cur, end, &offset); + if (ret) + return ret; + + if (offset > LONG_MAX) + return -EOPNOTSUPP; + + ctx->state.cfa_offset =3D offset; + break; + } + + case DW_CFA_def_cfa_offset_sf: { + long offset; + + if (ctx->state.cfa_rule !=3D CFA_REG_OFFSET) + return -EINVAL; + ret =3D read_sleb128(&cur, end, &offset); + if (ret) + return ret; + if (check_mul_overflow(offset, fde->cie.data_align, &offset)) + return -EINVAL; + + ctx->state.cfa_offset =3D offset; + break; + } + + case DW_CFA_restore_extended: { + unsigned long reg; + int idx; + + if (ctx->cie) + return -EINVAL; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) + ctx->state.reg_rule[idx] =3D ctx->cie_state.reg_rule[idx]; + break; + } + + case DW_CFA_undefined: { + unsigned long reg; + int idx; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + + if (reg =3D=3D EH_FRAME_REG_SP) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) + ctx->state.reg_rule[idx] =3D REG_UNDEFINED_EXPLICIT; + break; + } + + case DW_CFA_same_value: { + unsigned long reg; + int idx; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + + if (reg =3D=3D EH_FRAME_REG_SP && eh_frame_reject_sp_rule()) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) + ctx->state.reg_rule[idx] =3D REG_SAME_VALUE; + break; + } + + case DW_CFA_offset_extended: { + unsigned long reg, _offset; + long offset; + int idx; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_uleb128(&cur, end, &_offset); + if (ret) + return ret; + if (check_mul_overflow(_offset, fde->cie.data_align, &offset)) + return -EINVAL; + + if (reg =3D=3D EH_FRAME_REG_SP && eh_frame_reject_sp_rule()) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) { + ctx->state.reg_rule[idx] =3D REG_OFFSET; + ctx->state.reg_offset[idx] =3D offset; + } + break; + } + + case DW_CFA_offset_extended_sf: { + unsigned long reg; + long offset; + int idx; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_sleb128(&cur, end, &offset); + if (ret) + return ret; + if (check_mul_overflow(offset, fde->cie.data_align, &offset)) + return -EINVAL; + + if (reg =3D=3D EH_FRAME_REG_SP && eh_frame_reject_sp_rule()) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) { + ctx->state.reg_rule[idx] =3D REG_OFFSET; + ctx->state.reg_offset[idx] =3D offset; + } + break; + } + + case DW_CFA_val_offset: { + unsigned long reg, _offset; + long offset; + int idx; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_uleb128(&cur, end, &_offset); + if (ret) + return ret; + if (check_mul_overflow(_offset, fde->cie.data_align, &offset)) + return -EINVAL; + + if (reg =3D=3D EH_FRAME_REG_SP && offset !=3D EH_FRAME_SP_VAL_OFFSET) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) { + ctx->state.reg_rule[idx] =3D REG_VAL_OFFSET; + ctx->state.reg_offset[idx] =3D offset; + } + break; + } + + case DW_CFA_val_offset_sf: { + unsigned long reg; + long offset; + int idx; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_sleb128(&cur, end, &offset); + if (ret) + return ret; + if (check_mul_overflow(offset, fde->cie.data_align, &offset)) + return -EINVAL; + + if (reg =3D=3D EH_FRAME_REG_SP && offset !=3D EH_FRAME_SP_VAL_OFFSET) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) { + ctx->state.reg_rule[idx] =3D REG_VAL_OFFSET; + ctx->state.reg_offset[idx] =3D offset; + } + break; + } + + case DW_CFA_register: { + unsigned long reg1, reg2; + int idx; + + ret =3D read_uleb128(&cur, end, ®1); + if (ret) + return ret; + ret =3D read_uleb128(&cur, end, ®2); + if (ret) + return ret; + + if (reg1 =3D=3D EH_FRAME_REG_SP && eh_frame_reject_sp_rule()) + return -EOPNOTSUPP; + + idx =3D reg_to_index(reg1); + if (idx >=3D 0) { + ctx->state.reg_rule[idx] =3D REG_REGISTER; + ctx->state.reg_regnum[idx] =3D reg2; + } + break; + } + + case DW_CFA_expression: + case DW_CFA_val_expression: { + unsigned long reg, expr_len; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + ret =3D read_uleb128(&cur, end, &expr_len); + if (ret) + return ret; + + if (cur + expr_len > end) + return -EINVAL; + + if (reg =3D=3D EH_FRAME_REG_SP || reg =3D=3D EH_FRAME_REG_FP || reg =3D= =3D EH_FRAME_REG_RA) + return -EOPNOTSUPP; + + cur +=3D expr_len; + break; + } + + case DW_CFA_remember_state: + if (ctx->stack_depth >=3D EH_FRAME_MAX_STATE_STACK) + return -EINVAL; + ctx->stack[ctx->stack_depth++] =3D ctx->state; + break; + + case DW_CFA_restore_state: + if (ctx->stack_depth <=3D 0) + return -EINVAL; + ctx->state =3D ctx->stack[--ctx->stack_depth]; + break; + + default: + return -EOPNOTSUPP; + } + break; + + default: + return -EOPNOTSUPP; + } + + *cur_ptr =3D cur; + *ip_ptr =3D ip; + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int __do_cfi_program(struct eh_frame_section *sec, + struct eh_frame_fde *fde, + unsigned long target_ip, + struct eh_frame_cfi_context *ctx) +{ + void __user *cfi_ptr; + unsigned long cfi_size; + unsigned long ip =3D fde->func_addr; + unsigned long cur; + unsigned int insn_count =3D 0; + int ret; + + /* Initialize state */ + ctx->state.cfa_rule =3D CFA_UNDEFINED; + ctx->state.reg_rule[FP_IDX] =3D REG_UNDEFINED_IMPLICIT; + ctx->state.reg_rule[RA_IDX] =3D REG_UNDEFINED_IMPLICIT; + ctx->stack_depth =3D 0; + + /* Process CIE initial CFI instructions (if any) */ + ctx->cie =3D true; + cfi_ptr =3D (void __user *)fde->cie.cfi_insn_start; + cfi_size =3D fde->cie.cfi_insn_end - fde->cie.cfi_insn_start; + scoped_user_read_access_size(cfi_ptr, cfi_size, Efault) { + cur =3D fde->cie.cfi_insn_start; + while (cur < fde->cie.cfi_insn_end) { + if (insn_count++ >=3D EH_FRAME_CFI_INSN_LIMIT) + return -EINVAL; + ret =3D __do_cfi_insn(sec, fde, &cur, fde->cie.cfi_insn_end, &ip, targe= t_ip, ctx); + if (ret) + return ret; + } + } + + /* Save CIE state for DW_CFA_restore[_extended] */ + ctx->cie_state =3D ctx->state; + + /* Do not allow remember/restore between CIE and FDE */ + ctx->stack_depth =3D 0; + + /* Process FDE CFI instructions up to target IP */ + ctx->cie =3D false; + cfi_ptr =3D (void __user *)fde->cfi_insn_start; + cfi_size =3D fde->cfi_insn_end - fde->cfi_insn_start; + scoped_user_read_access_size(cfi_ptr, cfi_size, Efault) { + cur =3D fde->cfi_insn_start; + while (cur < fde->cfi_insn_end && ip <=3D target_ip) { + if (insn_count++ >=3D EH_FRAME_CFI_INSN_LIMIT) + return -EINVAL; + ret =3D __do_cfi_insn(sec, fde, &cur, fde->cfi_insn_end, &ip, target_ip= , ctx); + if (ret) + return ret; + } + } + + return 0; + +Efault: + return -EFAULT; +} + +static __always_inline int __find_frame_row(struct eh_frame_section *sec, + struct eh_frame_fde *fde, + unsigned long ip, + struct unwind_user_frame *frame) +{ + struct eh_frame_cfi_context ctx; + int ret; + + /* TODO: Signal frame - not supported yet */ + if (fde->cie.signal_frame) + return -EOPNOTSUPP; + + ret =3D __do_cfi_program(sec, fde, ip, &ctx); + if (ret) + return ret; + + /* Convert CFA rule */ + if (ctx.state.cfa_rule !=3D CFA_REG_OFFSET) + return -EINVAL; + + if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_SP) + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_SP_OFFSET; + else if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_FP) + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_FP_OFFSET; + else { + if (ctx.state.cfa_regnum > UINT_MAX) + return -EINVAL; + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_REG_OFFSET; + frame->cfa.regnum =3D ctx.state.cfa_regnum; + } + + if (ctx.state.cfa_offset < INT_MIN || + ctx.state.cfa_offset > INT_MAX) + return -EOPNOTSUPP; + frame->cfa.offset =3D ctx.state.cfa_offset; + + /* Convert RA rule */ + frame->outermost =3D false; + switch (ctx.state.reg_rule[RA_IDX]) { + case REG_UNDEFINED_IMPLICIT: + frame->ra.rule =3D UNWIND_USER_RULE_RETAIN; + break; + case REG_UNDEFINED_EXPLICIT: + frame->outermost =3D true; + break; + case REG_SAME_VALUE: + frame->ra.rule =3D UNWIND_USER_RULE_RETAIN; + break; + case REG_OFFSET: + if (ctx.state.reg_offset[RA_IDX] < INT_MIN || + ctx.state.reg_offset[RA_IDX] > INT_MAX) + return -EOPNOTSUPP; + frame->ra.rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF; + frame->ra.offset =3D ctx.state.reg_offset[RA_IDX]; + break; + case REG_VAL_OFFSET: + if (ctx.state.reg_offset[RA_IDX] < INT_MIN || + ctx.state.reg_offset[RA_IDX] > INT_MAX) + return -EOPNOTSUPP; + frame->ra.rule =3D UNWIND_USER_RULE_CFA_OFFSET; + frame->ra.offset =3D ctx.state.reg_offset[RA_IDX]; + break; + case REG_REGISTER: + if (ctx.state.reg_regnum[RA_IDX] > UINT_MAX) + return -EINVAL; + frame->ra.rule =3D UNWIND_USER_RULE_REG_OFFSET; + frame->ra.regnum =3D ctx.state.reg_regnum[RA_IDX]; + frame->ra.offset =3D 0; + break; + default: + return -EINVAL; + } + + /* Convert FP rule */ + switch (ctx.state.reg_rule[FP_IDX]) { + case REG_UNDEFINED_IMPLICIT: + case REG_UNDEFINED_EXPLICIT: + frame->fp.rule =3D UNWIND_USER_RULE_RETAIN; + break; + case REG_SAME_VALUE: + frame->fp.rule =3D UNWIND_USER_RULE_RETAIN; + break; + case REG_OFFSET: + if (ctx.state.reg_offset[FP_IDX] < INT_MIN || + ctx.state.reg_offset[FP_IDX] > INT_MAX) + return -EOPNOTSUPP; + frame->fp.rule =3D UNWIND_USER_RULE_CFA_OFFSET_DEREF; + frame->fp.offset =3D ctx.state.reg_offset[FP_IDX]; + break; + case REG_VAL_OFFSET: + if (ctx.state.reg_offset[FP_IDX] < INT_MIN || + ctx.state.reg_offset[FP_IDX] > INT_MAX) + return -EOPNOTSUPP; + frame->fp.rule =3D UNWIND_USER_RULE_CFA_OFFSET; + frame->fp.offset =3D ctx.state.reg_offset[FP_IDX]; + break; + case REG_REGISTER: + if (ctx.state.reg_regnum[FP_IDX] > UINT_MAX) + return -EINVAL; + frame->fp.rule =3D UNWIND_USER_RULE_REG_OFFSET; + frame->fp.regnum =3D ctx.state.reg_regnum[FP_IDX]; + frame->fp.offset =3D 0; + break; + default: + return -EINVAL; + } + + /* SP offset from CFA used in implicit CFA rule */ + frame->sp_off =3D EH_FRAME_SP_VAL_OFFSET; + + return 0; +} + +int eh_frame_find(unsigned long ip, struct unwind_user_frame *frame) +{ + struct mm_struct *mm =3D current->mm; + struct eh_frame_section *sec; + struct eh_frame_fde fde; + int ret; + + if (!mm) + return -EINVAL; + + guard(srcu)(&eh_frame_srcu); + + sec =3D mtree_load(&mm->eh_frame_mt, ip); + if (!sec) + return -ENOENT; + + ret =3D __find_fde(sec, ip, &fde); + if (!ret) + ret =3D __find_frame_row(sec, &fde, ip, frame); + + return ret; +} + static void free_section(struct eh_frame_section *sec) { kfree(sec); diff --git a/kernel/unwind/eh_frame.h b/kernel/unwind/eh_frame.h index 77eda5376dfb..9a0c71102742 100644 --- a/kernel/unwind/eh_frame.h +++ b/kernel/unwind/eh_frame.h @@ -2,6 +2,38 @@ #ifndef _EH_FRAME_H #define _EH_FRAME_H =20 +/* DWARF CFI opcodes */ +#define DW_CFA_advance_loc 0x40 +#define DW_CFA_offset 0x80 +#define DW_CFA_restore 0xc0 +#define DW_CFA_nop 0x00 +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_CFA_offset_extended_sf 0x11 +#define DW_CFA_def_cfa_sf 0x12 +#define DW_CFA_def_cfa_offset_sf 0x13 +#define DW_CFA_val_offset 0x14 +#define DW_CFA_val_offset_sf 0x15 +#define DW_CFA_val_expression 0x16 + +/* Helpers for CFI opcodes */ +#define DW_CFA_opcode(insn) ((insn) & 0xc0) +#define DW_CFA_operand(insn) ((insn) & 0x3f) + /* DWARF exception header pointer encodings */ #define DW_EH_PE_omit 0xff /* Formats */ @@ -27,4 +59,10 @@ #define DW_EH_PE_format(encoding) ((encoding) & 0x0f) #define DW_EH_PE_application(encoding) ((encoding) & 0x70) =20 +/* CIE/FDE constants */ +#define EH_FRAME_CIE_ID 0 +#define EH_FRAME_DWARF64_LENGTH 0xffffffff +#define EH_FRAME_CIE_MIN_LENGTH 13 +#define EH_FRAME_FDE_MIN_LENGTH 10 + #endif /* _EH_FRAME_H */ diff --git a/kernel/unwind/eh_frame_debug.h b/kernel/unwind/eh_frame_debug.h new file mode 100644 index 000000000000..5a3e4e7f065a --- /dev/null +++ b/kernel/unwind/eh_frame_debug.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _EH_FRAME_DEBUG_H +#define _EH_FRAME_DEBUG_H + +#include +#include "eh_frame.h" + +#ifdef CONFIG_DYNAMIC_DEBUG + +#define dbg(fmt, ...) \ + pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) + +#else /* !CONFIG_DYNAMIC_DEBUG */ + +#define dbg(args...) no_printk(args) + +#endif /* !CONFIG_DYNAMIC_DEBUG */ + +#endif /* _EH_FRAME_DEBUG_H */ --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D7AEF40DB25; Fri, 21 Aug 2026 19:54:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342086; cv=none; b=DECiI78k0ZbJadJJl2wmLUGGbCjhGQ8s8OEWVRkOMXsl9KX7txl7jlEONaVV4GjqTVl++WYHsRSMfzjp+fmirEKe6ceiZs4HhonFhXQ43XDYte8KdRdH4dEs8faEGZN33924nxvQhEUuoEUXTyZOZm8/0LNHnKvfpirsdmmkUGw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342086; c=relaxed/simple; bh=09Zi8Tthhl+ZVVEziNc/E61IazOn+tw78cTGwvV6nKw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pNcB260ytNXUcJlGGEZ9qF4M2cvoDblM0wBuVdUg0btX46gDEbO9bDIK101Lg24B1eujlrDavHMVb1o7xYS8YSHvAdJgzJrHGl2l0NVVxunHS7j7tDDUkQOqjEb2B2Sa22NLTC87zYy0wAjbJRU5lnexWO3C7m3cQgTkjU9orKw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=rHTvg4c0; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="rHTvg4c0" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIW6MP2254770; Fri, 21 Aug 2026 19:53:13 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=fFyEmBqPHxpjU8j/9 P+tl5drEECIF4jCQTJ4zpbmDvQ=; b=rHTvg4c0tpG0jc+0m09RG2JBzcAqL4SS2 RuOgtXd79HIUlJ7RIdGQ7uP2iY75+OTvlDqAt9xiRCDBbvle1UWGQ+FJjSrAL+Pz Wx6BkeoWQETyO23fya38uZoj1+OrOptMy/M6e7sX5vB/USZkrwZ1E9dfF/6YCY5X gIOwTSIfqaF78ulv5DczCs9TG3QDOJRR2JKd5fbjkhKLZx6gZ1NMpRJqLNfk7RMk sS5c/Vymo7lgCyw5GqjAGWwQLtjVS888U6M561sXMYjhp3thwUyxJFP1tkSG00qf RvXbdvaMBAi85BOJ8IUhMqnjslYMMSRKVXHCQKfj0JsrTh7xe6gjg== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4krkg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfHFG020569; Fri, 21 Aug 2026 19:53:11 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eqpupd-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr8ip42861024 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:08 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1108C20040; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C66572004B; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:07 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 10/24] unwind_user/eh_frame: Detect .eh_frame_hdr sections in executables Date: Fri, 21 Aug 2026 21:52:45 +0200 Message-ID: <20260821195259.2688377-11-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX1LAfFIvPD+Hx I5AbNO8kUSVGNJPWDQgtzJZq7wH0tp/2PvD9p3Kc+5VwuccbsU54hfdCvpI1NVFcMB3f7DAwHBD l2mG+2CqRoJKJeQrQAP2du7tUPbZHNE= X-Proofpoint-GUID: _ISUaloIPJWI5IfSkdhC2jJ4Ln3Jz1MD X-Proofpoint-ORIG-GUID: FgiNgdWvg_b-dAHk-xG20BzG0jo95Gcd X-Authority-Analysis: v=2.4 cv=RPmD2Yi+ c=1 sm=1 tr=0 ts=6a88aca9 cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=DTHPRnzGk-c2I6QTfOIA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX2G167PKX76KQ S8IuhleKu0MyJJEF7LWz/msiVyk0YvSf+wqF41YlG16tjYMT4ALqMLmOgpLCwI1OPSJj1zqHdO2 9oQdKLf7ivGfTzCQjoczBZ9cZfWDmnnNIOrBiGTA81fZrvRBlfDM1d+ZCkMteaZJOEcQKUooYj7 eMwMyfijHXB0sJ9E+mDJtxgJqFkdN/EW5wCwvs4YqGsWXGIkomFMiTJ9tfwLJ5+nBB9pum1SWgK 6chvOjT/e0j56EcBu6tf9fYT+08y4lPmqFXARkGQNtmxZfAbiRa+GQrwrornnKY/M8WGEk9/s2E yhbKZUKfc0S1ty6G0uAdiE40iIQhF1dET40V3a0Q8RxWaV7vam43/Xi3k3Egff63TCDIpGJOOuE q4r/HV/o8DnnKjZazsGnyxz71mO72J5iwc52tTjbSbL0ztUtvmg6X2NHPTI1KN3Y/A2GY4ThX3u K+xV28YPIz9B2qfKV3w== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 adultscore=0 spamscore=0 priorityscore=1501 bulkscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" When loading an ELF executable, automatically detect .eh_frame_hdr sections and associate them with the mm_struct. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- fs/binfmt_elf.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 16a56b6b3f6c..8c1cdd8318c5 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c @@ -48,6 +48,7 @@ #include #include #include +#include #include #include =20 @@ -637,6 +638,23 @@ static inline int make_prot(u32 p_flags, struct arch_e= lf_state *arch_state, return arch_elf_adjust_prot(prot, arch_state, has_interp, is_interp); } =20 +static void elf_add_eh_frame(const struct elf_phdr *text, + const struct elf_phdr *eh_frame, + unsigned long base_addr) +{ + unsigned long eh_frame_start, eh_frame_end, + text_start, text_end; + + eh_frame_start =3D base_addr + eh_frame->p_vaddr; + eh_frame_end =3D eh_frame_start + eh_frame->p_memsz; + + text_start =3D base_addr + text->p_vaddr; + text_end =3D text_start + text->p_memsz; + + /* Ignore return value, eh_frame[_hdr] section isn't critical */ + eh_frame_add_section(eh_frame_start, eh_frame_end, text_start, text_end); +} + /* This is much more generalized than the library routine read function, so we keep this separate. Technically the library read function is only provided so that we can read a.out libraries that have @@ -647,7 +665,7 @@ static unsigned long load_elf_interp(struct elfhdr *int= erp_elf_ex, unsigned long no_base, struct elf_phdr *interp_elf_phdata, struct arch_elf_state *arch_state) { - struct elf_phdr *eppnt; + struct elf_phdr *eppnt, *eh_frame_phdr =3D NULL; unsigned long load_addr =3D 0; int load_addr_set =3D 0; unsigned long error =3D ~0UL; @@ -673,7 +691,8 @@ static unsigned long load_elf_interp(struct elfhdr *int= erp_elf_ex, =20 eppnt =3D interp_elf_phdata; for (i =3D 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { - if (eppnt->p_type =3D=3D PT_LOAD) { + switch (eppnt->p_type) { + case PT_LOAD: { int elf_type =3D MAP_PRIVATE; int elf_prot =3D make_prot(eppnt->p_flags, arch_state, true, true); @@ -712,6 +731,19 @@ static unsigned long load_elf_interp(struct elfhdr *in= terp_elf_ex, error =3D -ENOMEM; goto out; } + break; + } + case PT_GNU_EH_FRAME: + eh_frame_phdr =3D eppnt; + break; + } + } + + if (eh_frame_phdr) { + eppnt =3D interp_elf_phdata; + for (i =3D 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { + if (eppnt->p_flags & PF_X && eppnt->p_type =3D=3D PT_LOAD) + elf_add_eh_frame(eppnt, eh_frame_phdr, load_addr); } } =20 @@ -837,6 +869,7 @@ static int load_elf_binary(struct linux_binprm *bprm) unsigned long error; struct elf_phdr *elf_ppnt, *elf_phdata, *interp_elf_phdata =3D NULL; struct elf_phdr *elf_property_phdata =3D NULL; + struct elf_phdr *eh_frame_phdr =3D NULL; unsigned long elf_brk; bool brk_moved =3D false; int retval, i; @@ -945,6 +978,10 @@ static int load_elf_binary(struct linux_binprm *bprm) executable_stack =3D EXSTACK_DISABLE_X; break; =20 + case PT_GNU_EH_FRAME: + eh_frame_phdr =3D elf_ppnt; + break; + case PT_LOPROC ... PT_HIPROC: retval =3D arch_elf_pt_proc(elf_ex, elf_ppnt, bprm->file, false, @@ -1242,6 +1279,14 @@ static int load_elf_binary(struct linux_binprm *bprm) elf_brk =3D k; } =20 + if (eh_frame_phdr) { + for (i =3D 0, elf_ppnt =3D elf_phdata; + i < elf_ex->e_phnum; i++, elf_ppnt++) { + if (elf_ppnt->p_flags & PF_X && elf_ppnt->p_type =3D=3D PT_LOAD) + elf_add_eh_frame(elf_ppnt, eh_frame_phdr, load_bias); + } + } + e_entry =3D elf_ex->e_entry + load_bias; phdr_addr +=3D load_bias; elf_brk +=3D load_bias; --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BC780411693; Fri, 21 Aug 2026 19:54:49 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342091; cv=none; b=ieE7uaQXm/aojR3n4EEQ5/qnXxSrZCQMrYANJ7tvKpzpmNMrcB3DqkOjOTFxQo4vYyd28S8O2x4nY9hhTP5jHY02YzkjsLtzNjWCH5wqWH3hHBIWu1SaFq6g4awf0RosBl/cgvmnFCC0pv+sRC4wHlaaxScxOE5PtOUFoxwj0fE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342091; c=relaxed/simple; bh=AMhQNb4JAsa+jlBSzff6AGFydffy3B//nxd42wH5HfA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=nX8mDoDgqRFANX5jP2hKbipfyn4dr18eNzeL9U3YtwwFLl94yjdT+YN9VLZz/0DBm9OvIr/hSF/MMdm103HOL0Jmen1Gb/hPUR+ZtdyrF/Ft/qVRdxX1ISTdWNzEyVX5tGPKbVAm0w5ctvfA3Hr5B+WLIwCQG+aBhjYuK3Xc8GM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=LV8PegSH; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="LV8PegSH" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVwqW492146; Fri, 21 Aug 2026 19:53:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=9uRn1piC2zfGR8Dyy ycUNE9uLIucBpzYcAaaqwnf1uo=; b=LV8PegSHn1j+L2Q/kfqkxJaxaBse0lpi3 qkEd9Q8A46zCKnXObhRZ0YnGKN+/ktddhbaGtZctiD0w0H+oyveqaLoBWA6dofLc XtWb/D2YC5WKqYsPJ0aw36zJCDYzXEvtrmheBmVLFeRsNuKoiw0y4lQH9jDCU1Wd Taw5uzX64v84sLNLvAsSVd3sw9ZNVWuG+6EoPDRQmnbpf0yHNjCktyFul8BJunDX 19tQ+FAnSvZRmQ59QTzQCylon6t5SZJEQKTap5caW2AcYqUpTnxxaGVABuqYz/9C lwFo+jozT+R7+obP5uao2bDuLInnT2P8PC3XR4RxiGuh2yXbjzTUA== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0kvd2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:14 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfHak020582; Fri, 21 Aug 2026 19:53:14 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eqpupq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr8Qh42861026 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:08 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 526972004B; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 15AD520043; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 11/24] unwind_user/eh_frame: Wire up unwind_user to eh_frame Date: Fri, 21 Aug 2026 21:52:46 +0200 Message-ID: <20260821195259.2688377-12-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-ORIG-GUID: lIugM_vnGLWqnLWURCpxLBatY63qBa1o X-Proofpoint-GUID: BIm13viEOWutGzu1kaI7vNWFv2ZYIJsu X-Authority-Analysis: v=2.4 cv=RoX16imK c=1 sm=1 tr=0 ts=6a88acab cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=Z71hq_FPCwn_qcrh8uAA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXy0GgUFSo/469 qYEnqW47Cdxd4zX2QKvPhtBndZEeKqe3A9r2NTy72RxodgUSbmFdFXRrBToLSglvG07cm7+oHQ0 SICO3S7DNhYY1mbjE8OujdKuBStL334= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXw7DidMuGOLaQ BHHSa2w55R6wCeocy9ZPPokYcjIq8DS1Xv3lNHPrr/84/dpJbE0M59/7zTVxRY+uXZ9e+YuY0ny jfrzlKFQrUphFJTMPF9s6dWV8IPq+VqEFNeZ7rFt9yjroYkRlLUArKGJQ1pVg9rJBXv1IJIczo9 urywnSzrG5L4uLjRuNS1GGEUlzaurWKuzW9LUZ2kxo1/7kX12+dhvlIAZrY6f96yUMVGi8N9vJb 7jqnv3rub8MtL1K0GpCZuYy0mvEO6EjwCzCOxtlaQUSYNOhSkNmjbJYrDOGFdXOKZgbdw0ZcnXJ 3dT65G2nmH0va6qtwrVMO/HX4odJWsKVxNr3EPyYfdS0Ng81mjbKMR5pngRJJI3UdiGoPdP3G55 HHS4pJtcqXZF45CARca4L2yutp/wuvTVkhhXd1PUG6FP9xcLFaJwSaTsdAS6Y20tg2e53tCBRmP QxF5MyIeIgzvTw3iYlA== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 suspectscore=0 malwarescore=0 adultscore=0 clxscore=1015 phishscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Now that the eh_frame infrastructure is fully in place, make it work by hooking it up to the unwind_user interface. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- arch/Kconfig | 1 + include/linux/unwind_user_types.h | 4 +++- kernel/unwind/user.c | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/arch/Kconfig b/arch/Kconfig index 60542d5e5731..ea969811f798 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -488,6 +488,7 @@ config UNWIND_USER =20 config HAVE_UNWIND_USER_EH_FRAME bool + select UNWIND_USER =20 config HAVE_UNWIND_USER_FP bool diff --git a/include/linux/unwind_user_types.h b/include/linux/unwind_user_= types.h index 4da058096259..88fc2fee8534 100644 --- a/include/linux/unwind_user_types.h +++ b/include/linux/unwind_user_types.h @@ -9,7 +9,8 @@ * available. */ enum unwind_user_type_bits { - UNWIND_USER_TYPE_FP_BIT =3D 0, + UNWIND_USER_TYPE_EH_FRAME_BIT =3D 0, + UNWIND_USER_TYPE_FP_BIT =3D 1, =20 NR_UNWIND_USER_TYPE_BITS, }; @@ -17,6 +18,7 @@ enum unwind_user_type_bits { enum unwind_user_type { /* Type "none" for the start of stack walk iteration. */ UNWIND_USER_TYPE_NONE =3D 0, + UNWIND_USER_TYPE_EH_FRAME =3D BIT(UNWIND_USER_TYPE_EH_FRAME_BIT), UNWIND_USER_TYPE_FP =3D BIT(UNWIND_USER_TYPE_FP_BIT), }; =20 diff --git a/kernel/unwind/user.c b/kernel/unwind/user.c index 830c620fe453..85fc82252af1 100644 --- a/kernel/unwind/user.c +++ b/kernel/unwind/user.c @@ -10,6 +10,7 @@ #include #include #include +#include =20 #ifdef CONFIG_DYNAMIC_DEBUG =20 @@ -173,6 +174,16 @@ static int unwind_user_next_fp(struct unwind_user_stat= e *state) return unwind_user_next_common(state, &fp_frame); } =20 +static int unwind_user_next_eh_frame(struct unwind_user_state *state) +{ + struct unwind_user_frame frame; + + /* eh_frame expects the frame to be local storage */ + if (eh_frame_find(state->ip, &frame)) + return -ENOENT; + return unwind_user_next_common(state, &frame); +} + static int unwind_user_next(struct unwind_user_state *state) { unsigned long iter_mask =3D state->available_types; @@ -186,6 +197,16 @@ static int unwind_user_next(struct unwind_user_state *= state) =20 state->current_type =3D type; switch (type) { + case UNWIND_USER_TYPE_EH_FRAME: + switch (unwind_user_next_eh_frame(state)) { + case 0: + return 0; + case -ENOENT: + continue; /* Try next method. */ + default: + state->done =3D true; + } + break; case UNWIND_USER_TYPE_FP: if (!unwind_user_next_fp(state)) return 0; @@ -214,6 +235,8 @@ static int unwind_user_start(struct unwind_user_state *= state) return -EINVAL; } =20 + if (current_has_eh_frame()) + state->available_types |=3D UNWIND_USER_TYPE_EH_FRAME; if (IS_ENABLED(CONFIG_HAVE_UNWIND_USER_FP)) state->available_types |=3D UNWIND_USER_TYPE_FP; =20 --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 50E7740F720; Fri, 21 Aug 2026 19:53:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342026; cv=none; b=EoWRHcD237qNvhW9w9DkAfsyLz9pH5k3GSC36XA97W/xWlLSqGCPfhy01bxYyLF0a19t0zz8NIBLwkx80VB27lb7WDQTpkL9eUbiR8CsLMQOdnFgg90801I6WjgaclIGZ01tSs2BtqumrZ9TtGlirXjpz3EHU1s9C7lqEZAQxhc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342026; c=relaxed/simple; bh=M1KvrJ6D665U2O1Y4c7wBpDUGn1F8NtBsXmty/EIsrM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=t/ORKktICKZIsA3rDrFUTXe7ftErYCl0hPyltCG90Pr1/Nw/GeTRGsc9q9phxngzsff2XSTroDVBvRRnlFPTTQMeioHKiUhTIMMZ0WMEPGAwHvWXZ7ThBvuvtj55uyVJoNZJ/ubmhJMEutXI3mRnlOacl/ZM5+Mas5NwwD0SxSw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=eLzh3U+I; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="eLzh3U+I" Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVf3d2387540; Fri, 21 Aug 2026 19:53:14 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=a08TLJkK4tjV5RcUT N7phu2xyYTSc6ax/xOBLLidlG4=; b=eLzh3U+I4vclSHrbeeVQWJaxPsAIc6z6x pO3ROgDn/8GiKyaGtegTiHAHsGVN+uHBDG2zIlE7d7Fk8W2+7W0OWSRCQ+8grsUx J2Ls9CajgofVHwXXCKsKA3zDwwLaqTIaN6L9A1EeE2TrTa0ne4bUOMPgvdE/QSJy 8m1vfUhsoMdR+O68/6Zo5UDIo7c3cauiMwrRJBVstVRWTWsU0um/3CUmasNl5caZ PUI1/B53xYAzfvnkQEnE9FTnb7f8WmaVjCGdtM4ozWJzbq0VKRHaMbTt77gD0eXG iZHEaiN558oRwETLxcchScriwv8gL8zx08dwmtuXg7mRFr/XQiPdA== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4kns1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfHGU023473; Fri, 21 Aug 2026 19:53:12 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g32twpraw-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr8L842861030 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:08 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 94D2920043; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 5772D20040; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 12/24] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption Date: Fri, 21 Aug 2026 21:52:47 +0200 Message-ID: <20260821195259.2688377-13-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=CpuPtH4D c=1 sm=1 tr=0 ts=6a88aca9 cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=sOSzolwKFyyup9Hw6m8A:9 X-Proofpoint-ORIG-GUID: YytZiVDjTCLnHUHldcwXwuOsSv6yH0Wq X-Proofpoint-GUID: WVqLuEpqhkkV7vsNZsNV71jZIU6aYfwM X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX3IkZ1tJvYvJQ RIzE9ax/Gg+fFx9w7JOsCaQTnhW6LH+cfYFnGHbYIP98oIZZFMBWSfZPIjqtg1DO/psyCfu6Wq8 0uXWr7h/8vZ2n/S7PIOxsA4blX1yjiQ= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX9S1ylM4qJrQ3 OMoyuzRuNXK8jyJfUGPDv1Zj8t5hwWzFPLw8+PJMtmsnZEPrjWAMDC4oHqzhb2c2ROY13kYEPEb bgR9Pm4BjRhdoBFImQRb6P41WegoLfJYj8hU+O1LFNGhCMfZYHepCFd6no2LulcjcL02ksDn2cF VDNhPDJ/RtjE2TbMhAxHEyTFfdG4kMxnQ57dWiJ0+eSLeteIZcZJ8GEABs/HjO4ZvVXwcUuD3cr hSSPM0hKjthy+JtUu2i9kMDe5YRDmlHEg6JSuoUVbbVXl87wO2Pnj7CiHFWNgh30LCOuPwyN7uo vdDFI01SIe//xy9ZznXyYtcL74HppLHvfkzt8S65XV1NghEZzEtJdoChP3wa3d7u/NzLS3hCJvE H4vlY6RpReLWZ8XtTkxW8DkvrH7Q4QdhRBV2pNCPUKqE7o5YXIRPuj3aTO/1rVF4g0YefPR0g0c UYxw1zebLYEq5d5uhEQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 adultscore=0 bulkscore=0 malwarescore=0 phishscore=0 lowpriorityscore=0 spamscore=0 clxscore=1015 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" To avoid continued attempted use of a bad .eh_frame[_hdr] sections, remove them on demand when the first sign of corruption is detected. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- kernel/unwind/eh_frame.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 21f40805b417..327849ea4a69 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1202,6 +1202,15 @@ int eh_frame_find(unsigned long ip, struct unwind_us= er_frame *frame) if (!ret) ret =3D __find_frame_row(sec, &fde, ip, frame); =20 + /* + * Unregister .eh_frame[_hdr] in case of an error, + * e.g. EINVAL (corrupted) or EFAULT (inaccessible). + * Keep if ENOENT (not found) or EOPNOTSUPP (unsupported CFI). + */ + if (ret && (ret !=3D -ENOENT && ret !=3D -EOPNOTSUPP)) + if (eh_frame_remove_section(sec->eh_frame_hdr_start)) + dbg("eh_frame_remove_section() failed\n"); + return ret; } =20 --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA7E140EB9D; Fri, 21 Aug 2026 19:53:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342021; cv=none; b=mwW2+rzCJI46NTh+yQGgUVqKgdOatzIQPUK5qpyIIiO+rTERB7aCmYBKKvwqSjSoMzlqtojw1EoS5IfZxMQTnexiljRD/Z3Yq+3XY/FWRLmL4cuSoUrnTe8/xtyGIOw6zWpmpGjzcKqXPuhRxRrTvyZ5YfUx3WswS7Xv2pq/U8Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342021; c=relaxed/simple; bh=zfkrCG/grEsqBerQEjKKNJBX6y9+FEaLBw9oftt91nw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mvzCL49P/FlBj2vUgotqjsWzZbqkfGMa4TvBjyuRjLWE/uTG+TBual9UB2pm6zdN5Ml5/cT9jjgxGBgetJYmOpniDdCA0/F7ck8G8XgBOdiwi8qIpAEzess18Nd/zJUwLAtCK1URuDD52zgj3yjApCT9/5dD7+o6Rkm+WmEO8+8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=T7vlRFjM; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="T7vlRFjM" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVjs3491844; Fri, 21 Aug 2026 19:53:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=0slGNflhrASa31G14 eLJHOXwNvhEtUH0F5bLRdVkFUs=; b=T7vlRFjM1inAGfvxdtdyJHpzun/EHxP3+ lY1uWqgJ4Jo4AQb0l4g3YJiNDULwN7BsJ2LmjvvKfr4KEAGt3SFZHB+0VP3+3xTt oCRLz//RuisXnltwhn+OUStZ6JbT/9eev6Z0nWiv6SxpXKhwBRkl4eaLgwxbMT0E bdW6UnubT61ghw5jqCueOtXN6IQMldfFSvviP9EW95XMPMdWPK0jUQed7S96dKS6 6Dralb1yQZ1OsxIq5RYSaxtzyqSGUJyUILBgKMZW9zYHm5oDP+HZbhMzZuSDHNwh VVdfI3OUU7R+dNUF80ZhJuXEszpM7u+BvZDEqwi4O//nyn3Zbj7Kg== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0kvcy-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:14 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfRI5016689; Fri, 21 Aug 2026 19:53:13 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xhpnkq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr8d542861032 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:09 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D7F0320040; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 999722004B; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 13/24] unwind_user/eh_frame: Show file name in debug output Date: Fri, 21 Aug 2026 21:52:48 +0200 Message-ID: <20260821195259.2688377-14-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-ORIG-GUID: 2CbATQqS6hTrEGGwpRM1UyfOT3Gf12eC X-Proofpoint-GUID: G937tc7y73pR_qeBgyYIJ355qus_8-MH X-Authority-Analysis: v=2.4 cv=RoX16imK c=1 sm=1 tr=0 ts=6a88acaa cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=FE0x1-_S9R1QEdhOvlkA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXwJRuihnlj8Wf ForN2vrzsiGNmDI9ObJzVCi67VkA2TaRuigxfeCZfHA3SLLCp+3UQdowz4fWa73m83b4oWwEhFi 3xFYwYNsvUgjBkfR7RcdyqVkS8Gljc0= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX5UP4lLFVF8nE drB90e9PbFqfohlCi7WCl+vVbbM3i0Im4guFMHmcZrt1Hb2IJzOULvrbVTgK4EIdgDzsoxRvEqa 184e90aGvy5cDucAd5XyNKELUbrEEGZd3ay3m9ucLxlV4oquVbaS1qD48k63tn7MRH8AbeqBsQU ImxqLTnCQj8EVG9ywWIZtz/dzxuah8DNHg/8cazgKj+L7GbE1AE2ERliMIXRhH8kCSNkQA2W/Hi l1KS3YpA40dmHZPiVcoaSYDC6PSTlmIjY0RYWpKf5iLXZhb6UFFmvsZwuJTgpQK3ax28XzlfL7j tGB1bUdFoYw+ELkyGGtEOYo2RCXsgE81qcKMd5z8bbTZxhQUVK04rSdH/pNgbD0UO78TTCSmdp1 2fDfdNXqk+OFhl4lPsdilBRM4JSIZhRlRX8qPfuCP9CqH2DORtOT/MXqTPswjYNvkXUdqDMy6+w PD/J3HpzHq1GztSOo6w== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 suspectscore=0 malwarescore=0 adultscore=0 clxscore=1015 phishscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" When debugging eh_frame issues, the error messages aren't all that helpful without knowing what file a corresponding .eh_frame[_hdr] section belongs to. Prefix debug output strings with the file name. Based on Josh Poimboeuf's, Steven Rostedt's, and my unwind user sframe implementation. Signed-off-by: Jens Remus --- include/linux/eh_frame.h | 4 ++++ kernel/unwind/eh_frame.c | 13 ++++++++---- kernel/unwind/eh_frame_debug.h | 37 ++++++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h index 740316b19df3..70b4f9d12828 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -11,6 +11,10 @@ struct eh_frame_section { struct rcu_head rcu; =20 +#ifdef CONFIG_DYNAMIC_DEBUG + const char *filename; +#endif + unsigned long eh_frame_hdr_start; unsigned long eh_frame_hdr_end; unsigned long text_start; diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 327849ea4a69..96237a96d263 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1207,15 +1207,18 @@ int eh_frame_find(unsigned long ip, struct unwind_u= ser_frame *frame) * e.g. EINVAL (corrupted) or EFAULT (inaccessible). * Keep if ENOENT (not found) or EOPNOTSUPP (unsupported CFI). */ - if (ret && (ret !=3D -ENOENT && ret !=3D -EOPNOTSUPP)) + if (ret && (ret !=3D -ENOENT && ret !=3D -EOPNOTSUPP)) { + dbg_sec("removing bad .eh_frame[_hdr] section\n"); if (eh_frame_remove_section(sec->eh_frame_hdr_start)) dbg("eh_frame_remove_section() failed\n"); + } =20 return ret; } =20 static void free_section(struct eh_frame_section *sec) { + dbg_free(sec); kfree(sec); } =20 @@ -1342,6 +1345,8 @@ int eh_frame_add_section(unsigned long eh_frame_hdr_s= tart, sec->text_start =3D text_start; sec->text_end =3D text_end; =20 + dbg_init(sec); + ret =3D eh_frame_read_header(sec); if (ret) goto err_free; @@ -1349,8 +1354,8 @@ int eh_frame_add_section(unsigned long eh_frame_hdr_s= tart, ret =3D mtree_insert_range(eh_frame_mt, sec->text_start, sec->text_end - = 1, sec, GFP_KERNEL_ACCOUNT); if (ret) { - dbg("mtree_insert_range failed: text=3D%lx-%lx\n", - sec->text_start, sec->text_end); + dbg_sec("mtree_insert_range failed: text=3D%lx-%lx\n", + sec->text_start, sec->text_end); goto err_free; } =20 @@ -1372,7 +1377,7 @@ static int __eh_frame_remove_section(struct ma_state = *mas, struct eh_frame_section *sec) { if (mas_erase(mas) !=3D sec) { - dbg("mas_erase failed: text=3D%lx\n", sec->text_start); + dbg_sec("mas_erase failed: text=3D%lx\n", sec->text_start); return -EINVAL; } =20 diff --git a/kernel/unwind/eh_frame_debug.h b/kernel/unwind/eh_frame_debug.h index 5a3e4e7f065a..40a80861d4d4 100644 --- a/kernel/unwind/eh_frame_debug.h +++ b/kernel/unwind/eh_frame_debug.h @@ -3,6 +3,7 @@ #define _EH_FRAME_DEBUG_H =20 #include +#include #include "eh_frame.h" =20 #ifdef CONFIG_DYNAMIC_DEBUG @@ -10,9 +11,45 @@ #define dbg(fmt, ...) \ pr_debug("%s (%d): " fmt, current->comm, current->pid, ##__VA_ARGS__) =20 +#define dbg_sec(fmt, ...) \ + dbg("%s: " fmt, sec->filename, ##__VA_ARGS__) + +static inline void dbg_init(struct eh_frame_section *sec) +{ + struct mm_struct *mm =3D current->mm; + struct vm_area_struct *vma; + const char *name; + + guard(mmap_read_lock)(mm); + vma =3D vma_lookup(mm, sec->eh_frame_hdr_start); + if (!vma) + sec->filename =3D kstrdup("(vma gone???)", GFP_KERNEL_ACCOUNT); + else if (vma_is_anonymous(vma)) + sec->filename =3D kstrdup("(anonymous)", GFP_KERNEL_ACCOUNT); + else if (vma->vm_file) + sec->filename =3D kstrdup_quotable_file(vma->vm_file, GFP_KERNEL_ACCOUNT= ); + else if (vma->vm_ops && vma->vm_ops->name && (name =3D vma->vm_ops->name(= vma))) + sec->filename =3D kstrdup(name, GFP_KERNEL_ACCOUNT); + else if (arch_vma_name(vma)) + sec->filename =3D kstrdup(arch_vma_name(vma), GFP_KERNEL_ACCOUNT); + else if (!vma->vm_mm) + sec->filename =3D kstrdup("(vdso)", GFP_KERNEL_ACCOUNT); + else + sec->filename =3D kstrdup("(vma unknown???)", GFP_KERNEL_ACCOUNT); +} + +static inline void dbg_free(struct eh_frame_section *sec) +{ + kfree(sec->filename); +} + #else /* !CONFIG_DYNAMIC_DEBUG */ =20 #define dbg(args...) no_printk(args) +#define dbg_sec(args...) no_printk(args) + +static inline void dbg_init(struct eh_frame_section *sec) {} +static inline void dbg_free(struct eh_frame_section *sec) {} =20 #endif /* !CONFIG_DYNAMIC_DEBUG */ =20 --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 07B1C353A91; Fri, 21 Aug 2026 19:54:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342077; cv=none; b=uyYQkyKtDxYdVt10ZPTTJ2VsDieV7qx9Ixp6ZncH7gWsX0LMaJ4kSFQJd3De/sSNYTrdSHgKcjKHmUYJj68bB4DudI5tv71Rosfx+DGA/9IHoN9Di0EsfXl5XjKCTKbAkmVb7l5yNnBMdzlNb65I4EtjDZqT/s0DyLY2xrvBs9E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342077; c=relaxed/simple; bh=+Z9miNuw66BzYd2CkMiywvYw35N8qAwEFDJwozK58T0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=a/I7bq1rrDXcn8Eky89opIKf12vWXbOF5/qfT84Rye0wjszsFGDzlwkdAFRV7uuShkKfgE4iOCC9/sG5dwJ3x9SvvOjS3VOpzrsr91POUZKPEJgbdiRq+0iJVFvllHiVky81GrTpVAkhD32IUn1Q5WlkYqiWiEIcLZNx2JmdYAo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=GZxBnqcG; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="GZxBnqcG" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVfLR1237389; Fri, 21 Aug 2026 19:53:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=9ug5wA5UefrH1rkFi jmEW+AkmRi6rwLJHFRpVtdIb08=; b=GZxBnqcGu5ki0eu9/8vzFyTX7cC+I4Pdj FxUCCsOsIrDdY0zdasLQdujForlV29m9D7YO1CNdrHJMF6UKcZDiBi80qjmRsAUE ni4XQ27yhCagUqHZBlyrPQl3JuzcWyZ8SRJyM2jAYRF+dlrvRiLLKw0Yg+4wzr7U jnioCCZrlW3/S4R2VjCp6jxJznk9Fs9w5WZjG4xtTWv5KFdtbI/YjT4LxFHw0r1N hxEvr9URaWLEXOK44ODCLbQYU/gZb2mmDDBlrx9lhM5OABs45VW39VC7vZaMmBMW 1Jwsz+IDR9ZhCmw49NA8xxOFfM+O1sOQuYYM4yL3kGEe3guTR4e1A== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu2kr0m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfIqt008710; Fri, 21 Aug 2026 19:53:13 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354yxdwm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr9tR45679052 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:09 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 25BC020040; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id DD26B20043; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:08 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 14/24] unwind_user/eh_frame: Add .eh_frame[_hdr] validation option Date: Fri, 21 Aug 2026 21:52:49 +0200 Message-ID: <20260821195259.2688377-15-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=AdqB2XXG c=1 sm=1 tr=0 ts=6a88acaa cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VnNF1IyMAAAA:8 a=rU79QueooZ11dTUg0tsA:9 X-Proofpoint-GUID: V0QbgjbecwJnbO6dU4IgQ-bBO3sGdUfh X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX1iVigc/iW8LB zeqq4vE+GPJLSxItxBmu3VRnL/3oRRr8kjlci1KHJadHGRC8H43mpt1CqviFREy3nVAJODZ6sS8 h+ZaYSwA7HyQY9krH8TKU5pq6G7v4ziooiCBkfXjD+zXyxo+S+K4njorH6qNu+5bVD3683qrsPR BWd5mxzfiPbDbSmJfz9UjhgnFZsCzPH7F3DITljFiBBDbMSey+LGv1iqnXccg+SS3r4i9KKdgpN dqcOWVMILcDMfHF08nP3KyuF21Yw0S/EkuCa0vVmQv3KpzIi+8muccF18SyIoKLnXJtc5u936dT vjjbdCKvAqHIHue1ISrIK+CjZwy4iixTucHK0wJixY0F9qSqNPAJJCHeg7cqJ+Wl8MZ4k2e6nol F9dsWzGAxRX7Ol6nbVyVwIQMZxIUQrNs1j0cQFMaSOjD40K7mb4JO30O4HkxVWKJPvgPql0mf1Q g0JTqY8RxDnAiAAA0gg== X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX0mQVwO7Z4iLA sNZ6cUUHh4dcWQyiCHC5GHj8vpxe1LxlTshbbBebiyoUro73YJU9uvDE8r1LxykSUrg9HAsDj2i uyESaMo4IaSG23qdrih51d/Z6lyDL+w= X-Proofpoint-ORIG-GUID: lW3CGmU-Qqxb1m_pLlfWazP5XlGeBG4t X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 suspectscore=0 malwarescore=0 impostorscore=0 adultscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Add a debug feature to validate all .eh_frame[_hdr] sections when first loading the file rather than on demand. Signed-off-by: Jens Remus --- Notes (jremus): FIXME: dbg*() with UACCESS enabled. =20 Changes in RFC v2: - Fix compile error. (Sashiko AI) - Correct loop counter type to prevent infinite loop. (Sashiko AI) arch/Kconfig | 22 +++++++++ kernel/unwind/eh_frame.c | 90 ++++++++++++++++++++++++++++++++++ kernel/unwind/eh_frame_debug.h | 4 ++ 3 files changed, 116 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index ea969811f798..c06e5010a88a 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -490,6 +490,28 @@ config HAVE_UNWIND_USER_EH_FRAME bool select UNWIND_USER =20 +config EH_FRAME_VALIDATION + bool "Enable .eh_frame[_hdr] section debugging" + depends on HAVE_UNWIND_USER_EH_FRAME + depends on DYNAMIC_DEBUG + help + When adding an .eh_frame_hdr section for a test, validate the + entire section and its referenced entire .eh_frame section + immediately rather than on demand. + + This is a debug feature which is helpful for rooting out + .eh_frame[_hdr] section issues. If the .eh_frame[_hdr] + section is corrupt, it will fail to load immediately, with + more information provided in dynamic printks. + + This has a significant page cache footprint due to its reading + of the entire .eh_frame[_hdr] sections for every loaded executable + and shared library. Also, it's done for all processes, even those + which don't get stack traced by the kernel. Not recommended for + general use. + + If unsure, say N. + config HAVE_UNWIND_USER_FP bool select UNWIND_USER diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 96237a96d263..b0be56e31508 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1216,6 +1216,92 @@ int eh_frame_find(unsigned long ip, struct unwind_us= er_frame *frame) return ret; } =20 +#ifdef CONFIG_EH_FRAME_VALIDATION + +static int eh_frame_validate_section(struct eh_frame_section *sec) +{ + void __user *table_start_ptr; + unsigned long table_size; + u8 table_enc; + int entry_size; + unsigned long prev_func_addr; + unsigned long i; + + if (!sec->fde_count) { + dbg_sec(".eh_frame_hdr: invalid FDE count\n"); + return -EINVAL; + } + + table_enc =3D sec->binary_search_table_enc; + entry_size =3D 2 * encoded_pointer_size(table_enc); + if (!entry_size) { + dbg_sec(".eh_frame_hdr: invalid binary search table entry size\n"); + return -EINVAL; + } + table_start_ptr =3D (void __user *)sec->binary_search_table_start; + table_size =3D sec->binary_search_table_end - sec->binary_search_table_st= art; + + for (i =3D 0; i < sec->fde_count; i++) { + struct eh_frame_fde fde; + unsigned long cur; + unsigned long func_addr, fde_addr; + int ret; + + cur =3D sec->binary_search_table_start + i * entry_size; + + scoped_user_read_access_size(table_start_ptr, table_size, Efault) { + /* Read function start address from table */ + ret =3D read_encoded_pointer(sec, &cur, + sec->binary_search_table_end, + table_enc, &func_addr); + if (ret) { + dbg_sec_ehfh(cur, "table[%lu]: failed to read function start address\n= ", i); + return ret; + } + if (i && func_addr <=3D prev_func_addr) { + dbg_sec(".eh_frame_hdr: table[%lu]: not sorted\n", i); + return -EINVAL; + } + prev_func_addr =3D func_addr; + + /* Read FDE address from table */ + ret =3D read_encoded_pointer(sec, &cur, + sec->binary_search_table_end, + table_enc, &fde_addr); + if (ret) { + dbg_sec_ehfh(cur, "table[%lu]: failed to read FDE pointer\n", i); + return ret; + } + if (fde_addr < sec->eh_frame_start) { + dbg_sec(".eh_frame_hdr: table[%lu]: invalid FDE address\n", i); + return -EINVAL; + } + } + + ret =3D __read_fde(sec, fde_addr, &fde); + if (ret) { + dbg_sec(".eh_frame_hdr: table[%lu]: failed to read FDE at .eh_frame+%#l= x\n", + i, fde_addr - sec->eh_frame_start); + return ret; + } + if (func_addr !=3D fde.func_addr) { + dbg_sec(".eh_frame_hdr: table[%lu]: function start address mismatch\n",= i); + return -EINVAL; + } + } + + return 0; + +Efault: + return -EFAULT; +} + +#else /* !CONFIG_EH_FRAME_VALIDATION */ + +static int eh_frame_validate_section(struct eh_frame_section *sec) { retur= n 0; } + +#endif /* !CONFIG_EH_FRAME_VALIDATION */ + static void free_section(struct eh_frame_section *sec) { dbg_free(sec); @@ -1351,6 +1437,10 @@ int eh_frame_add_section(unsigned long eh_frame_hdr_= start, if (ret) goto err_free; =20 + ret =3D eh_frame_validate_section(sec); + if (ret) + goto err_free; + ret =3D mtree_insert_range(eh_frame_mt, sec->text_start, sec->text_end - = 1, sec, GFP_KERNEL_ACCOUNT); if (ret) { diff --git a/kernel/unwind/eh_frame_debug.h b/kernel/unwind/eh_frame_debug.h index 40a80861d4d4..bcb2d03ab9ab 100644 --- a/kernel/unwind/eh_frame_debug.h +++ b/kernel/unwind/eh_frame_debug.h @@ -14,6 +14,9 @@ #define dbg_sec(fmt, ...) \ dbg("%s: " fmt, sec->filename, ##__VA_ARGS__) =20 +#define dbg_sec_ehfh(addr, fmt, ...) \ + dbg_sec(".eh_frame_hdr+%#lx: " fmt, ((addr) - sec->eh_frame_hdr_start), #= #__VA_ARGS__) + static inline void dbg_init(struct eh_frame_section *sec) { struct mm_struct *mm =3D current->mm; @@ -47,6 +50,7 @@ static inline void dbg_free(struct eh_frame_section *sec) =20 #define dbg(args...) no_printk(args) #define dbg_sec(args...) no_printk(args) +#define dbg_sec_ehfh(args...) no_printk(args) =20 static inline void dbg_init(struct eh_frame_section *sec) {} static inline void dbg_free(struct eh_frame_section *sec) {} --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4FDA740EB88; Fri, 21 Aug 2026 19:53:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342016; cv=none; b=AXW1CyCEPpIkhCzFcIodE0le3B4m1GrZAbyXXvUJISfqwdLCzvHHq4g0Gihk+3ODi5YapW2AaV1AcWn5r5IQEQam7wRlZucLXSNHxCEVyyX0Oh7/4cogi9F1ici4mWDhdZxWZ4HfviRtqWaILj6yYrZ6GWiidGj1I289cVU6+r0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342016; c=relaxed/simple; bh=+FII3ZleZb3oyEqGkP8JYRC62Ua6H8UV4CkPYFoBSS4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sWQPe7y0VFyrCmQ3Tf4r/A2GX5c5aiJnPWXNHvdytK6gqi5A8zM7nStH+L9KfebUJpsKTyuH2n+N0UapaCvbNhOiGNQ649mcXMzl/79tX4zd9wEiq2ZEfB55gExdb2ZLBLVdwhN4goYrfamGhG4vJ1CzzcW3QzKvDm5QTGTIIdg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=BxBzHINU; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="BxBzHINU" Received: from pps.filterd (m0353725.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIViSn1237447; Fri, 21 Aug 2026 19:53:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=zNEI/rvzWWiCdBJ45 dXHM6TCzn9R2LbS7/L7IPC1vYA=; b=BxBzHINUHVTeZ/UVLbCnM1gU3NxkTbczp lOMcl981/fyHGanXxcLdVIBFmMWeT2BSdtsyQXWdRC7UkUMclAzsjHeQe5iFyo4N /HlBIlgdpjgDbZVMM/PUtyloCBrG6dlBhSxps5yFqkdrAkJ7Tfsp8rcUckZXNKqf EW/a3ndHzDkWmGqyR1/1tctZnwOS7SHSMQTSeJRr8uDh/SHez9Xgczo/shJ/FxI6 2aP5dUBn0QikmJM/8PdLiF2QV6KXJX+BLt/dUgU5tu7ffB3YhtAmN3FjsyYhO6tp MVKoE7PMDTTUpe8SoR1Xx4mUn1UmrAOLkiWl41kk3TkP1qk1EFTsg== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu2kr0q-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:14 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfIo1016590; Fri, 21 Aug 2026 19:53:13 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xhpnkt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr96a45679054 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:09 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6855820040; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2AB2F2004B; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 15/24] unwind_user/eh_frame: Duplicate registered .eh_frame[_hdr] section data on clone/fork Date: Fri, 21 Aug 2026 21:52:50 +0200 Message-ID: <20260821195259.2688377-16-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=AdqB2XXG c=1 sm=1 tr=0 ts=6a88acaa cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VnNF1IyMAAAA:8 a=D1Fd06331sE75a_1HDMA:9 X-Proofpoint-GUID: jEmS4Qqtg_JGoA_Q4fcGRFlzMHhtNirM X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX7LYlMIt3RLpI V475rJgnO+2DGP5MuYXojcdJtxphmoc/P/kIL4FozlenH6bfeERRjepps3Nizlp0ZBO+82AnGKO /4OoW2EDoBUKNHfEMniTehW0tZpw25JrVJlhYaXTbC5L82Q37zmu+tI5KPP75k5QWRBrZr3hUpt dbskFlV6LCnRtrtWH/Zb9vneKlCwpZ5e6t9Neq5U6SPv+ZmXJEicfH6INceC91uAssnNZDOinto Nxba65V1bGDIwpFpVff3cAg/91VM9Ep4/tS//JKB5rjCwVyD4KWh7nY3fFZYGmG8j0AphW7Vuhj Vuz14iDFlP4ER5sM091mbIkIj/f6vutu1b5Ujtsh8tQSWfPlltoifcRDlyqnAuWOM3FbYUvLebX y8kGdcp6STjzJBe22vJ5yAc10bzXBKzs2QkTWNcPoBYSdZ8jZZShG9GerNfUgkYWXEnw3un+Q7M 5gFVIshFUb0URKX2GrQ== X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX21cqWDdLir9a h2Gj8g3xhw58tb/R5jr+vPgnJ6MVtGnhUs8Zu51qPepKnDAv6Jc5N8Gmj94M4Xjui4fO02Srz1L m+LXXUVOck7jRUnAArr5+LYHRcmcxCg= X-Proofpoint-ORIG-GUID: _h4cdYqwFwZjAcD6Hm2pdlrqqzDZo3dt X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 priorityscore=1501 suspectscore=0 malwarescore=0 impostorscore=0 adultscore=0 bulkscore=0 lowpriorityscore=0 phishscore=0 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" When duplicating a process' virtual memory mappings also duplicate all of its registered .eh_frame_hdr sections stored in the per-mm maple tree to enable stacktracing using eh_frame of the child process. Signed-off-by: Jens Remus --- include/linux/eh_frame.h | 7 +++++ kernel/unwind/eh_frame.c | 48 ++++++++++++++++++++++++++++++++++ kernel/unwind/eh_frame_debug.h | 7 +++++ mm/mmap.c | 5 ++++ 4 files changed, 67 insertions(+) diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h index 70b4f9d12828..3c88ab2f7858 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -32,6 +32,7 @@ struct eh_frame_section { #define EH_FRAME_MT_FLAGS (MT_FLAGS_USE_RCU) =20 #define INIT_MM_EH_FRAME .eh_frame_mt =3D MTREE_INIT(eh_frame_mt, EH_FRAME= _MT_FLAGS), +extern int eh_frame_dup_mm(struct mm_struct *mm, struct mm_struct *oldmm); extern void eh_frame_free_mm(struct mm_struct *mm); =20 extern int eh_frame_add_section(unsigned long eh_frame_hdr_start, @@ -51,6 +52,12 @@ static inline bool current_has_eh_frame(void) #else /* !CONFIG_HAVE_UNWIND_USER_EH_FRAME */ =20 #define INIT_MM_EH_FRAME + +static inline int eh_frame_dup_mm(struct mm_struct *mm, struct mm_struct *= oldmm) +{ + return 0; +} + static inline void eh_frame_free_mm(struct mm_struct *mm) {} =20 static inline int eh_frame_add_section(unsigned long eh_frame_hdr_start, diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index b0be56e31508..1ac7308814a1 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1501,6 +1501,54 @@ int eh_frame_remove_section(unsigned long eh_frame_h= dr_start) return 0; } =20 +static void __eh_frame_dup_section(struct eh_frame_section *sec, + struct eh_frame_section *oldsec) +{ + sec->eh_frame_hdr_start =3D oldsec->eh_frame_hdr_start; + sec->eh_frame_hdr_end =3D oldsec->eh_frame_hdr_end; + sec->text_start =3D oldsec->text_start; + sec->text_end =3D oldsec->text_end; + + sec->eh_frame_start =3D oldsec->eh_frame_start; + sec->eh_frame_vma_end =3D oldsec->eh_frame_vma_end; + sec->binary_search_table_start =3D oldsec->binary_search_table_start; + sec->binary_search_table_end =3D oldsec->binary_search_table_end; + sec->fde_count =3D oldsec->fde_count; + sec->binary_search_table_enc =3D oldsec->binary_search_table_enc; + + dbg_dup(sec, oldsec); +} + +int eh_frame_dup_mm(struct mm_struct *mm, struct mm_struct *oldmm) +{ + struct eh_frame_section *sec, *oldsec; + unsigned long index =3D 0; + int ret; + + guard(srcu)(&eh_frame_srcu); + + mt_for_each(&oldmm->eh_frame_mt, oldsec, index, ULONG_MAX) { + sec =3D kzalloc(sizeof(*sec), GFP_KERNEL_ACCOUNT); + if (!sec) + return -ENOMEM; + + __eh_frame_dup_section(sec, oldsec); + + ret =3D mtree_insert_range(&mm->eh_frame_mt, + sec->text_start, + sec->text_end - 1, + sec, GFP_KERNEL_ACCOUNT); + if (ret) + goto err_free; + } + + return 0; + +err_free: + free_section(sec); + return ret; +} + void eh_frame_free_mm(struct mm_struct *mm) { struct eh_frame_section *sec; diff --git a/kernel/unwind/eh_frame_debug.h b/kernel/unwind/eh_frame_debug.h index bcb2d03ab9ab..e72e011ba539 100644 --- a/kernel/unwind/eh_frame_debug.h +++ b/kernel/unwind/eh_frame_debug.h @@ -41,6 +41,12 @@ static inline void dbg_init(struct eh_frame_section *sec) sec->filename =3D kstrdup("(vma unknown???)", GFP_KERNEL_ACCOUNT); } =20 +static inline void dbg_dup(struct eh_frame_section *sec, struct eh_frame_s= ection *oldsec) +{ + if (oldsec->filename) + sec->filename =3D kstrdup(oldsec->filename, GFP_KERNEL_ACCOUNT); +} + static inline void dbg_free(struct eh_frame_section *sec) { kfree(sec->filename); @@ -53,6 +59,7 @@ static inline void dbg_free(struct eh_frame_section *sec) #define dbg_sec_ehfh(args...) no_printk(args) =20 static inline void dbg_init(struct eh_frame_section *sec) {} +static inline void dbg_dup(struct eh_frame_section *sec, struct eh_frame_s= ection *oldsec) {} static inline void dbg_free(struct eh_frame_section *sec) {} =20 #endif /* !CONFIG_DYNAMIC_DEBUG */ diff --git a/mm/mmap.c b/mm/mmap.c index 2311ae7c2ff4..7715a799810e 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -48,6 +48,7 @@ #include #include #include +#include =20 #include #include @@ -1844,6 +1845,9 @@ __latent_entropy int dup_mmap(struct mm_struct *mm, s= truct mm_struct *oldmm) goto loop_out; } } + retval =3D eh_frame_dup_mm(mm, oldmm); + if (retval) + goto loop_out; /* a new mm has just been created */ retval =3D arch_dup_mmap(oldmm, mm); loop_out: @@ -1893,6 +1897,7 @@ __latent_entropy int dup_mmap(struct mm_struct *mm, s= truct mm_struct *oldmm) vm_unacct_memory(charge); } __mt_destroy(&mm->mm_mt); + eh_frame_free_mm(mm); /* * The mm_struct is going to exit, but the locks will be dropped * first. Set the mm_struct as unstable is advisable as it is --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 712BD411A03; Fri, 21 Aug 2026 19:53:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342043; cv=none; b=bahWKRCYLLrKx6SZzTg4DzxnqAGpNtGRriBy7t5ZPjugjnyvELXTAFB1rsn+16r4UBKbZ+zxs7hyTg0kO4e5PG+DqNOUQyJbrwUA+B0NiGfkQ3SGHpL+KOAViEb5AvOaz+N2qN6kVgbfgNjjamQRWbScbDgfuJV3wvRrxVs/wUw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342043; c=relaxed/simple; bh=CijnpLgnFKB8WMdF68gN5v75gDWZ0eEtgeICc4kMbVw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=kWJdHJ16E+AxzzPmLAHCG5FbcIep3TuEnj0tc0VEod+f67BB+6WOf8G0kdCgIUZd1HcWhxmaPNjjHfPAzoi9RYMCePdqw+XlwmkhcNGucQvF1TkuY4rPNgD/npMTbBQ6rmku53p/aXm7kbImDR4eT/JOVe86nQWPt+1IWJbrv3k= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=N39L+4wt; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="N39L+4wt" Received: from pps.filterd (m0360083.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVRZA2314623; Fri, 21 Aug 2026 19:53:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=kCOKOkueq+VfUETIJ ByLo8qoaTH3QETrvkMVm1Hwq4Q=; b=N39L+4wtOjIKhItS/LDFE9HK4zRRWTi/3 nTj+MJn1+RiPjzaT5jCX4zazCIsbfdmlHNzEEzvhFvVCC2PqmBX0EBD3jLC+oQyv oGvSWSvXQkd3/zH5pKEegwG0w3nSJ5YH2Fz712EXEA6GRLBncD88aQB7cz2RVs4l WdVZeeTBabURhJOe+JangBsaVxWLM+p1UrrWrF7+e6NuAqk1IALz+cOzRR60uWsp 4xld5yTJ71/A3KRzMYfNGJ6I0kNBsHpl1NO47TK35AFqSLoKJ1axKaBQsJSY8sFo j61io9W3dVDBc9kYJXUjFg7WkDqY1BhIQf3hMW9/An7/ArZfnx05w== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu1uteq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:14 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfHgn008693; Fri, 21 Aug 2026 19:53:13 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354yxdwq-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJr9VQ45679056 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:09 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AA43A20040; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6D50420043; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 16/24] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size Date: Fri, 21 Aug 2026 21:52:51 +0200 Message-ID: <20260821195259.2688377-17-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=LsCiDHdc c=1 sm=1 tr=0 ts=6a88acab cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=iQ6ETzBq9ecOQQE5vZCe:22 a=VnNF1IyMAAAA:8 a=bNYdn40op4m7Rmrl5ooA:9 X-Proofpoint-GUID: uBmxp-udTVl5WcoYm2i4owqnk8DaaQ15 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX/mRM2xk9j8h1 wPaUa+sIMGX/Kv+9jpvwKJ3yCpcD33FxyuNBrS/5LFdLXaxL7rLXsqR14AT+U/YwNrslSMVbnvm q6n9h16viKrhbqgewIe/sW64sbwI+9g= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXxLaSlVJu5mIK wEIrMKq9CZ1sWsiNYIymaZyS9WGDjHvRzbZMBcDMYDdPI5VTVkKA07UJY0SmT4oR7iNu7CpoIMg jYzQXQbsccQeRN1id1XIjugGUfu5s8vVFpzXN2BDPvSMdufUofs2rEHjbA0u6KIvnSJkLLMdu1h GT7dEe0E32yx9O6i3dvTAAu1AViOYNmPmOWY1ULCEXP5AI7z0fFx6Hc28cc6Xt4fvb9R/323iIY CcATHQvBLzUxjye/1TW/wCbOM5Uqnj9opGOMnfo4qa36Nn3ZKMP36TJOBtwN1ehqv0rqDjCUkAY g8WgnixvL3fEF9liMGRrGsGIEHb+V/sKuH3riRE2/qBSBQV2sKwE1XdWAfcA2ba1/o8zs9b7QVT GDGeadig5x+EFFsgO2J1fncCKFp2wgWb800EFjtcgF3C0t/wBeb1bSrSo48L7LAoNJJFIOw7ue4 kLbeG9Eh5dcF3bcArtA== X-Proofpoint-ORIG-GUID: xKmdZyASn5M0pRptJC8JiHcExZafOzkK X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 spamscore=0 priorityscore=1501 lowpriorityscore=0 bulkscore=0 adultscore=0 suspectscore=0 impostorscore=0 clxscore=1015 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" The DW_CFA_GNU_args_size DWARF CFI instruction is used by GCC to track the size of arguments pushed on the stack for exception handling purposes. It is not needed for stack tracing. Signed-off-by: Jens Remus --- Notes (jremus): This patch could be squashed into "unwind_user/eh_frame: Add support for reading .eh_frame section". Leaving separate for review. kernel/unwind/eh_frame.c | 11 +++++++++++ kernel/unwind/eh_frame.h | 1 + 2 files changed, 12 insertions(+) diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 1ac7308814a1..d185187b0c34 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -980,6 +980,17 @@ static __always_inline int __do_cfi_insn(struct eh_fra= me_section *sec, break; } =20 + case DW_CFA_GNU_args_size: { + unsigned long args_size; + + ret =3D read_uleb128(&cur, end, &args_size); + if (ret) + return ret; + + /* Ignore DW_CFA_GNU_args_size */ + break; + } + case DW_CFA_remember_state: if (ctx->stack_depth >=3D EH_FRAME_MAX_STATE_STACK) return -EINVAL; diff --git a/kernel/unwind/eh_frame.h b/kernel/unwind/eh_frame.h index 9a0c71102742..a43560486283 100644 --- a/kernel/unwind/eh_frame.h +++ b/kernel/unwind/eh_frame.h @@ -29,6 +29,7 @@ #define DW_CFA_val_offset 0x14 #define DW_CFA_val_offset_sf 0x15 #define DW_CFA_val_expression 0x16 +#define DW_CFA_GNU_args_size 0x2e =20 /* Helpers for CFI opcodes */ #define DW_CFA_opcode(insn) ((insn) & 0xc0) --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB8093DFC6B; Fri, 21 Aug 2026 19:53:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342020; cv=none; b=frQudqBGbKip6BN96VSNbeFnj7FRbhPyHS5UdzU5y7vm+rTStqY7qBfSZcWlnu915VSwTbm4zx+QFL75+xSpyD+RVkmEjki/uU1ZsjmiUwy6t7a/lZzO6Fhb4quYTt7FpO5hOou7MZOftbKsptS2KDuHO85eJPKg939iwOgdrI0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342020; c=relaxed/simple; bh=WMyBpQzaz7z8JbLlLulfrQmBGsKPHDahtYmddyFk8/k=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ihkypqxoHc2md2mEvcfobc8Kg3EYNYRqBq6tZt/QtPeVOZnRDvw525dYPlOqSh33fW761C20yzRIEY2a3rdIfXTggCAdNcQPAcha5GvjOfCR/EblOKk3kBtuE43/XPg8Mc/4jKV0H3PPk8t8yn4AJrAAPemg+AyW88VbFlCkYzA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=tPG47Xxv; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="tPG47Xxv" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVVOS2363561; Fri, 21 Aug 2026 19:53:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=dFCr5T9phyYLehboO bVirVwXB3O2bo8jq4xPArTF4sg=; b=tPG47Xxv2G0jIEfBuDf3JDM3KivNVLIBX huX0P2Ix2x0u8rl47N8K4Y2RcpgXBi6KleljqJ4GVz6beEMEoQuxK+7PNR5c5dwt DA5O7Kkirtdix6F66ND8/WuaPZA2xkdIw2VyJXuG6CLEVVrZ8yCaGMLEW6CjOA9U jpomlA/0XQTnVYPDdDabv7FY9i8NDY6CxAjHD1iJQ/B370/jHcQxyyUSa4TWQfQO 31UqHofuAbVARIjJlkxhauq43E9xBkMdM/iSY7ikzi3lCf9OIHFkawuShtimCdES Wt8D0RDOpfEvoqi2fmnWMNoKV3EiAC2mtk/yglSWHuwqnFYYLC4Dw== Received: from ppma22.wdc07v.mail.ibm.com (5c.69.3da9.ip4.static.sl-reverse.com [169.61.105.92]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0uxm9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:15 +0000 (GMT) Received: from pps.filterd (ppma22.wdc07v.mail.ibm.com [127.0.0.1]) by ppma22.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfKY4023504; Fri, 21 Aug 2026 19:53:14 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g32twprb1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:13 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrAUP10420730 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:10 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0125B20040; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id AFECB2004B; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 17/24] unwind_user/eh_frame: Add support for DWARF expressions Date: Fri, 21 Aug 2026 21:52:52 +0200 Message-ID: <20260821195259.2688377-18-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=MthiLWae c=1 sm=1 tr=0 ts=6a88acab cx=c_pps a=5BHTudwdYE3Te8bg5FgnPg==:117 a=5BHTudwdYE3Te8bg5FgnPg==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=KkslVM8iKOnbzSZrsQ8A:9 X-Proofpoint-ORIG-GUID: F2cjGmsoF7SvFBo8kVlmsC1HIOVJwAev X-Proofpoint-GUID: fAPKUeWmHTvd3YCRHPSSzwsgZPa1dlqI X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXx3eKJIgdtg9W nwtLi0HNVNV33Tn1knPX1VtuU8kCNbfy6fZZs8XqoxWShIbRQAmCDBE96CT3A04OS11l9iYA7Py cyVFdTDshHFZrkiRq7Wg6wfwrHf0ujI= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX9EAjLZQE0Ac+ 84OyBff4e8QawnTvJghqcf5h2DcsxunjbiY/iZAjGNOGpSgRNDj81IjxKDf8z05Ksj0gx/Mfqfl oOFf23+XhTo9ZHQ0ueJXArT4I1DID0bRWT7Ih6NyJoD5AdwF9z4rCoR1IOmsg14+y7TKd03dMfj iRlGgORsaJZNDgf/WhG6hVoKky9O204MaVyxku+XLtA7V4Mo0el54FMZ+AsB/4w8Wol3NYbeF// KP7IYPpb64uuMj0MOsYFVQoJsZa8dQnqyQ+omsNPv2K7Q4U96cvUkbwRWrUmG1BXaBSXech7Rb6 rMpm4VGTFojHH8t6lZcsTGmzfMxogYI0D9WMLGQib3r2dFaoRXBLNU0TcsoKGDNBKNlOQMTU6ho W5bLvh1DZaPV4WKic3v0KRF8pQOcDoRWF/Bc9LGWs7qNzicOqVCYpP2sZhbJgfX3Er1SW0L7lNX EHaFFC27KaQP/8eckHg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 impostorscore=0 bulkscore=0 phishscore=0 clxscore=1015 spamscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Enable architectures to handle DWARF expressions in DWARF CFI instructions DW_CFA_def_cfa_expression, DW_CFA_expression, and DW_CFA_val_expression. Limit the maximum expression length to a reasonable size, while enabling architectures to override the limit. Architectures are supposed to only handle specific known expressions or expression patterns, not to implement a stack-based expression evaluation machinery. Signed-off-by: Jens Remus --- Notes (jremus): Changes in RFC v2: - Fix expression length overflow checks. (Sashiko AI) include/asm-generic/unwind_user_eh_frame.h | 41 ++++++++++++ include/linux/unwind_user_eh_frame_types.h | 37 +++++++++++ kernel/unwind/eh_frame.c | 72 +++++++++++----------- 3 files changed, 114 insertions(+), 36 deletions(-) create mode 100644 include/linux/unwind_user_eh_frame_types.h diff --git a/include/asm-generic/unwind_user_eh_frame.h b/include/asm-gener= ic/unwind_user_eh_frame.h index da238557605b..a3cd3b3b55c7 100644 --- a/include/asm-generic/unwind_user_eh_frame.h +++ b/include/asm-generic/unwind_user_eh_frame.h @@ -2,6 +2,8 @@ #ifndef _ASM_GENERIC_UNWIND_USER_EH_FRAME_H #define _ASM_GENERIC_UNWIND_USER_EH_FRAME_H =20 +#include + #ifndef EH_FRAME_MAX_CIE_LENGTH #define EH_FRAME_MAX_CIE_LENGTH 128 #endif @@ -14,6 +16,10 @@ #define EH_FRAME_MAX_AUGSTR_LENGTH 16 #endif =20 +#ifndef EH_FRAME_MAX_EXPRESSION_LENGTH +#define EH_FRAME_MAX_EXPRESSION_LENGTH 32 +#endif + #ifndef EH_FRAME_MAX_STATE_STACK #define EH_FRAME_MAX_STATE_STACK 1 #endif @@ -47,5 +53,40 @@ static inline bool eh_frame_reject_sp_rule(void) #define eh_frame_reject_sp_rule eh_frame_reject_sp_rule #endif =20 +#ifndef eh_frame_do_def_cfa_expression +static inline int eh_frame_do_def_cfa_expression(const char *expr, + int size, + unsigned long ip, + struct eh_frame_reg_state *reg_state) +{ + return -EOPNOTSUPP; +} +#define eh_frame_do_def_cfa_expression eh_frame_do_def_cfa_expression +#endif + +#ifndef eh_frame_do_expression +static inline int eh_frame_do_expression(unsigned int reg, + const char *expr, + int size, + unsigned long ip, + struct eh_frame_reg_state *reg_state) +{ + return -EOPNOTSUPP; +} +#define eh_frame_do_expression eh_frame_do_expression +#endif + +#ifndef eh_frame_do_val_expression +static inline int eh_frame_do_val_expression(unsigned int reg, + const char *expr, + int size, + unsigned long ip, + struct eh_frame_reg_state *reg_state) +{ + return -EOPNOTSUPP; +} +#define eh_frame_do_val_expression eh_frame_do_val_expression +#endif + #endif /* _ASM_GENERIC_UNWIND_USER_EH_FRAME_H */ =20 diff --git a/include/linux/unwind_user_eh_frame_types.h b/include/linux/unw= ind_user_eh_frame_types.h new file mode 100644 index 000000000000..e9f9d1abb76f --- /dev/null +++ b/include/linux/unwind_user_eh_frame_types.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_UNWIND_USER_EH_FRAME_TYPES_H +#define _LINUX_UNWIND_USER_EH_FRAME_TYPES_H + +enum eh_frame_cfa_rule { + CFA_UNDEFINED, /* unrecoverable */ + CFA_REG_OFFSET, /* CFA =3D reg + offset */ +}; + +enum eh_frame_reg_rule { + REG_UNDEFINED_IMPLICIT, /* reg =3D reg */ + REG_UNDEFINED_EXPLICIT, /* unrecoverable; RA: outermost frame */ + REG_SAME_VALUE, /* reg =3D reg; TODO: reset to CIE initial CFI */ + REG_OFFSET, /* reg =3D *(CFA + offset) */ + REG_VAL_OFFSET, /* reg =3D CFA + offset */ + REG_REGISTER, /* reg =3D other_reg */ +}; + +enum eh_frame_reg_index { + FP_IDX, /* frame pointer (FP) */ + RA_IDX, /* return address (RA) */ + NR_REGS +}; + +struct eh_frame_reg_state { + /* CFA recovery rule */ + enum eh_frame_cfa_rule cfa_rule; + unsigned long cfa_regnum; + long cfa_offset; + + /* FP and RA recovery rules (SP uses implicit recovery) */ + enum eh_frame_reg_rule reg_rule[NR_REGS]; + unsigned long reg_regnum[NR_REGS]; + long reg_offset[NR_REGS]; +}; + +#endif /* _LINUX_UNWIND_USER_EH_FRAME_TYPES_H */ diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index d185187b0c34..a98804dbe588 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -12,45 +12,14 @@ #include #include #include +#include #include +#include #include =20 #include "eh_frame.h" #include "eh_frame_debug.h" =20 -/* Register state for CFI interpreter */ -enum eh_frame_cfa_rule { - CFA_UNDEFINED, /* unrecoverable */ - CFA_REG_OFFSET, /* CFA =3D reg + offset */ -}; - -enum eh_frame_reg_rule { - REG_UNDEFINED_IMPLICIT, /* reg =3D reg */ - REG_UNDEFINED_EXPLICIT, /* unrecoverable; RA: outermost frame */ - REG_SAME_VALUE, /* reg =3D reg; TODO: reset to CIE initial CFI */ - REG_OFFSET, /* reg =3D *(CFA + offset) */ - REG_VAL_OFFSET, /* reg =3D CFA + offset */ - REG_REGISTER, /* reg =3D other_reg */ -}; - -enum eh_frame_reg_index { - FP_IDX, /* frame pointer (FP) */ - RA_IDX, /* return address (RA) */ - NR_REGS -}; - -struct eh_frame_reg_state { - /* CFA recovery rule */ - enum eh_frame_cfa_rule cfa_rule; - unsigned long cfa_regnum; - long cfa_offset; - - /* FP and RA recovery rules (SP uses implicit recovery) */ - enum eh_frame_reg_rule reg_rule[NR_REGS]; - unsigned long reg_regnum[NR_REGS]; - long reg_offset[NR_REGS]; -}; - struct eh_frame_cfi_context { struct eh_frame_reg_state state; struct eh_frame_reg_state stack[EH_FRAME_MAX_STATE_STACK]; @@ -803,6 +772,27 @@ static __always_inline int __do_cfi_insn(struct eh_fra= me_section *sec, break; } =20 + case DW_CFA_def_cfa_expression: { + unsigned long expr_len; + char expr[EH_FRAME_MAX_EXPRESSION_LENGTH]; + + ret =3D read_uleb128(&cur, end, &expr_len); + if (ret) + return ret; + + if (cur + expr_len < cur || cur + expr_len > end) + return -EINVAL; + + if (expr_len > sizeof(expr)) + return -EOPNOTSUPP; + unsafe_copy_from_user(&expr, (void __user *)cur, expr_len, Efault); + ret =3D eh_frame_do_def_cfa_expression(expr, expr_len, target_ip, &ctx-= >state); + if (ret) + return ret; + cur +=3D expr_len; + break; + } + case DW_CFA_undefined: { unsigned long reg; int idx; @@ -970,12 +960,22 @@ static __always_inline int __do_cfi_insn(struct eh_fr= ame_section *sec, if (ret) return ret; =20 - if (cur + expr_len > end) + if (cur + expr_len < cur || cur + expr_len > end) return -EINVAL; =20 - if (reg =3D=3D EH_FRAME_REG_SP || reg =3D=3D EH_FRAME_REG_FP || reg =3D= =3D EH_FRAME_REG_RA) - return -EOPNOTSUPP; + if (reg =3D=3D EH_FRAME_REG_SP || reg =3D=3D EH_FRAME_REG_FP || reg =3D= =3D EH_FRAME_REG_RA) { + char expr[EH_FRAME_MAX_EXPRESSION_LENGTH]; =20 + if (expr_len > sizeof(expr)) + return -EOPNOTSUPP; + unsafe_copy_from_user(&expr, (void __user *)cur, expr_len, Efault); + if (opcode =3D=3D DW_CFA_expression) + ret =3D eh_frame_do_expression(reg, expr, expr_len, target_ip, &ctx->= state); + else + ret =3D eh_frame_do_val_expression(reg, expr, expr_len, target_ip, &c= tx->state); + if (ret) + return ret; + } cur +=3D expr_len; break; } --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61C0E420E9D; Fri, 21 Aug 2026 19:53:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342030; cv=none; b=PR0l3NXXHwfulewVCLv5vCJxmY0rLJjg9Y8ZXSuahfbRzCL1RYeKLr0uEmfUmLTE9jOvuLWLTjeBZalx14KXKn/a/qyWUxD4S6d4AKHdyf5iXsJSXeZ1Y01Ahj5V5RUTN9yjt0Xjdm7Xgy+GGVniA4jVwR5ofSrp4IosxfXrd9M= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342030; c=relaxed/simple; bh=O0SPzgf2EQOjoZmBiRzcLTE+OD7iWiK8l5BG6BpKfwo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GAKGTM5FG8dznr5pNWu0JJ3Vx4RaiisPyewPuI+ft/1wp1BmABL/W8GE0yealzwvBfCeeKDaEzupJ52XImp9zw0rxp+07mqNLGzJrfLuaQVHRCVYWiRawVsxxBC2+GAejuRvwaTs2Ao826t9enzgl7YJCVJEDDpqtrhNyV9Y4+M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=i77TMcAU; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="i77TMcAU" Received: from pps.filterd (m0360072.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVl2R2387663; Fri, 21 Aug 2026 19:53:15 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Uy5/N5srkznANn5S/ Kowiheg8PnzcVvDEkJYvUPZGHQ=; b=i77TMcAU/Pas0MUbV9e0PsBF8MGyKTcoA 3mX7s8j8atxV0xDRtb77jTZ5m3LFU6+ZgZUI9Oz5mqRlOizPTvjgdQAO+/aVs/W8 F1n5h90Rk2ldP5BN4xN2c5KgQOF4mxw5oUiJ9PEmsK1383/I/s0J5aI1rXIHi5i1 +zvsYLY+CnnhJ76PZmsjudnrTJqjZ5vYc1pr94AOnVVvfuaecWqBbRTz13OuPMLU zaPJy+cEgQ0XNIcRF6ODLuLt8iFSClqPjY/rxSLu9s3H4xNfmfHkFNgIcQ/BX6pq lHpMFQb36A9ZmEUy7TJoWogv7OWF/qBex29ouOBE2F0IN1E0kVB3g== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4kns9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:15 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfGoj008687; Fri, 21 Aug 2026 19:53:14 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354yxdws-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:14 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrAum28312130 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:10 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4732320040; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0625A20043; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:09 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song , "Steven Rostedt (Google)" Subject: [RFC PATCH v2 18/24] x86/uaccess: Add unsafe_copy_from_user() implementation Date: Fri, 21 Aug 2026 21:52:53 +0200 Message-ID: <20260821195259.2688377-19-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=CpuPtH4D c=1 sm=1 tr=0 ts=6a88acab cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=meVymXHHAAAA:8 a=pGLkceISAAAA:8 a=gpC398cPzQKiNBT45cIA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-ORIG-GUID: sBCi4w2KoxmTUXnn0_0RtLncFVsZNQzo X-Proofpoint-GUID: sPjoGvRGfAWM15i-VustWF0lJ8p8_rdW X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX0qCDoMY+00of ctdtxIBGk9NFW42OBk7P2uso30HM7Dsjb1O+WUj9ZPszRu54jEdi7jgSbbhLBvIl/pth37dikRP nDHrsFFj87/FaNoqs9Yp/W1/Q0DZj6w= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX3Yd14KcwHlvk qzbGe92HjycmeduiWearIOfZyNKiHAQn+Lfizu/dzNmap8K0O6scMEug4m+5aP7Y0aStuAGnrSj 5s9AsJWOOhherYY/E5ZgfS0RY2ZBFCTPSNaWFT4B78l36ESp+ypVPEjzKNaciLnYVX/23Q5xdvk /nvEdM0lLSBVtBjUsnA4zkn8jhSZ3/muqSum+upgaLX+gZ59/ybSEKnD3saq+4jjKl+CTmxYlwV sHB8SNCPHW3HZsfFVsPE8Rk8Tm7/zVI9NyU2HYE9hzdlCY8ENOP7zjS72UThqfINvNyGUCmyJqy VlcOErGmxy1hXyv7lIIZCtpmqFvjqfQEtEVB6kh7GD6bAP5qrhBEQ0W1wwCG7NlM6Z7aKCkurtD IC1rK6vkUUZ2HwuOKWDfTWPXNdQaR0OrrDdPxiVwzHUKF3uaWI116hnZjGJHTFwnidS2SK3/N4W MEdpWxGGFMJlBJii2mQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 adultscore=0 bulkscore=0 malwarescore=0 phishscore=0 lowpriorityscore=0 spamscore=0 clxscore=1015 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" From: Josh Poimboeuf Add an x86 implementation of unsafe_copy_from_user() similar to the existing unsafe_copy_to_user(). Signed-off-by: Josh Poimboeuf Signed-off-by: Steven Rostedt (Google) Reviewed-by: Indu Bhagat Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v16 00/20] unwind_deferred: Implement sframe handling" series: https://lore.kernel.org/all/20260521142546.3908498-5-jremus@linux.ibm.c= om/ arch/x86/include/asm/uaccess.h | 39 +++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h index 3a0dd3c2b233..235886106f31 100644 --- a/arch/x86/include/asm/uaccess.h +++ b/arch/x86/include/asm/uaccess.h @@ -598,7 +598,7 @@ _label: \ * We want the unsafe accessors to always be inlined and use * the error labels - thus the macro games. */ -#define unsafe_copy_loop(dst, src, len, type, label) \ +#define unsafe_copy_to_user_loop(dst, src, len, type, label) \ while (len >=3D sizeof(type)) { \ unsafe_put_user(*(type *)(src),(type __user *)(dst),label); \ dst +=3D sizeof(type); \ @@ -606,15 +606,34 @@ _label: \ len -=3D sizeof(type); \ } =20 -#define unsafe_copy_to_user(_dst,_src,_len,label) \ -do { \ - char __user *__ucu_dst =3D (_dst); \ - const char *__ucu_src =3D (_src); \ - size_t __ucu_len =3D (_len); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u64, label); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u32, label); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u16, label); \ - unsafe_copy_loop(__ucu_dst, __ucu_src, __ucu_len, u8, label); \ +#define unsafe_copy_to_user(_dst, _src, _len, label) \ +do { \ + void __user *__dst =3D (_dst); \ + const void *__src =3D (_src); \ + size_t __len =3D (_len); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u64, label); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u32, label); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u16, label); \ + unsafe_copy_to_user_loop(__dst, __src, __len, u8, label); \ +} while (0) + +#define unsafe_copy_from_user_loop(dst, src, len, type, label) \ + while (len >=3D sizeof(type)) { \ + unsafe_get_user(*(type *)(dst), (type __user *)(src), label); \ + dst +=3D sizeof(type); \ + src +=3D sizeof(type); \ + len -=3D sizeof(type); \ + } + +#define unsafe_copy_from_user(_dst, _src, _len, label) \ +do { \ + void *__dst =3D (_dst); \ + const void __user *__src =3D (_src); \ + size_t __len =3D (_len); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u64, label); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u32, label); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u16, label); \ + unsafe_copy_from_user_loop(__dst, __src, __len, u8, label); \ } while (0) =20 #ifdef CONFIG_CC_HAS_ASM_GOTO_OUTPUT --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DB88D3F9278; Fri, 21 Aug 2026 19:54:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342054; cv=none; b=b4SUXfiL24ZDN7S/2phmMxgQdtUsZo66WDiCWk+bglDponZ3hL2RhmEf5q27T2LTJzA74eikUT46nPwbK64PLCpGhmXwLPnxVbqWv2xMvrbDcCX8M2HJXrpQCyuvSgdTVBLu5Ofrhz3UgyaH50Ue8w0pA9izqMka6gl//PHoKs8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342054; c=relaxed/simple; bh=TgiT8Xnhc5VLifuhTHbl67ng/yIBp4wlIbp5EtKoKcg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=K1NR8iNILoybXsuN4M41Ke5+kHkqTAFaCqsm11KIho8FhcnxV/NVQckpOUWeGMHCZc8SoVC+u+qB2RuWmCJwJBJPr04qirW2LvtCQ/HVfWf/9Ors7za2GVdXD1gQFF9Dvs02zogSMlYTl6uAqOZ+6ZKB4K5gweJW+8CSUZE9MSc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=f1qgWRvD; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="f1qgWRvD" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIW5bb2254763; Fri, 21 Aug 2026 19:53:16 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Y+mdTmXPgPz0paNvu 3GnRv+WInnbZ0GCjERerrKsAso=; b=f1qgWRvDG1qtN2I/6fsZuazodHrXbDBwJ 1Jyk3nc+YOMEs3AzpgQtWuH2a7asHZNUnLP7El7bK8yXUIcc+OmucAHRZ5Pd1aD+ ntWL1d5gfrq5hyCUG9YCOX9K3edAqnRM7775KCBIBIK8OpBJY9sx36BxZACGzZAQ RdtmM8SEoPPfYHFQgz9ff31UxP1ilTJ07zDSzKLAZRImUkTsPQA+TpXH9Gt+u5EC cHecAS44Q7ZdDiZvU/DGFZp1ZzltMnAgLcVR93MhXZ5n3sGucRVq72iPWqsyb6d2 ENEmqd0wMiFt+Sbv3v4SKnRuzshAW4Kap9j9QmkjZ8oRAbTR67cRA== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4krkv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:15 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfIZP016594; Fri, 21 Aug 2026 19:53:14 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xhpnkv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:14 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrAe010420482 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:10 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 8C5F420040; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4EA252004B; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 19/24] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86 Date: Fri, 21 Aug 2026 21:52:54 +0200 Message-ID: <20260821195259.2688377-20-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX7P16kilAz/Cg Lq/sSi7M8fKGWynnhYOI+Kza/6SGI/O/WNq/fSqjEbktt6d3IWsHxHCJo+GdfSCxnJ4nrgueh0n Vh5XwJKguDm8wOsvkWo9ptgtUCuIT9Y= X-Proofpoint-GUID: hX6K2Yi5jUq9h32bOLekL6f4ADhy0INj X-Proofpoint-ORIG-GUID: MB8ma26FyBMsQ5YMuoUB-JXbpT_uSI9A X-Authority-Analysis: v=2.4 cv=RPmD2Yi+ c=1 sm=1 tr=0 ts=6a88acab cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=TKDeGWYlhpvMKGhGT-EA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX42idbx157ijU ecZfUaHcpMcqMrpf64CuqiHi7T9YZVpLzRwVU2D7WsjVfF24QOhfk2qOzm+usBRMBt7qdX7aYqT ue2++I+Gzfss0TNxoRooL5m6BuZcupxQ+wIFOrZoHl7NqjEiiM+MSv8rptMoOIFYMXJGxdkA1J5 JIpvI3wHakZWEVScZ2kdaqStEF8WyY5PZaYrgl4VnRBLBvEC9xZa1g7W7JR647eBdN77ir/UCIH Ks/jLqCBvFZSIBBj3ayZxPsp6ZfnKpmWthERW/9P8R9IEDBwBlw6/OyPEK8D/FDVUtNx4fdvx+U 7RXNGEAYseI0kyMNjAHPtOlfntHH3/U21kA0JxrYti6b91dR4Zkg8jIuqGhFjrU33XmmtgeRHb+ Hp60ofot2kfPMdnmOd4JnnTqhflQ56CEqepdG0QXSfbuotw+sFeHFyNHXR2yD6cSYCPqq5rzpQH Y8zOQ/NDI0Y2Z3L4hig== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 adultscore=0 spamscore=0 priorityscore=1501 bulkscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" The x86-64 .eh_frame implementation works well with GCC and Clang generated code. Enable it. Signed-off-by: Jens Remus --- arch/x86/Kconfig | 1 + arch/x86/include/asm/unwind_user.h | 40 +++++++++++++++++++++ arch/x86/include/asm/unwind_user_eh_frame.h | 22 ++++++++++++ 3 files changed, 63 insertions(+) create mode 100644 arch/x86/include/asm/unwind_user_eh_frame.h diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index bdad90f210e4..fe7919915084 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -300,6 +300,7 @@ config X86 select HAVE_SYSCALL_TRACEPOINTS select HAVE_UACCESS_VALIDATION if HAVE_OBJTOOL select HAVE_UNSTABLE_SCHED_CLOCK + select HAVE_UNWIND_USER_EH_FRAME if X86_64 select HAVE_UNWIND_USER_FP if X86_64 select HAVE_USER_RETURN_NOTIFIER select HAVE_GENERIC_VDSO diff --git a/arch/x86/include/asm/unwind_user.h b/arch/x86/include/asm/unwi= nd_user.h index c96645c824d1..df1966bcb0f6 100644 --- a/arch/x86/include/asm/unwind_user.h +++ b/arch/x86/include/asm/unwind_user.h @@ -4,6 +4,7 @@ =20 #ifdef CONFIG_UNWIND_USER =20 +#include #include #include =20 @@ -15,6 +16,45 @@ static inline int unwind_user_word_size(struct pt_regs *= regs) return user_64bit_mode(regs) ? 8 : 4; } =20 +#ifdef CONFIG_X86_64 + +static inline int unwind_user_get_reg(unsigned long *val, unsigned int reg= num) +{ + struct pt_regs *regs =3D task_pt_regs(current); + + /* TODO: eh_frame is currently limited to x86-64 */ + if (!user_64bit_mode(regs)) + return -EINVAL; + + switch (regnum) { + /* DWARF register numbers 0..15 */ + case 0: *val =3D regs->ax; break; + case 1: *val =3D regs->dx; break; + case 2: *val =3D regs->cx; break; + case 3: *val =3D regs->bx; break; + case 4: *val =3D regs->si; break; + case 5: *val =3D regs->di; break; + case 6: *val =3D regs->bp; break; + case 7: *val =3D regs->sp; break; + case 8: *val =3D regs->r8; break; + case 9: *val =3D regs->r9; break; + case 10: *val =3D regs->r10; break; + case 11: *val =3D regs->r11; break; + case 12: *val =3D regs->r12; break; + case 13: *val =3D regs->r13; break; + case 14: *val =3D regs->r14; break; + case 15: *val =3D regs->r15; break; + default: + pr_debug("%s (%d): %s(%u): unsupported register number\n", + current->comm, current->pid, __func__, regnum); + return -EINVAL; + } + return 0; +} +#define unwind_user_get_reg unwind_user_get_reg + +#endif /* CONFIG_X86_64 */ + #endif /* CONFIG_UNWIND_USER */ =20 #ifdef CONFIG_HAVE_UNWIND_USER_FP diff --git a/arch/x86/include/asm/unwind_user_eh_frame.h b/arch/x86/include= /asm/unwind_user_eh_frame.h new file mode 100644 index 000000000000..fdccbda2fe4b --- /dev/null +++ b/arch/x86/include/asm/unwind_user_eh_frame.h @@ -0,0 +1,22 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_X86_UNWIND_USER_EH_FRAME_H +#define _ASM_X86_UNWIND_USER_EH_FRAME_H + +#ifdef CONFIG_X86_64 + +#define EH_FRAME_REG_SP 7 /* designated stack pointer register */ +#define EH_FRAME_REG_FP 6 /* designated frame pointer register */ +#define EH_FRAME_REG_RA 16 /* (pseudo) return address register */ + +/* Instructions must be 1-byte aligned */ +#define EH_FRAME_MAX_CODE_ALIGN 1 + +/* Stack grows towards lower addresses and SP must be 8-byte aligned */ +#define EH_FRAME_MIN_DATA_ALIGN -8 +#define EH_FRAME_MAX_DATA_ALIGN -1 + +#endif + +#include + +#endif /* _ASM_X86_UNWIND_USER_EH_FRAME_H */ --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 635E6389460; Fri, 21 Aug 2026 19:53:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342031; cv=none; b=iGCUvs4JRiKfEUuaVkAS2oWHqwe+VlfqwsTDvBgs3OePNlNUGurI0O6rTGDokBm8xZ6X14f7zLqW2rCTNaPfu7d4S87XU3h06dtjqWCzA1j7WWsP7o2eMz7vX0ljnK9ih3MMBIJ8CCUShJ7MTtBzAsLenjkqyC44Xfx27Vwn+Ic= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342031; c=relaxed/simple; bh=P1YSpG+zs128CymzdiY+3Nnu13S/UugxwgcnR7b8GMs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lATJA8LYh4acshqbzAYMzhA8I1IidSL+128T4MeaKxFXiT6tgoLQCH30zhpXGOAmx24cuDKixLGswF/bXcLyqsjlri1mbru7JiQU7zj9oYGjUAty/MGsmduYXu7BD0Z9W2h+feg+KsA5VN8Y376G2mhgDryJH5qbvOGxl0OWSis= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=LA0Fxjgu; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="LA0Fxjgu" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVvZr2253873; Fri, 21 Aug 2026 19:53:23 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Py6xfwdNsaHG7pzwS kL8ia98s+iXudOl/0MXjctgP6Y=; b=LA0Fxjguezwj2uyYtVMXWFKD+lHn75WtR /oVq0GCT6DUHdXq8XSQbzRkKIpDQNLhPMeRQT/8SNDonFv8bJ/BnZVDkkfDg8QXX JdtjSGlH3bjtz4yReTUJC9xrPNg+dn4RgBqXm5OsjU3+iOy76xEEJvnJpm+jnUKv B56KSf/3lX52or1F1Bzgi/0+43nrvESXuMwOYSa7s33tq+1FU6qrC0Jc/1dmUG5N IUphwQ458Ut2N7BqXlfLhmsVi11rm+oYmMLacNuCRQvf6QSF9kNLtGh+7p+1LK0B 0w+euJ9qe7YT4TzRnVtM6xKYU6BCZ2S5OeTLoZ0G+jLijETGQ/vGA== Received: from ppma11.dal12v.mail.ibm.com (db.9e.1632.ip4.static.sl-reverse.com [50.22.158.219]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4krms-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:22 +0000 (GMT) Received: from pps.filterd (ppma11.dal12v.mail.ibm.com [127.0.0.1]) by ppma11.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfKUF008731; Fri, 21 Aug 2026 19:53:21 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354yxdxc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:21 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrAI710420484 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:11 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id CEEDC20040; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9103920043; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 20/24] unwind_user/eh_frame/x86: Handle PLT expressions Date: Fri, 21 Aug 2026 21:52:55 +0200 Message-ID: <20260821195259.2688377-21-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX8saOyv/gDEtr I7GxitEGxzBXqt1pRVMFNJZ4RmtOzWAeMZ+j6PmPFareRLK4ZFIr6J5+Dj9Cj+qfE2rV/DX+IJV tEbrIuaxINysFcTKQJnewbmwsbZi2PI= X-Proofpoint-GUID: 8Pcb3teDPGwBNila6rlEwAYe63BXY_49 X-Proofpoint-ORIG-GUID: YhFiri8BotwIrQ0cszGGj9zx1iESGqcp X-Authority-Analysis: v=2.4 cv=RPmD2Yi+ c=1 sm=1 tr=0 ts=6a88acb3 cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=lN3RThuQUzBg4E8S6xQA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXxTMwDFTKXbZm pGZh2l9Z7VR4zY+X/cgKMfpT4fNO78LDpTFCBxiaOAQdhFR5sSKTx6QvwcWMq0BpcaDEbX3m/DC w+mBr6FWnoY6yji98ZU/dI0S6itM5NbJzPP0ZMzHJSuy1LCsrSXhxwULnDfvt+rSkqKjXLXCNbt TsJYkfgg25wAw2YcBR+NYJ8EqVLYErLvQn6zQbeWIe5bGFLVaG5oWHHAQyEr24hID6eRCVayuYc lLAjkvxRhEforXMgyIjojcUyzh8r31cDQaI59nDNno4o6R+QoDpyx3N5VGyszBso71RcpGHY5hu S/t5o2QYHzYZRIgIcG1Bjo7EwH7TvErx5d7JfwWX6AsF85QW0MmlYPCVsA6ItTPmwSF79C5aG94 oFuek4rl0KgmKGDHUZvAYwW0RbubhBQtxL4qfp4X3H/8TBm4R6kqT+fA4pjnpWOa+yMWt9ikBUo LDIYUoMRiKLyCN4ntdg== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 adultscore=0 spamscore=0 priorityscore=1501 bulkscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" Add x86-specific support for handling the CFA expression found in GNU linker generated .eh_frame for PLT. This enables unwinding through GNU linker generated PLT entries on i386 and x86-64, unless linker option --no-ld-generated-unwind-info is used. Signed-off-by: Jens Remus --- arch/x86/include/asm/unwind_user_eh_frame.h | 68 ++++++++++++++++++++- kernel/unwind/eh_frame.c | 3 +- kernel/unwind/eh_frame.h | 14 +++++ 3 files changed, 83 insertions(+), 2 deletions(-) diff --git a/arch/x86/include/asm/unwind_user_eh_frame.h b/arch/x86/include= /asm/unwind_user_eh_frame.h index fdccbda2fe4b..8268eb1a0ff5 100644 --- a/arch/x86/include/asm/unwind_user_eh_frame.h +++ b/arch/x86/include/asm/unwind_user_eh_frame.h @@ -2,6 +2,8 @@ #ifndef _ASM_X86_UNWIND_USER_EH_FRAME_H #define _ASM_X86_UNWIND_USER_EH_FRAME_H =20 +#include + #ifdef CONFIG_X86_64 =20 #define EH_FRAME_REG_SP 7 /* designated stack pointer register */ @@ -15,7 +17,71 @@ #define EH_FRAME_MIN_DATA_ALIGN -8 #define EH_FRAME_MAX_DATA_ALIGN -1 =20 -#endif +#endif /* CONFIG_X86_64 */ + +static inline int memcmp_masked(const void *s1, const void *s2, + const void *mask, size_t n) +{ + const unsigned char *p1 =3D s1, *p2 =3D s2, *m =3D mask; + int res =3D 0; + + while (n--) + if ((res =3D (*p1++ ^ *p2++) & *m++)) + break; + + return res; +} + +static inline int eh_frame_do_def_cfa_expression(const char *expr, + int size, + unsigned long ip, + struct eh_frame_reg_state *reg_state) +{ + /* + * PLT CFA expression: + * + * DW_OP_breg + // 4 (ESP) + 4 or 7 (RSP) + 8 + * DW_OP_breg + 0 // 8 (EIP) or 16 (RIP) + * DW_OP_lit15 + * DW_OP_and + * DW_OP_lit + * DW_OP_ge + * DW_OP_lit // 2 or 3 + * DW_OP_shl + * DW_OP_plus + * + * CFA =3D (SP + offset) + (((IP & 0xf) >=3D N) << shift) + */ + static const char plt_expr[] =3D {0x00,0x00,0x00,0x00,0x3f,0x1a,0x30,0x2a= ,0x30,0x24,0x22}; + static const char plt_mask[] =3D {0x00,0xf0,0x00,0xff,0xff,0xff,0xf0,0xff= ,0xf0,0xff,0xff}; + + if (size =3D=3D sizeof(plt_expr) && + !memcmp_masked(expr, plt_expr, plt_mask, sizeof(plt_expr))) { + unsigned char sp_op =3D expr[0]; + unsigned char sp_offset =3D expr[1] & 0x0f; + unsigned char ip_op =3D expr[2]; + unsigned char n =3D DW_OP_lit_value(expr[6]); + unsigned char shift =3D DW_OP_lit_value(expr[8]); + unsigned char sp_reg, ip_reg; + + if (!DW_OP_is_breg(sp_op) || !DW_OP_is_breg(ip_op)) + return -EOPNOTSUPP; + + sp_reg =3D DW_OP_breg_register(sp_op); + ip_reg =3D DW_OP_breg_register(ip_op); + if (sp_reg !=3D EH_FRAME_REG_SP || ip_reg !=3D EH_FRAME_REG_RA) + return -EOPNOTSUPP; + + /* CFA =3D (SP + SP_offset) + (((IP & 0xf) >=3D N) << shift) */ + reg_state->cfa_rule =3D CFA_REG_OFFSET; + reg_state->cfa_regnum =3D EH_FRAME_REG_SP; + reg_state->cfa_offset =3D sp_offset + (((ip & 15) >=3D n) << shift); + return 0; + } + + return -EOPNOTSUPP; +} +#define eh_frame_do_def_cfa_expression eh_frame_do_def_cfa_expression =20 #include =20 diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index a98804dbe588..0a81ba1a0377 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -15,11 +15,12 @@ #include #include #include -#include =20 #include "eh_frame.h" #include "eh_frame_debug.h" =20 +#include + struct eh_frame_cfi_context { struct eh_frame_reg_state state; struct eh_frame_reg_state stack[EH_FRAME_MAX_STATE_STACK]; diff --git a/kernel/unwind/eh_frame.h b/kernel/unwind/eh_frame.h index a43560486283..2f87d1b32bbc 100644 --- a/kernel/unwind/eh_frame.h +++ b/kernel/unwind/eh_frame.h @@ -60,6 +60,20 @@ #define DW_EH_PE_format(encoding) ((encoding) & 0x0f) #define DW_EH_PE_application(encoding) ((encoding) & 0x70) =20 +/* DWARF expression operations */ +#define DW_OP_lit0 0x30 +/* ... */ +#define DW_OP_lit31 0x4f +#define DW_OP_breg0 0x70 +/* ... */ +#define DW_OP_breg31 0x8f + +/* Helpers for DWARF expression operations */ +#define DW_OP_is_lit(op) ((op) >=3D DW_OP_lit0 && (op) <=3D DW_OP_lit31) +#define DW_OP_is_breg(op) ((op) >=3D DW_OP_breg0 && (op) <=3D DW_OP_breg3= 1) +#define DW_OP_lit_value(op) ((op) - DW_OP_lit0) +#define DW_OP_breg_register(op) ((op) - DW_OP_breg0) + /* CIE/FDE constants */ #define EH_FRAME_CIE_ID 0 #define EH_FRAME_DWARF64_LENGTH 0xffffffff --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5164E40F75B; Fri, 21 Aug 2026 19:53:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342026; cv=none; b=iyHMjp9WX02UrlcC9zxkUCpieuzkVrgHT5jGlFA3PaC3GD/R8SKLvzNvNSQYhwT+Hf+Cy51/ZGfQjS0kVz2lKJgWEWMoWo1dTZze/VK1uEtGTAqbSaOECfioR6vRvGvQDmqJ8jCQznFXJcF1vcWwQ9wCQMhxNNskx8HxBSisGJE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342026; c=relaxed/simple; bh=g7TvgZy6XOZBKCswfNzB3dLoqZ/eGefaLm9pTKHCZ1U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=UTODGJKureYuoePEKdSphIbQOH7I8IFftHzBGnUvy1QIvwz3CI51sNSRSHzmyXOv/4fJqYzN82yoGsxJkmLYaqkbq8wL+9ZNDZGw4T4qKdiXg6kOZo8CmW+l3sJhAgJ5lGRvGictSVm7w1ZFmSCA5OTfMTg0bBBLXi7j2/IS/Fw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=J4rFDmMe; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="J4rFDmMe" Received: from pps.filterd (m0356517.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVhLp2363840; Fri, 21 Aug 2026 19:53:17 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Uc2H1ny73nZVVmNdP 1gES8aoeXmzxmUN+CBNL7lP44c=; b=J4rFDmMeku/auoQ6pq0cG9AvN1G0eRKdq p7Fv6MhRyVUvVnDB4QpHgUogQK+yN1IZTp/uELnspoa+pcTYbzAIEzID+/8sHssr 88p23+2KckAaLJQ+8Qlcz/IO6VjlyuIKcDCn2rm821oHwbBTMtNlvmfBCh0P4pnA dRHLCMCQWdiOxm8bR4f2nxuzUmzBg1AnePjHEIUeNWAqrewerYaRERFA51Z1rEcN gMVALkh62CunP2+Kr6DodosNlb9RlDQYxh6WRwpuJMTiaKRuJjelXo8lv8BU60v6 mQM+zELXfmixt9Wo3GM6kVIX/kn7XujzkBQA0WN3ldgeGaaCWHdMA== Received: from ppma12.dal12v.mail.ibm.com (dc.9e.1632.ip4.static.sl-reverse.com [50.22.158.220]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0uxmc-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:16 +0000 (GMT) Received: from pps.filterd (ppma12.dal12v.mail.ibm.com [127.0.0.1]) by ppma12.dal12v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfMOt020629; Fri, 21 Aug 2026 19:53:15 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eqpupt-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:15 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrBMl50331920 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:11 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 26F6B20040; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id D3ABD2004B; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:10 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 21/24] unwind_user/eh_frame/x86: Handle DRAP expressions Date: Fri, 21 Aug 2026 21:52:56 +0200 Message-ID: <20260821195259.2688377-22-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Authority-Analysis: v=2.4 cv=MthiLWae c=1 sm=1 tr=0 ts=6a88acac cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=CAsaE8RiOkJQvnkcRxMA:9 X-Proofpoint-ORIG-GUID: kNDSzTw_ntX5oD9COhkRCOds83m98PVh X-Proofpoint-GUID: -Q-PoLBGfZFKRTshpn4oP7FrtUEgbK__ X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX43eWqKv8u+oe EuhMGs1F1ztP1niXFFaAeHNELsDfQoBqpdLHqH8Prkiz98QNEX1fN5Uq2hN10kKEhS1d/SuzAPv 2hSCjfEbVhRtr/CRVQuNn9FZXc9/vHg= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX2a/6WPtw/cvL Vk89LGqAnfZ1NUTtR4fudZhF8RJgxirftP3Pao//Dpwdb+AHF0VRXAi786gV6CIgrnJUX3dou0n u4K+aTu9AyiXHV42FQ6U7mlKWDG6YfeeBiSi6PEfq9xLAr/dzc/+6wkoaiuQtGs4YG4xUGaX/xx yUsKgzS83+tD/drOVe/qNlasMEyuRv9pFBHzqP3mHWRsUSgH+jjJ9BPnIfJKXxUwkTDEo9xQv93 EV+AG/7zbv9W5mHSN/eXknJSXcJmUhA6k3B44+WdbIVM3ewA+jj9reKdHh//81lzraIQjkian6A D/+ZCFcgdXeNjwslIqKSrIksiKwFMo/JBP3O3B+gd8T2z5Z0tibxTyg6O2dyTwdM2tBvinjcwZd 12H6l0O0wmy2EoxM1naeV2wAKK2s6vuXJDaUxPJ00Ga0V/Rklr6/kfRggaYLnaxrelRQbVDByNE bT3NgzKtijlxhuBNkNw== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 impostorscore=0 bulkscore=0 phishscore=0 clxscore=1015 spamscore=0 adultscore=0 lowpriorityscore=0 priorityscore=1501 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" GCC uses DRAP (Dynamic Realign Argument Pointer) when the stack needs to be dynamically realigned (e.g. for aligned local variables). This uses DWARF expressions to describe how to unwind through such frames. Add x86-specific handling for the CFA and FP expressions patterns: 1. CFA expression (DW_OP_breg + offset, DW_OP_deref): - Semantics: CFA =3D *(FP + offset) - Restores the CFA from the saved SP at FP-4 (i386) or FP-8 (x86-64). 2. FP expression (DW_OP_breg +0): - Semantics: FP =3D *(FP + 0) - Restores FP from DRAP location (FP+0). The implementation uses mask-based pattern matching similar to the existing x86 PLT expression support. Signed-off-by: Jens Remus --- arch/x86/include/asm/unwind_user_eh_frame.h | 65 +++++++++++++++++++++ include/linux/unwind_user_eh_frame_types.h | 4 ++ kernel/unwind/eh_frame.c | 57 ++++++++++++++---- 3 files changed, 115 insertions(+), 11 deletions(-) diff --git a/arch/x86/include/asm/unwind_user_eh_frame.h b/arch/x86/include= /asm/unwind_user_eh_frame.h index 8268eb1a0ff5..670740cdbd8c 100644 --- a/arch/x86/include/asm/unwind_user_eh_frame.h +++ b/arch/x86/include/asm/unwind_user_eh_frame.h @@ -79,10 +79,75 @@ static inline int eh_frame_do_def_cfa_expression(const = char *expr, return 0; } =20 + /* + * DRAP (Dynamic Realignment Pointer) CFA expression: + * + * DW_OP_breg + // 5 (EBP) - 4 or 6 (RBP) - 8 + * DW_OP_deref + * + * CFA =3D *(FP + FP_offset) + */ + static const char drap_expr[] =3D {0x70, 0x00, 0x06}; + static const char drap_mask[] =3D {0xf0, 0x80, 0xff}; + + if (size =3D=3D sizeof(drap_expr) && + !memcmp_masked(expr, drap_expr, drap_mask, sizeof(drap_expr))) { + unsigned char fp_reg =3D DW_OP_breg_register(expr[0]); + unsigned char fp_offset_byte =3D expr[1]; + long fp_offset; + + if (fp_reg !=3D EH_FRAME_REG_FP) + return -EOPNOTSUPP; + + fp_offset =3D (long)(fp_offset_byte); + if (fp_offset_byte & 0x40) + fp_offset |=3D -(1L << 7); /* Sign extend */ + + /* CFA =3D *(FP + offset) */ + reg_state->cfa_rule =3D CFA_REG_OFFSET_DEREF; + reg_state->cfa_regnum =3D EH_FRAME_REG_FP; + reg_state->cfa_offset =3D fp_offset; + return 0; + } + return -EOPNOTSUPP; } #define eh_frame_do_def_cfa_expression eh_frame_do_def_cfa_expression =20 +static inline int eh_frame_do_expression(unsigned int reg, + const char *expr, + int size, + unsigned long ip, + struct eh_frame_reg_state *reg_state) +{ + /* + * DRAP (Dynamic Realignment Pointer) FP expression: + * + * DW_OP_breg +0 // 5 (EBP) or 6 (RBP) + * + * FP =3D *(FP + 0) + */ + static const char drap_fp_expr[] =3D {0x70, 0x00}; + static const char drap_fp_mask[] =3D {0xf0, 0xff}; + + if (reg =3D=3D EH_FRAME_REG_FP && size =3D=3D sizeof(drap_fp_expr) && + !memcmp_masked(expr, drap_fp_expr, drap_fp_mask, sizeof(drap_fp_expr)= )) { + unsigned char fp_reg =3D DW_OP_breg_register(expr[0]); + + if (fp_reg !=3D EH_FRAME_REG_FP) + return -EOPNOTSUPP; + + /* FP =3D *(FP + 0) */ + reg_state->reg_rule[FP_IDX] =3D REG_REGISTER_OFFSET_DEREF; + reg_state->reg_regnum[FP_IDX] =3D EH_FRAME_REG_FP; + reg_state->reg_offset[FP_IDX] =3D 0; + return 0; + } + + return -EOPNOTSUPP; +} +#define eh_frame_do_expression eh_frame_do_expression + #include =20 #endif /* _ASM_X86_UNWIND_USER_EH_FRAME_H */ diff --git a/include/linux/unwind_user_eh_frame_types.h b/include/linux/unw= ind_user_eh_frame_types.h index e9f9d1abb76f..9547e963bb5f 100644 --- a/include/linux/unwind_user_eh_frame_types.h +++ b/include/linux/unwind_user_eh_frame_types.h @@ -5,6 +5,8 @@ enum eh_frame_cfa_rule { CFA_UNDEFINED, /* unrecoverable */ CFA_REG_OFFSET, /* CFA =3D reg + offset */ + /* CFA expressions rules */ + CFA_REG_OFFSET_DEREF, /* CFA =3D *(reg + offset) */ }; =20 enum eh_frame_reg_rule { @@ -14,6 +16,8 @@ enum eh_frame_reg_rule { REG_OFFSET, /* reg =3D *(CFA + offset) */ REG_VAL_OFFSET, /* reg =3D CFA + offset */ REG_REGISTER, /* reg =3D other_reg */ + /* expressions rules */ + REG_REGISTER_OFFSET_DEREF, /* reg =3D *(other_reg + offset) */ }; =20 enum eh_frame_reg_index { diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 0a81ba1a0377..d1656f5d40f1 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1098,18 +1098,33 @@ static __always_inline int __find_frame_row(struct = eh_frame_section *sec, return ret; =20 /* Convert CFA rule */ - if (ctx.state.cfa_rule !=3D CFA_REG_OFFSET) + switch (ctx.state.cfa_rule) { + case CFA_REG_OFFSET: + if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_SP) + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_SP_OFFSET; + else if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_FP) + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_FP_OFFSET; + else { + if (ctx.state.cfa_regnum > UINT_MAX) + return -EINVAL; + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_REG_OFFSET; + frame->cfa.regnum =3D ctx.state.cfa_regnum; + } + break; + case CFA_REG_OFFSET_DEREF: + if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_SP) + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_SP_OFFSET_DEREF; + else if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_FP) + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_FP_OFFSET_DEREF; + else { + if (ctx.state.cfa_regnum > UINT_MAX) + return -EINVAL; + frame->cfa.rule =3D UNWIND_USER_CFA_RULE_REG_OFFSET_DEREF; + frame->cfa.regnum =3D ctx.state.cfa_regnum; + } + break; + default: return -EINVAL; - - if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_SP) - frame->cfa.rule =3D UNWIND_USER_CFA_RULE_SP_OFFSET; - else if (ctx.state.cfa_regnum =3D=3D EH_FRAME_REG_FP) - frame->cfa.rule =3D UNWIND_USER_CFA_RULE_FP_OFFSET; - else { - if (ctx.state.cfa_regnum > UINT_MAX) - return -EINVAL; - frame->cfa.rule =3D UNWIND_USER_CFA_RULE_REG_OFFSET; - frame->cfa.regnum =3D ctx.state.cfa_regnum; } =20 if (ctx.state.cfa_offset < INT_MIN || @@ -1150,6 +1165,16 @@ static __always_inline int __find_frame_row(struct e= h_frame_section *sec, frame->ra.regnum =3D ctx.state.reg_regnum[RA_IDX]; frame->ra.offset =3D 0; break; + case REG_REGISTER_OFFSET_DEREF: + if (ctx.state.reg_regnum[RA_IDX] > UINT_MAX) + return -EINVAL; + if (ctx.state.reg_offset[RA_IDX] < INT_MIN || + ctx.state.reg_offset[RA_IDX] > INT_MAX) + return -EOPNOTSUPP; + frame->ra.rule =3D UNWIND_USER_RULE_REG_OFFSET_DEREF; + frame->ra.regnum =3D ctx.state.reg_regnum[RA_IDX]; + frame->ra.offset =3D ctx.state.reg_offset[RA_IDX]; + break; default: return -EINVAL; } @@ -1184,6 +1209,16 @@ static __always_inline int __find_frame_row(struct e= h_frame_section *sec, frame->fp.regnum =3D ctx.state.reg_regnum[FP_IDX]; frame->fp.offset =3D 0; break; + case REG_REGISTER_OFFSET_DEREF: + if (ctx.state.reg_regnum[FP_IDX] > UINT_MAX) + return -EINVAL; + if (ctx.state.reg_offset[FP_IDX] < INT_MIN || + ctx.state.reg_offset[FP_IDX] > INT_MAX) + return -EOPNOTSUPP; + frame->fp.rule =3D UNWIND_USER_RULE_REG_OFFSET_DEREF; + frame->fp.regnum =3D ctx.state.reg_regnum[FP_IDX]; + frame->fp.offset =3D ctx.state.reg_offset[FP_IDX]; + break; default: return -EINVAL; } --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2B17440F736; Fri, 21 Aug 2026 19:54:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342083; cv=none; b=hgg5njbIiDuD4VtEgGytlJR4Btvrv//Y4+rzRb52eAOFrZmCPYbq6V/9RNOBO31/O6WDMUOC3V82xDJkQijU/rgkepkSytHegBzS5EFTr1wkSDmrERHCcro4glbhI/TCejC6GULe4yDojx6Azr/R+ljWntVxqcAyJlGd6EMmkt4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342083; c=relaxed/simple; bh=QWiO/oVjltZVMmCOotSP7wKcIueRwp06oxRRGGodGAs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=s/Kk7Qb8HDie0FhMqrLziO1wmfRUP5YjhDVKE0lpPs7U9QSMKbGOPHIHMXLzjGMUxAXzseV4hnFJawAM40dy7kZtCodc8rVlH4kJOI+PNGazqxjNB9n8Yay+MpqeMBLUD4shrXQUZmhn7WcoPRqS+ezzBYNIt7uzIhLXkUgTmzk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=TOhtz60v; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="TOhtz60v" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVYdr491713; Fri, 21 Aug 2026 19:53:19 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=Y+euVRI6M/Fa6YfSr 8B9MiMOGuuw4vVLdiMUtQIZdas=; b=TOhtz60vQ41nFEGwl5CIRg0ZJ+l35cTqm 3xvsdIJCcRMND7kmKAekXMHUrUcgx8hYHkcWv1YVDGIH6QtEJCeOQkbcWG1/4mi+ iQpQe9LvBqcFEJET0fH7/HPlP/0z/u52c19ESPS3CrY8Av/GE1r0NYywq7VOXCxZ QALuLeyGOMf2Z1JmrS4op1WqME9HH82Um9vfnkswgMfupfJsVvdydw2zjUh/8inM c5CbhlYMrCWVTG2wY3QSXHR2jZM5DldUni8gXpxArmSNPuKPDDtVA3/tT/3cv7Xv dryoae9Tmb4AXIyG3pZoNtYgJomIkk17JY8KoSCZ8NqhRWFU447sg== Received: from ppma21.wdc07v.mail.ibm.com (5b.69.3da9.ip4.static.sl-reverse.com [169.61.105.91]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0kvdj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:18 +0000 (GMT) Received: from pps.filterd (ppma21.wdc07v.mail.ibm.com [127.0.0.1]) by ppma21.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfJOM021077; Fri, 21 Aug 2026 19:53:17 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ekpnyh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:17 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrBP550331922 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:11 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7262120040; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2BB0020043; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 22/24] s390/ptrace: Provide frame_pointer() Date: Fri, 21 Aug 2026 21:52:57 +0200 Message-ID: <20260821195259.2688377-23-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-ORIG-GUID: 3nzV6AOfPHHCbrxy4rmssFcpqvGzTx28 X-Proofpoint-GUID: sJV3iXG8PI9gma7BYgItxWlsQCi4IpV3 X-Authority-Analysis: v=2.4 cv=RoX16imK c=1 sm=1 tr=0 ts=6a88acaf cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=NEAV23lmAAAA:8 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=_uadzYZ_BUT95G4SQMEA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX4VPgQYp+Bj7v ZqENTHps6NKG3o8wU3nVz8F/tgfhaQI8wvjBOckho17DsCdrV51WX8O0BUBb+IqjtpWesb3bPCn 5C/pz4OAHkz+3T443Kx1uLt2XBM0Qkg= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX2oYEHYbnYwdE q/nppDQnWaC7gII1SOCPuHlbehvP3+uFpi+TYrMquEIhxYcHMLVHE9e1pZyfqIsdeZZ1p40tJHN jGOjo5ryALhXNg7qvB0i9oEsqj/SHr2ysQoxll+fmJJkbFUFYDDr8/HlnS26iUv1MQSj2p3lJbI A1h3aFZdCPdNZ7/1h6wzDw20pHiFeD4HnV6Se7k4cu+HU7x/Nd1yXQiNaN3n7xHFC6ZHlM8B+US nrfqc1+3nmxQ8xMLFQtWVJh7b7o16NOb+Ttoob3DnhQYPvCd47vUj5KyZu6+swyOVVTu1XSzMoL A8yKHgxJcweARhBBKXQA3Ymt2sqD33NuDBDdqkQ0qM3zwDSrz3XyCf25eP2DRXLDm2+RX0IKRMa shHSJZSbEVzUfF+GoO5w6wYlmemLDM5UQ/PVSlNfCAVvezlIecin04YmGPsp0dfvrc8HiFsfnaq HL6z3Iv/ju/s2sN4n3Q== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 suspectscore=0 malwarescore=0 adultscore=0 clxscore=1015 phishscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" On s390 64-bit the s390x ELF ABI [1] designates register 11 as the "preferred" frame pointer (FP) register in user space. [1]: s390x ELF ABI, https://github.com/IBM/s390x-abi/releases Signed-off-by: Jens Remus --- Notes (jremus): Cherry-picked from "[PATCH v4 00/12] s390: SFrame user space unwinding" series and adjusted to .eh_frame: https://lore.kernel.org/all/20260127151926.2805123-9-jremus@linux.ibm.c= om/ arch/s390/include/asm/ptrace.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/s390/include/asm/ptrace.h b/arch/s390/include/asm/ptrace.h index 495e310c3d6d..85765979a595 100644 --- a/arch/s390/include/asm/ptrace.h +++ b/arch/s390/include/asm/ptrace.h @@ -255,6 +255,12 @@ static __always_inline unsigned long user_stack_pointe= r(const struct pt_regs *re return regs->gprs[15]; } =20 +static __always_inline unsigned long frame_pointer(const struct pt_regs *r= egs) +{ + /* Return ABI-designated "preferred" frame-pointer register value. */ + return regs->gprs[11]; +} + static __always_inline unsigned long regs_get_register(const struct pt_reg= s *regs, unsigned int offset) { --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0b-001b2d01.pphosted.com (mx0b-001b2d01.pphosted.com [148.163.158.5]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A03743FFAA4; Fri, 21 Aug 2026 19:54:12 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.158.5 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342054; cv=none; b=GC67nmHk/SBwQ+O07eXmJwiKQlM74JZ4/JFCtWsBEr8sYZiFlS2ejjqLOWlaDAY+soOa3ZjSGjznDVHwwu5cmIu41NpNNSc/E0fE376Wvr60lgW/PNy62dQJ9khomQQ7fxLU8ec5wlwmRY00eV6KFMSgfT6gEhjqmpMyhktUC2A= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342054; c=relaxed/simple; bh=ZWia27gK5Uu/rA6TzDzSSPKWN0bclHUCBb817crgoGA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=bH3DW7t1AMebAZ9Omjg8KA1rEgoP2eVaTzoEwBpA6bT23Z2opQtU7fuY/+54uZuTn0I3pkZgIxPUIL9Jq3kmYh3A31fHZy8IHZ2Bs48AkYEaFMQJBNdHFcbSbfVkHfPXgwSZKCPyNlkaApwx9A34IFBLLZsm/JlrSUPX1Z52HwI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=eaRTdbVJ; arc=none smtp.client-ip=148.163.158.5 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="eaRTdbVJ" Received: from pps.filterd (m0356516.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVsMb2253836; Fri, 21 Aug 2026 19:53:17 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=UBQVMEerwR6B6Lb2m WCr+ZIf4sr/j5+4uJyDzFTYLIY=; b=eaRTdbVJErkdFF7CjeWZRJ2nLmkpR0Ffa htGsE2FDWt0ECHXix52Pe+Wcgh4Tw4P3dSplcZTkHHLnlVgzawWw2UZjEVrdrG9O AO0VgbHZmfx/QCU8TJFgCdNU6YJFzrOfxha+CkOogVNktzAt5bnmiZbScEdbrc5m FnT3HCCeAEVXnaJ39okTITVi0WFjv7hNdyBOMAN5wPwf/VDgJRRerUZ6+qfYHuKs /Ls0V9r68cdAAHN943JZdHomyfti0hWVp68r7lA5I7wbhlMV+ecsYinWHiTzUFsV Qr4TGBwsS4BVCtDBNFBdDJdT4ESvM6DMkj1NASmfqb3Nsg5cG8Qqg== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu4krm0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:16 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfOOH016658; Fri, 21 Aug 2026 19:53:15 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xhpnky-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:15 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrBLo50331924 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:11 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B41F120040; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 776702004B; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 23/24] unwind_user/eh_frame/s390: Enable eh_frame unwinding on s390 Date: Fri, 21 Aug 2026 21:52:58 +0200 Message-ID: <20260821195259.2688377-24-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXzKG+S2u53BzP hqy+2y2eBLsMuAyXCGbVawq72lSScsbNJz2QBM8GHbKjMux/2gIhPSukvKMSA7oG/MbgdbfegmF LXqxfdluZWsF3/GctKUrLyfHKa1iTRs= X-Proofpoint-GUID: ismV3-0PHheBjc3lL-v0KI1YRoSnqBTU X-Proofpoint-ORIG-GUID: fh0wHN0Grpa8vy5clGXhKBYq-SjqqQM1 X-Authority-Analysis: v=2.4 cv=RPmD2Yi+ c=1 sm=1 tr=0 ts=6a88acad cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=FmDO2REWYRq66Aip4RwA:9 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX2Xt7KTGJ0tcn jUt54EXZmbaP4rKr+60qBjMsiMxVUT7F/D2spaFaf24XGFV2jam59DxRof9obOnyHn7A9j4w4P1 lIYANRQp6kylxUgd4IMoPK87Yr2Gm7YI94bx+PG2YDn5kC7k5Vk0PGFW7t2cpx7suCkkLe4S0kw 2BYVjcbcEvDmblSMoM+Z0bX/WM5TK9nOxqDUZbmb2EowFvrKKYkj8L5v2jxh21yAc1Q4SVLSuAN E9wZghJECHta9UQ871tupgBHyEZt+/GvL5kmnZcICkerSFRdeNzhrEXeiy4i3NGO0FJ16ReaurX MJjFd+hYpu5dzEULoddLKMvfclco6brQx6+MqUzLDEkiHtnoY+GJXHRWlfaRzv0PZCAa5iAXGhF 0L7Vqm8eSrgZb/p79ezXVyxHsZZXKmkB3u6wzjhzEKevMxzCOsTLitzv006b+KII3Nw63hD0k5a UuqtQgWrWQu06mPuyrQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 clxscore=1015 phishscore=0 adultscore=0 spamscore=0 priorityscore=1501 bulkscore=0 impostorscore=0 malwarescore=0 lowpriorityscore=0 suspectscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" The unwind user eh_frame implementation works well with GCC and Clang generated code on s390. Enable it. Signed-off-by: Jens Remus --- arch/s390/Kconfig | 1 + arch/s390/include/asm/unwind_user.h | 71 ++++++++++++++++++++ arch/s390/include/asm/unwind_user_eh_frame.h | 24 +++++++ 3 files changed, 96 insertions(+) create mode 100644 arch/s390/include/asm/unwind_user.h create mode 100644 arch/s390/include/asm/unwind_user_eh_frame.h diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 84404e6778d5..fa229ac92d5a 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -251,6 +251,7 @@ config S390 select HAVE_SOFTIRQ_ON_OWN_STACK select HAVE_STACKPROTECTOR if CC_HAS_STACKPROTECTOR_GLOBAL select HAVE_SYSCALL_TRACEPOINTS + select HAVE_UNWIND_USER_EH_FRAME select HAVE_VIRT_CPU_ACCOUNTING select HAVE_VIRT_CPU_ACCOUNTING_IDLE select HOTPLUG_SMT diff --git a/arch/s390/include/asm/unwind_user.h b/arch/s390/include/asm/un= wind_user.h new file mode 100644 index 000000000000..41ff0b477626 --- /dev/null +++ b/arch/s390/include/asm/unwind_user.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_S390_UNWIND_USER_H +#define _ASM_S390_UNWIND_USER_H + +#include +#include +#include + +#ifdef CONFIG_UNWIND_USER + +static inline int unwind_user_word_size(struct pt_regs *regs) +{ + return 8; +} + +static inline int unwind_user_get_ra_reg(unsigned long *val) +{ + struct pt_regs *regs =3D task_pt_regs(current); + *val =3D regs->gprs[14]; + return 0; +} +#define unwind_user_get_ra_reg unwind_user_get_ra_reg + +static inline unsigned long __s390_dwarf_fpr_to_fpr(unsigned int regnum) +{ + unsigned int fpr; + + /* + * Convert from s390 DWARF floating-point register number (16..31) + * to floating-point register number (0..15): left rotate the least + * significant three bits and then return the least significant four + * bits. + */ + fpr =3D (regnum & 3) << 1; + fpr |=3D (regnum & 4) >> 2; + fpr |=3D (regnum & 8); + return fpr; +} + +static inline unsigned long __s390_get_dwarf_fpr(unsigned int regnum) +{ + struct fpu *fpu =3D ¤t->thread.ufpu; + + save_user_fpu_regs(); + return fpu->vxrs[__s390_dwarf_fpr_to_fpr(regnum)].high; +} + +static inline int unwind_user_get_reg(unsigned long *val, unsigned int reg= num) +{ + if (regnum <=3D 15) { + /* DWARF register numbers 0..15 */ + struct pt_regs *regs =3D task_pt_regs(current); + *val =3D regs->gprs[regnum]; + return 0; + } else if (regnum <=3D 31) { + /* DWARF register numbers 16..31 */ + *val =3D __s390_get_dwarf_fpr(regnum); + return 0; + } + + pr_debug("%s (%d): %s(%u): unsupported register number\n", + current->comm, current->pid, __func__, regnum); + return -EINVAL; +} +#define unwind_user_get_reg unwind_user_get_reg + +#endif /* CONFIG_UNWIND_USER */ + +#include + +#endif /* _ASM_S390_UNWIND_USER_H */ diff --git a/arch/s390/include/asm/unwind_user_eh_frame.h b/arch/s390/inclu= de/asm/unwind_user_eh_frame.h new file mode 100644 index 000000000000..842d9f7c3d80 --- /dev/null +++ b/arch/s390/include/asm/unwind_user_eh_frame.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_S390_UNWIND_USER_EH_FRAME_H +#define _ASM_S390_UNWIND_USER_EH_FRAME_H + +#define EH_FRAME_REG_SP 15 /* designated stack pointer register */ +#define EH_FRAME_REG_FP 11 /* "preferred" frame pointer register */ +#define EH_FRAME_REG_RA 14 /* designaged return address register */ + +/* Instructions must be 2-byte aligned */ +#define EH_FRAME_MAX_CODE_ALIGN 2 + +/* CFA is defined as SP at call site + 160, so that SP =3D CFA - 160 */ +#define EH_FRAME_SP_VAL_OFFSET -160 + +/* SP may be saved on the stack or in a register */ +static inline bool eh_frame_reject_sp_rule(void) +{ + return false; +} +#define eh_frame_reject_sp_rule eh_frame_reject_sp_rule + +#include + +#endif /* _ASM_S390_UNWIND_USER_EH_FRAME_H */ --=20 2.53.0 From nobody Mon Sep 28 12:33:13 2026 Received: from mx0a-001b2d01.pphosted.com (mx0a-001b2d01.pphosted.com [148.163.156.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 158EC40926E; Fri, 21 Aug 2026 19:53:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=148.163.156.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342026; cv=none; b=fpT93mmFCpGrPupe4MuzeOP7emnXOV94rtAYni8rqg7/a2c4dL+cd2/0KVOe7fxP6alNezCLFmF7rNBZbzUrNg52zl06+0gwyqu7YyzpTHL3hfn5AnWGdGFNeeAJ5uilALZNXxlgkCNW2UrhRF/JFL1sng9USr+Pszl1FPXT1JM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787342026; c=relaxed/simple; bh=9Gf0mjWJVje9AvWrkpcwY8nML4OmYITCRsXGuGEPsh8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=htl6n+cHvZIgxmbklbKEK8JiwJe/r08opsdrhgKcEbybIQEyyI5yXhx98RLWUe06ovXnB7G1M0CuX3pU+xfELbBpGkX/gWjdWMfCtXw7Orm6Y6ZFwxYsKZkyYC/CgFrLpIYJpc+fuD1NvIGjm1ePKQh85PwSkIb4ukBcQgQf5Cs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com; spf=pass smtp.mailfrom=linux.ibm.com; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b=AGcNeIcV; arc=none smtp.client-ip=148.163.156.1 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.ibm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=ibm.com header.i=@ibm.com header.b="AGcNeIcV" Received: from pps.filterd (m0353729.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 67LIVUDd491584; Fri, 21 Aug 2026 19:53:18 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ibm.com; h=cc :content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=pp1; bh=8rY+uuCnqVe7Q3+18 p03523fKSiBzC3K17ktOGVPiEA=; b=AGcNeIcVB3h9W/JuQs7F46pUMDT2/GE/W DxkmGguNi1jNqirPesYkTkTe52SirvH7j41xAJWmjMjrJHglctvER32q7jbM/xmh 59wkWpmFlSi3fLlYraCqTHRgpjEQAsBzmRflJaGIe9q3CbwzoyWF5tIr0HcI+yoB NkbIsxBlNEe6oqf8PowRscNy1YR9K9YzrHEhI596HNBcCDnGT7+JzCIhIu5/8rNH SnM89uohL5rWKJdHKwT/7aOXkf5wMwXWcnaukX1CT5pm3qNoM6vRxPweZ3laVzEn g1Ao8tdbq8SExWZaxaLeQWyYg0iBpRg1gayHOSMvVKWvYBl94Z0Bg== Received: from ppma23.wdc07v.mail.ibm.com (5d.69.3da9.ip4.static.sl-reverse.com [169.61.105.93]) by mx0a-001b2d01.pphosted.com (PPS) with ESMTPS id 4g4yu0kvde-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:17 +0000 (GMT) Received: from pps.filterd (ppma23.wdc07v.mail.ibm.com [127.0.0.1]) by ppma23.wdc07v.mail.ibm.com (8.18.1.7/8.18.1.7) with ESMTP id 67LJfONa016663; Fri, 21 Aug 2026 19:53:16 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xhpnm1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Fri, 21 Aug 2026 19:53:16 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (smtpav03.fra02v.mail.ibm.com [10.20.54.102]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67LJrCts46662004 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Fri, 21 Aug 2026 19:53:12 GMT Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0A23C20040; Fri, 21 Aug 2026 19:53:12 +0000 (GMT) Received: from smtpav03.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B90B820043; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav03.fra02v.mail.ibm.com (Postfix) with ESMTP; Fri, 21 Aug 2026 19:53:11 +0000 (GMT) From: Jens Remus To: linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, linux-s390@vger.kernel.org, x86@kernel.org, Steven Rostedt , Josh Poimboeuf , Peter Zijlstra , Mathieu Desnoyers Cc: Jens Remus , Heiko Carstens , Vasily Gorbik , Alexander Gordeev , Ilya Leoshkevich , Indu Bhagat , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , Namhyung Kim , Andrii Nakryiko , Kees Cook , Sam James , Fangrui Song Subject: [RFC PATCH v2 24/24] unwind_user/eh_frame: Add prctl() interface for (un)registering .eh_frame_hdr sections Date: Fri, 21 Aug 2026 21:52:59 +0200 Message-ID: <20260821195259.2688377-25-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260821195259.2688377-1-jremus@linux.ibm.com> References: <20260821195259.2688377-1-jremus@linux.ibm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-TM-AS-GCONF: 00 X-Proofpoint-Reinject: loops=2 maxloops=12 X-Proofpoint-ORIG-GUID: SuTCKgQiXsg2zUdBEiewlc9c_ulmQ1d2 X-Proofpoint-GUID: AkTCuL3l6dUSh2nfNRu__wC3MPuXeRgX X-Authority-Analysis: v=2.4 cv=RoX16imK c=1 sm=1 tr=0 ts=6a88acae cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=PpU6TSaerSOHJBOlBi4A:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfXxLuhit6kjRTR aapVjOJSGBtlrFSVzvgJnzG0ScIyG3VJqJx3zYTj7kUP+e4PHrRd8VgSNK+tQMOFWd2J4do7Aif y1BYhR6SstpLmgv4ThwOVzVJF+YTFZs= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODIxMDE1NSBTYWx0ZWRfX8O8V/7reRjPy a+cTkM8rDl8ZqswtfBXazHK77gBzmtWOalDSy2AHffB509XvjAxlrgi5QTje4JfCI8gT7wUjUKo 46L1rnjZoCkW8/wuXkMOS8VhlGKuK453+6anMkItSEFRMCEPM/9ylyVrjNAPG3fU5DUqN5JQVp0 P2Z+fbUDDtIu4R6P9fsjTN6WbjhJzT5FeqVcmgdApwuKH8BP+DgskeJfdT1WU0jg3oGddRawjzu mp4sh/p9To+H2d5lSaWQ3+uVP4TdsOvvyc1K/0jmDHrr3wHur1kOk57QxfjvywsOqB0jkYMkBJr Z+Bu+etG5RpltJFs9Am5Z1X7CzSxnD6ibk+AkDHsYWoVG3M1WYpuVNasAEyqMKEFx5iz4te5cXu g/1HGzX9R+dfMtKIedbNQ3nHvWzTI5bRLj4SLkoq6tccMswHGx4DUAllWyrc6G4iNsGdQnxCGnN zLR8Xq7ZKS9Bpn72+xQ== X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-08-21_06,2026-08-21_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 suspectscore=0 malwarescore=0 adultscore=0 clxscore=1015 phishscore=0 spamscore=0 bulkscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608210155 Content-Type: text/plain; charset="utf-8" The kernel does not have direct visibility to the ELF contents of shared libraries. Add prctl() interfaces to register and unregister .eh_frame_hdr sections that allow dynamic linkers to tell the kernel where to find these. Both prctl's take a pointer to a new structure: struct eh_frame_setup { __u64 eh_frame_hdr_start; __u64 eh_frame_hdr_size; __u64 text_start; __u64 text_size; }; and a size of the passed in structure. If the prctl's need to be extended, then the structure could be changes and the sizre of that structure will tell the kernel what it is the new version. If the kernel does not recognize the structure, it returns -EINVAL. eh_frame_hdr_start - Virtual address of the .eh_frame_hdr section eh_frame_hdr_size - Length of the .eh_frame_hdr section text_start - Virtual address of the related text section text_size - Length of the related text section The unregister only needs the eh_frame_hdr_start and requires all of the remaining fields to be zero. Based on Steven's patch "[PATCH v2] unwind: Add sframe_(un)register() system calls". [1] [1]: https://lore.kernel.org/all/20260528151023.00f5ec4e@gandalf.local.home/ Signed-off-by: Jens Remus --- Notes (jremus): Changes in RFC v2: - eh_frame_{register|unregister}(): Reject zero user_data or size. include/linux/eh_frame.h | 20 +++++++++++++++ include/uapi/linux/eh_frame.h | 14 +++++++++++ include/uapi/linux/prctl.h | 4 +++ kernel/sys.c | 11 +++++++++ kernel/unwind/eh_frame.c | 46 +++++++++++++++++++++++++++++++++++ 5 files changed, 95 insertions(+) create mode 100644 include/uapi/linux/eh_frame.h diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h index 3c88ab2f7858..3a61ed0ae739 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -6,6 +6,8 @@ #include #include =20 +struct eh_frame_setup; + #ifdef CONFIG_HAVE_UNWIND_USER_EH_FRAME =20 struct eh_frame_section { @@ -40,6 +42,12 @@ extern int eh_frame_add_section(unsigned long eh_frame_h= dr_start, unsigned long text_start, unsigned long text_end); extern int eh_frame_remove_section(unsigned long eh_frame_hdr_start); + +extern int eh_frame_register(struct eh_frame_setup __user *user_data, + __kernel_size_t size); +extern int eh_frame_unregister(struct eh_frame_setup __user *user_data, + __kernel_size_t size); + extern int eh_frame_find(unsigned long ip, struct unwind_user_frame *frame= ); =20 static inline bool current_has_eh_frame(void) @@ -78,6 +86,18 @@ static inline int eh_frame_find(unsigned long ip, struct= unwind_user_frame *fram return -ENOSYS; } =20 +static inline int eh_frame_register(struct eh_frame_setup __user *user_dat= a, + __kernel_size_t size) +{ + return -EINVAL; +} + +static inline int eh_frame_unregister(struct eh_frame_setup __user *user_d= ata, + __kernel_size_t size) +{ + return -EINVAL; +} + static inline bool current_has_eh_frame(void) { return false; } =20 #endif /* CONFIG_HAVE_UNWIND_USER_EH_FRAME */ diff --git a/include/uapi/linux/eh_frame.h b/include/uapi/linux/eh_frame.h new file mode 100644 index 000000000000..8cca3792f323 --- /dev/null +++ b/include/uapi/linux/eh_frame.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +#ifndef _UAPI_LINUX_EH_FRAME_H +#define _UAPI_LINUX_EH_FRAME_H + +#include + +struct eh_frame_setup { + __u64 eh_frame_hdr_start; + __u64 eh_frame_hdr_size; + __u64 text_start; + __u64 text_size; +}; + +#endif /* _UAPI_LINUX_EH_FRAME_H */ diff --git a/include/uapi/linux/prctl.h b/include/uapi/linux/prctl.h index b6ec6f693719..801a209bab3f 100644 --- a/include/uapi/linux/prctl.h +++ b/include/uapi/linux/prctl.h @@ -416,4 +416,8 @@ struct prctl_mm_map { # define PR_CFI_DISABLE _BITUL(1) # define PR_CFI_LOCK _BITUL(2) =20 +/* EH_FRAME management */ +#define PR_REGISTER_EH_FRAME 82 +#define PR_UNREGISTER_EH_FRAME 83 + #endif /* _LINUX_PRCTL_H */ diff --git a/kernel/sys.c b/kernel/sys.c index df69bd71de03..ee67badf267c 100644 --- a/kernel/sys.c +++ b/kernel/sys.c @@ -65,6 +65,7 @@ #include #include #include +#include =20 #include =20 @@ -2907,6 +2908,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, a= rg2, unsigned long, arg3, if (arg3 & PR_CFI_LOCK && !(arg3 & PR_CFI_DISABLE)) error =3D arch_prctl_lock_branch_landing_pad_state(me); break; + case PR_REGISTER_EH_FRAME: + if (arg4 || arg5) + return -EINVAL; + error =3D eh_frame_register((void __user *)arg2, arg3); + break; + case PR_UNREGISTER_EH_FRAME: + if (arg4 || arg5) + return -EINVAL; + error =3D eh_frame_unregister((void __user *)arg2, arg3); + break; default: trace_task_prctl_unknown(option, arg2, arg3, arg4, arg5); error =3D -EINVAL; diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index d1656f5d40f1..063133d1bf97 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -15,6 +15,7 @@ #include #include #include +#include =20 #include "eh_frame.h" #include "eh_frame_debug.h" @@ -1609,3 +1610,48 @@ void eh_frame_free_mm(struct mm_struct *mm) =20 mtree_destroy(&mm->eh_frame_mt); } + +int eh_frame_register(struct eh_frame_setup __user *user_data, __kernel_si= ze_t size) +{ + struct eh_frame_setup data; + unsigned long eh_frame_hdr_end, text_end; + + if (!user_data || !size) + return -EINVAL; + + if (size !=3D sizeof(data)) + return -EINVAL; + + if (copy_from_user(&data, user_data, sizeof(data))) + return -EFAULT; + + if (check_add_overflow(data.eh_frame_hdr_start, data.eh_frame_hdr_size, + &eh_frame_hdr_end)) + return -EINVAL; + + if (check_add_overflow(data.text_start, data.text_size, &text_end)) + return -EINVAL; + + return eh_frame_add_section(data.eh_frame_hdr_start, eh_frame_hdr_end, + data.text_start, text_end); +} + +int eh_frame_unregister(struct eh_frame_setup __user *user_data, __kernel_= size_t size) +{ + struct eh_frame_setup data; + + if (!user_data || !size) + return -EINVAL; + + if (size !=3D sizeof(data)) + return -EINVAL; + + if (copy_from_user(&data, user_data, sizeof(data))) + return -EFAULT; + + /* Unregister only uses eh_frame_hdr_start */ + if (data.eh_frame_hdr_size || data.text_start || data.text_size) + return -EINVAL; + + return eh_frame_remove_section(data.eh_frame_hdr_start); +} --=20 2.53.0