From nobody Mon Sep 28 18:33:38 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 46BE53A83BF; Tue, 18 Aug 2026 14:50:26 +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=1787064631; cv=none; b=AOcpsCZSm6ELFaUEB+03or2ll4NLgXz9Xp+KWQWwzWLtnBMSrLmBkNFHANA21XxUa9ePg6NwfTAY/mp6FstSM9PesUBx0zeUYyOITbnOV7Kp9mTz4GpXYSM1fknb+EE/VFghww/Fz/XpBV7CndvKHobcpCgmThR10vav79s5NFo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064631; c=relaxed/simple; bh=CXyGtsG81Jje362NCcX1DJbpQJ04vztCnyVvNnO2UEk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NC9aBljn14WTHrIkdqNvvW2JNCbGgkbrDTXvbhmaGN90xmSenRPBf7ZfHyDu5hoQISohAMPb3Nx0jAr884bS0NEDiu7r57h7qB3Lx3+ToNRP4yfQ17Wax5wZ1D5+MjTQwa4JI6lc7XXhEcq5tBfwunf3+D8Dwpmkw+iJUfslBcA= 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=fnWD5jLX; 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="fnWD5jLX" 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 67IE3akj542384; Tue, 18 Aug 2026 14:50:03 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=fnWD5jLXufQ9nlTjKRgdAQdzBwDOlYFl4 52Pr5o5UGSwQk6VmJ8BwJJHgm2cbUxrwgYR9Rk9umqvu+uU1quKZnaQkdzscSAU5 B0UYYeVV08l9MFiWefkORQTdrkEc4yMO03e8IQiPgjD67MxrZW8we56sl/oBAMwg 1rswb1eGgc9F9ynchR3YkBN5zjBAuwkPa+spvWFNp0NMk70PNdYMiPy71jvk/z7l AjcWdnqUUcd0I/liBgHpf6JkVcw7Y43WnUlJDZERyinXoMwww5lEffkLoEz9pSKD 2fLr+fagfhfgIDm7y0juFwjY/El5gG05P8TvmcnxxYgr2kA7O3T9Q== 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 4g2frt8bs5-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +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 67IEfK9V029618; Tue, 18 Aug 2026 14:50:01 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g34ngbhge-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnvaT47448324 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:57 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4D66420040; Tue, 18 Aug 2026 14:49:57 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 002372004B; Tue, 18 Aug 2026 14:49:56 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:56 +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 , Dylan Hatch Subject: [RFC PATCH v1 01/25] unwind_user: Add generic and arch-specific headers to MAINTAINERS Date: Tue, 18 Aug 2026 16:49:30 +0200 Message-ID: <20260818144954.2320378-2-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a84711a cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=1XWaLZrsAAAA:8 a=meVymXHHAAAA:8 a=bzoO1hpTG78L7GYmDxgA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX4CG38aez3I14 7JFjNNMkq3aTGejANgcaCSauLftyhhpwzg9raaMbfpfyK3PQt02BWmGpvPuh/oEJcp4zvi685J1 oGU6KXisEKqGhpBjggknjdjAHThKTvs= X-Proofpoint-GUID: p6qFDlKRo-LvSHFTcB6etbf3_AKBGgZc X-Proofpoint-ORIG-GUID: zE0OTYiw_Vjwwm_HHtEpUUKZXLOH4HIt X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX0OMewfk2ifSy 3JWnW8UAhshJbXE0eqUNJrZpDUE+OXlV7ZgK8NOdazL4DODi9To1/WPq6MV/pQv4Z5UIbN9/mCA eTT49e6Fdl1Sg4Mk5LhelkGXrn7rugSXpdttxlyMGyDEgkr7WGyGK+N4EnAhHPSqFX40eymfdOz 4F0wJ+H9vP6U+0FG3zOAdS4SIRe6HuH5AVBymF2nEboQsCpN1DenWjK4tFl3smkDup6L6FzMQbb ATkVeWpK2eOmsekJ3iIZkRJM4Z5vWcMuDOnhkhwzFi5Yq5YlwMOrljDLB4W8tcFad4hyucvNjum 1ITif0I5vedtrOF6GlJKeJmIzLEruvtE/OTozIJcG5j9RqfoBXbWMLj98gJx6bzfIaoRmAAkmHJ n1JKNfm/UMYbDAtCBP751SEgB8+IC41FyHZJC1BlSniYfxoRqvKbdKAjlT192BeIrbecE3XwMP4 vvzTIKP1SQyjvMuErkA== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 2B0F33A7F60; Tue, 18 Aug 2026 14:50:26 +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=1787064630; cv=none; b=f0AHMwmxsckohf/mod5XjQLK3+Tx93Lk41Xz1vgSOrtgC4zgZkj6hi89ES68aEBdXRGaJihnVVwQaea9U6vvQX2Tfcv2AGE/cJPA9NvCYzqxkGd8DOWe2a33M70tiw2ziohJ853V5VtpBSsNILCw/mo1mRss4rnO3PgzlnTHfAQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064630; c=relaxed/simple; bh=uHi5IOcGGygfGL5thWHRKIwx88fWG7DAaRDICca0tMs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=XGovUJxKqnakMFYoaCDPyTQpKgRgnoLfd6X7Z5SUImGOtoLC7TSCgmf6C9ck0AFFCC9Rk9+YeojocMrNGRbr/hgmjDcuDYFgzVC8HeoGScHne3ubTmBIfCNlVo4EoBzNUrq/oAvoNT048cHV/OgXjG51EXHuZJtGp1LfWqcMCdA= 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=Rkvxq6nn; 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="Rkvxq6nn" 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 67IE3c0F542431; Tue, 18 Aug 2026 14:50:03 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=Rkvxq6nn1+qQJ+u923OL9iIAVTCxVZIWP MFrEp1l99xf+b682ro/Be+q77Z/thz5Qm2+aSQuGTivuYgh6edxGsMAfTVnpSwQg RmEJdzftBfwueLc/61R5LMwKMvx7n8RxALZrbAAMKHzUfCQJYwKARiXlA20OC6G0 qIFbg7S9i/1l5IcT9es35/U7oi7bAD3m6yE2tGTm+yDO6l9dIfHFxFKqmlcluzbv GEnSPnTrQ2mSwsmnbKJfIoSEKDI3S9GYzFwkvNmiEiwp3qpO1GpVEujZDbBXmYZ6 4fqJOuA9/C+aECldPFjzGgSkhcwZ/2C4TGFbl6q/rGIMmChuKy1dQ== 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 4g2frt8bs9-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +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 67IEfU2M014833; Tue, 18 Aug 2026 14:50:01 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ek3r6p-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnvF247448326 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:57 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9AC4520040; Tue, 18 Aug 2026 14:49:57 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 52AA820043; Tue, 18 Aug 2026 14:49:57 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:57 +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 Subject: [RFC PATCH v1 02/25] unwind_user: Stop when reaching an outermost frame Date: Tue, 18 Aug 2026 16:49:31 +0200 Message-ID: <20260818144954.2320378-3-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a84711a cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==: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=_1qlYuAciRtwIPuEvDgA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX1HgocRRzc6g2 9fzKEgl1nshKcnTWQyBY0Oa2ES6LmJWSHHb6gK2AJUdaTI+ifxZ+rnoucB0fxGXu20M6zlT1oKR iEraWTq4Ax+ogTPPaEGiOcJvx8uOf6I= X-Proofpoint-GUID: BjcQdVBPIduTvG0QhKpfaWkmmsN4oxp5 X-Proofpoint-ORIG-GUID: c4yxkrPBATvtVIzOd_MAkONSX9IU3OHG X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX1ENGtsLw745t 4KzZoMlltsUQ9jvdKFpBaGApM7jCq7Vghv2c0icJDDU33683t7kspW+QJaH5ioT1cct+fv5YPau iEBUEsqp6VuZVXAewSV8UC+9ohhtycjwaioiCV15eQKj5tw4iOsu6xpTHz/jIOrAoyQ9NXB88xd rqNWXaVtuq1q/9LFT2lEXM+lEm3H4LZf4LRGYrJu/qPUFb68xnmn8poviqZtylxi3Bg3q1alEy3 +W6zFtEOvodGTaTu+fcpvOxL7ReotZ5AXBc0x/X14KB4BrCXJksrWkLSxu2KdPrzFBSYwbB6Ym4 wqmc85mnYrPuE0UiN4fJSV/8/2yx32pkwQq9dOy88u4mCTdNxmPDBr9QWDRk6PkGZLaZs4unSe7 lDTlt5PXDKdsh/MX1zFzoBFJI6img3XWzdIFAybf36vA9aTS3XP78hn9VtD6KU3bdsG8do27r3j WNZjP2dweftf4xMafBw== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 4F0A33AD53F; Tue, 18 Aug 2026 14:50:36 +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=1787064641; cv=none; b=EUhJVt+0mpaR8JJJyARhY46Hqa2Y4vVuGmBlmVP4dp9d1xH//0VbkfskZ8cuY6JjSTetrWMvKKW1IzUOZLpxhDaehbSpHJ67LiqhzpPS9219251Rpj/oncaC1SK9K1OOUShVwYMm0BVcW/8cTJ209xQOT+FIyXgaO7i9+ub7zd0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064641; c=relaxed/simple; bh=URzcqcKildsNvgSpR2lLGV/p+z/i7pvGxHXc8UvWV84=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KuBCUSIuSeY/9Cof+5Jwif4jgRTuPmEDc4wmIRAQXstpGwB+yjy2tgZm3DQc0ZX77lsGBAhhRO7bqtw+Os8yZuPrVowdSvAupMCcUg6sVzohbUDkP29LV2C3UZMVeiuUF0STxtzwvGqj+u+6iTrUjITzkG6Hri9YLak5wfHb1MM= 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=VSqo18AB; 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="VSqo18AB" 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 67IE3rD03582829; Tue, 18 Aug 2026 14:50:03 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=VSqo18ABFmlZVT78D5lhAcdqMy2jAVJdC MWZXHL9OB8cXo3NQ5SJ0h7mqQsL/dsMpKe26jLE8b+XQq9pTfb09owkmzSJz4L+d gnb5uzCT1p0Oa7qBd53GheI6ie9m62vwgsgccStNpnJpAayU3w4O/BDmyt/+hmhz Fc0C9/fAaTknubK7dA9+/lsCvlYT7XOym0snyOvLorIqC7Xl0cYIVB7rATvntM3L OHXqx2BLS6CqIjaalK1m5q3KxEvX/PtcA/FsaUofbPbOERchbgyJIu9s3Z0YL/zX JUWw6ZdO67nEPQIakG7v8MDggDWs0x2WXf5jq9x3qZbw1bohWiKgQ== 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 4g2ehe8h08-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +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 67IEfMvI032436; Tue, 18 Aug 2026 14:50:02 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354ybgbp-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnwQs43450644 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:58 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id EB28A20043; Tue, 18 Aug 2026 14:49:57 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A0C442004D; Tue, 18 Aug 2026 14:49:57 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:57 +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 Subject: [RFC PATCH v1 03/25] unwind_user: Enable archs that pass RA in a register Date: Tue, 18 Aug 2026 16:49:32 +0200 Message-ID: <20260818144954.2320378-4-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX9D7QzlJzNNWQ Q7jTN6AM5BGt/Oj8UPtmrGIAuNszgRp+bf53wC6DTWHvSralC6Cc9vKgC6uNcJ/l54c21LoBDlt pZ9++Ry+Tfv8kUzxM3Z+kGmQW3muXQ7D0/SeSqwnr2cpux2khkRaG6QbuEwr2X8wN5DpAwv6BWL vwWoL8gXCu84aui+VwEeG3ErkOyFDCXKM/FsfI7sYvqmD7kSyS3d8tAIu2OuV1KhGX4yOU+b8TZ ltTiwyUz2E03luVidwA41veYud27I64kL3bSAOkqCnYVOgBXX/MXU809U4HOl+kqX4pyuy7KvTO RBVDlpqAJhRdLJqOLcK+02mkXRqZBciI0MjgZ5ar5ORHwB8xeFoQUPRH99XDXZgpvo+FoVDq+DC kV++7wSgmH+urvts4cQDJvuL6xFFDXQZ9ipXO8gb80xyzUe5txf4p6aGcLh8D3vx963NZoMMnF2 yZtiqErDTzapMm+2WQA== X-Authority-Analysis: v=2.4 cv=DY8nbPtW c=1 sm=1 tr=0 ts=6a84711b cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pGLkceISAAAA:8 a=lmaF1edk6S-LLGGX4wsA:9 X-Proofpoint-ORIG-GUID: Fudr4d5TOv1TC2mZhNZSW_il2A9ovbc6 X-Proofpoint-GUID: p3H-jH2f_7fiOQMXqfiP0tlFV2B7VZR_ X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX/IE7IFnUMmb3 MGRJ+xcs+TdUd+glWqKuWQrX5JmMD8VWLpIa2hInh9esNLIMAfe//YomuZ08e63H9u71D9R6W2c 2EThFgDnrud2/nU4T2LP4Ix7H5mQcy0= 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 clxscore=1015 spamscore=0 malwarescore=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 2AD663A7F41; Tue, 18 Aug 2026 14:50:26 +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=1787064629; cv=none; b=O8wZQdSMI6R7UU6jrKH+82TVPCx5pOxmu9O06QoRsnBUo3W06JZlBRnF58ijISM+epcgBZcQkoiata7J6wVarkdnNg0KnrZ1XBzIIh4S6t88vIHi3YjgO4Urx6JevsIcgo/XhjpEL5RHUg90UoWMGBhgOBJh1hoFbjWZgxr8rBE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064629; c=relaxed/simple; bh=+QQyByo4jRu3q83Fet4sn4qipXTG+C9lCtCzCGQstiA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=llYjmDyJtG0AIMim7niIst9F4TpUAdUG+3rYH6Zp706wI1tC4QETz7eR58ZcMEp01tavxxWSIYZ2iLuPZwaVw5JQMz8P3VL7HtxD18y5ONgKZHPLLLrUOv2p9YzdN8/WTPQWkt7KSp+zWYnu0MjFS11Im2oojwj+RES3+QRvwng= 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=f/fuXXEp; 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="f/fuXXEp" 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 67IE3gtk3582598; Tue, 18 Aug 2026 14:50:03 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=f/fuXXEpHBYBx436dekrjrjdYiX96FBym KenBAoq0/Kpi7S4W+IsRnTK7g+UsK7p3Do+I/3h0wh1JuQgyTOiUPurHgQvgZH3w Z5PO2GhIqyI8vaDoa10rSo+sxxWT3vv/LsmwdMlW6/3OyL+6NTD0RYwkVEQF4rMW XylBPxdx5kRPbZvg+d1nuFg+mrPBZWccGe1HBF3jSMn5NhIJggnphq+GdEruai9i 66FTTSmqUbZP3V0xrXOyWBQZXfoV9731x07K/aY5PJEkP6L8ULIGWm149Q2YxxcN 1DsDevwEwOk1KxeaeZdSbPU5wY+F3fM8AOiGcWiaKKpXRDO1wz8pg== 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 4g2ehe8h0b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:03 +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 67IEfOQ8025421; Tue, 18 Aug 2026 14:50:02 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xh3q50-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnwE226804504 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:58 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 4E74720043; Tue, 18 Aug 2026 14:49:58 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id F08E52004B; Tue, 18 Aug 2026 14:49:57 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:57 +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 Subject: [RFC PATCH v1 04/25] unwind_user: Flexible FP/RA recovery rules Date: Tue, 18 Aug 2026 16:49:33 +0200 Message-ID: <20260818144954.2320378-5-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXyxtV/3S/mqYW ZbZNKYQGpYKLekCAmQpoo2GhhhbT+mwHHKAdreBgHuzSCMTqwhiuoRZ614TJBGdHGIPQALjBzTU /w9yRoiW6zSO8wZ8LoLJHVXvVYCNIntlUPxLBlQ3r6Vrmr53AnBq04UWh4SQSNrkgSfp3OMX+qK 3Sbse5/D2Z3h2PcJqR9eWlRJBQ9i7jYpeoASl5E0s53TjmvFt0AxbWdItHWaEIhpwb+mHdu6XZa zsrP5jo5ysms17Zcz/kww3p03ApMMD6HXwME92cFn+quiNTJC0mpSkwUh6ag0CHGiOTmZr4SiE8 wFyLSh+LstCGvX/WaSFbpzqxq1wSBVwMXQpyLqy2uTbjxcItYkn8MaulxRnFNUYYa+xrHvcJ978 4gpnAkbNavSf/m5DNQcfD9QdRyLfCZAVhWu2jJvu1S/4orPYRKyQbjECCadDZiPN9wSE2TJLZ75 5fJINUrZaGHMnmjelJQ== X-Authority-Analysis: v=2.4 cv=DY8nbPtW c=1 sm=1 tr=0 ts=6a84711b cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=pGLkceISAAAA:8 a=ZPQ1DpjoKQCSDTLUZ9wA:9 X-Proofpoint-ORIG-GUID: jJpqNrZ-Kw8rl0Cis7oREJVuEePW2isf X-Proofpoint-GUID: RlH9MfvZJiHdJU40lmDPVAxyRtMG-7GA X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX2KWEujZhJwC/ PFP4zi8qeylENOcuwcTJspTGVwjnWrZsqW6YbwBBl8P5plJuuH/Lo9NfgFtb6FCPVynY8qh/O0e hbrBpsF5wPp7LLAa96hcdF7/qlhsD/U= 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 clxscore=1015 spamscore=0 malwarescore=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 99FE126F288; Tue, 18 Aug 2026 14:50:27 +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=1787064632; cv=none; b=fPMFeKeSCnVWhp87sGnNU7d/lL2ag+tnASSWWSDEWeW65906evzsmNkI0jsbRoqIqWS0nzqY/Av0mtVynWg6+ftZtdxyV3SbfyuhdbEkPTGObm1owqf96nNV0iDbpAjNq5bR9avbP1NjvF773Ydv4d3JOnY585CIr0+7F09fzwI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064632; c=relaxed/simple; bh=pxvnkWjyvllmDpNuTjBidERmsTqRP+y+9EN7+vcXhiY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=gjLM7ta2zj2LFagw/imHWQI1GvQuaXyFz+rB3Y+1TAoHJnEze0FDLnhjzB9zA7KbqzOcWlsXYNdk2Gwqu+O8lC+mfhg9/d0JrkjyQGZlO3BkrmyCVH+zv1kjdIToOsi4U4rcUDnO9xWoO15EyEwLGM/3axqGODyGkyA0u07mPpY= 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=ZK1Lo1qK; 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="ZK1Lo1qK" 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 67IE3cPe542428; Tue, 18 Aug 2026 14:50:04 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=ZK1Lo1qKe/Do4onnBLwpIfbwLGXSw1WLu Uufr/U/V4gz8M7uQ6RbERLjf47stTFmfHSBU2fipIppNu0a3zxJb/f/K2Oz7pE2w dKjJrAmBFM/UR5R6yVV45TgIyrPWLjGeuX8eGH2ZkvmdGRFtS1Wj/C94h73SXVri BNWqGG5Fy1VgqDc3ZROlZCMpRVJUp1+jJs+IGTliV2L/qikONCT8H/K9Zl0mthAz POzQpOGvTEgdy2VEC2ZtR5n6YXHo2okWoxIivAzbzpQt2QZCJ7Flr3O735qs9mPG 4+tujDrrx46xvUQGm1UgOw4ZM2HKGNIznD+VtAZhROC/2oN+zmlqg== 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 4g2frt8bsg-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:03 +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 67IEfHNO032404; Tue, 18 Aug 2026 14:50:02 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354ybgbs-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnwit26804506 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:58 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 9B3BD20043; Tue, 18 Aug 2026 14:49:58 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 538A12004D; Tue, 18 Aug 2026 14:49:58 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:58 +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 Subject: [RFC PATCH v1 05/25] unwind_user: Flexible CFA recovery rules Date: Tue, 18 Aug 2026 16:49:34 +0200 Message-ID: <20260818144954.2320378-6-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a84711b 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=pGLkceISAAAA:8 a=IqD6mcJyx09DUBNVDg4A:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX45AChHTl32qm 9l3FVFT95G3Y5UdfBeL2mtXBNPBG6zvSzxsKtBKG7a14QxOpYeYWh7hoBCjT5GbUJRVZGIjo6Ap NQZJHffILydiLHXcDlxWHo7xEn1/H1E= X-Proofpoint-GUID: CuXYJYWmmgOnqSIeGQgtNOF3bMgxIBMt X-Proofpoint-ORIG-GUID: lFCVTm_HiiHuq4N_JjyW9MxNqg5tmPAS X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXz+Niq5DmiYGn pZY60Si1KQRxnPkZkhLXEQvRnRviPPRSezzc5LqgyTw4BcMqhowXxLvuitEhgsf5C2+3NJs1bPI b3fITdm0N1LOM4Ceu5rWsS5fNopHsci6BfdYoDdLcng9RLpmFFpg0VoMayBEacNEu3vtveeJuEF setVuGOuZoM2pND95nbSLhM0y6DBLEQIifcsbfxbTq1jhePUhCcutIuSjZ0vaycnjJVilABfFIi afUMfAvowW2phIkodIMe5wDur7vf0E0VFwy2Sj7h0P4wEKJD56wyFkMNtvN6hpDcbKvGOQOZl0M 0M1dZ9o/hgjdmGqiFHEz8MHEHjgFEvDNQstINnIkZS0l0opUF/mF1Q1sgv2CP7FiiSM1JfjuR7/ N5ihOWugkwShR7G9L53ZXl47Ae9sIQDk+Ke5+2q+BOtMJZcaex0eeQj12/KbYFFX2rjUsouznls +oEca+I2jZApqAM+ofQ== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 7EC603A9D9A; Tue, 18 Aug 2026 14:50:33 +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=1787064638; cv=none; b=Gr5eTVvgRfDyoY99tQ9Xp5669nwlPCS6uQBofdNcv+Cknv3x+51MSc2JTQMKvUpDVY7NpA9Lfzfy+HeNC028nNk+/MNl+t5lJSN8L+Z/7JpGVp+cu2vyOLfKpSKw/88UjMKAiJTH+X1WNBEGHbmZS3O5C36LMyxOd5nb6FPz4/I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064638; c=relaxed/simple; bh=VxkjHAblvepLIgb9AXIOQ4663CYXn8d6zZ9kO2Cgr1c=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=NxgXguC2HCd7suwigL/wdcTrrX3wBobuVGza8UGLO6jTDupT7uPlHyLf5OgGRgOnjc6y1G5hXT7VWJMOALCtpR3dKHQuu9TdZyn6W51Opg8InIv40uHaFdf2Q/xFNgG5frv4mzijmXZb8H9tsV5tZizHfgGKvjtKnumcTPa89Wc= 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=kHjfTbZr; 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="kHjfTbZr" 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 67IE3bEW505269; Tue, 18 Aug 2026 14:50:04 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=kHjfTbZrUHcOeLys3+kP+S9d6JUqDKkGn x50jPyVfl64Xd2Tnfg9LcZP81Qg3Hdl4xZ87Q7iyROHhghHtQ5nj2ZRztA74d1i+ +jKQ5nJtgd3AdtYEjl11QgrUsdGyuewgoqniidD23N2yoUYmZp0hHvfrXMqMkN/x e8LEOCGWE8ekmos74jnnhN0PusetRZwQ8emaJ1G73GxK9C2VpN7S8Vn0wLm+cfJA W/yQ35isNi+uCeEBq/NWirho4Y/r3a40RPvkAhTKapftNaNbZI5milfJFhdsBVSS yUqsEe7Vr+MGIgtPKFzVqqXsQVC+I5LAIEjJloLBqxFYte0zee2sQ== 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 4g2fu4rx1v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:04 +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 67IEfM2m014736; Tue, 18 Aug 2026 14:50:03 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ek3r6s-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnxCS43712876 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:59 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id E7AA720040; Tue, 18 Aug 2026 14:49:58 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A0B0F2004B; Tue, 18 Aug 2026 14:49:58 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:58 +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 Subject: [RFC PATCH v1 06/25] unwind_user: Enable archs that define CFA = SP_callsite + offset Date: Tue, 18 Aug 2026 16:49:35 +0200 Message-ID: <20260818144954.2320378-7-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-GUID: WK31jflkumh_TAB4r2GSlR-3b_SAKDab X-Authority-Analysis: v=2.4 cv=NLLlPU6g c=1 sm=1 tr=0 ts=6a84711c cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=ejlfquudVdD-DdDf6fkA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXzDFRDG15wH3i 4L0Ft9lfO6tczkGnVIAfi0Qa/ud9OEoLw3KVcHEdWEVfpejDzYnPHLehmHnuwTzCVBRKAM0abr4 DWGVDdCo0/HXB9GMBWWuFQYvFowsRGw= X-Proofpoint-ORIG-GUID: AlszMMSDSTmDmd0BmEaJdjLfPUN__UIC X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX8eD8O8XQ6j2Z /r0OlZV4ng9uK6FWJ21J7EAUvhZnHbLpsnETMvz503q20pcTQj8s+r6vClFcGcc8A7BBm+R3yWw iIdNg2BzH+dLDK72xvwwsnBnDlTJ97gre0hg2uOkbPUiKQcl2sogqzXC9y/PjovP0CTp+d+Y7zk xDUCxTI0ZZ401D68WG8JgyQUWtIji2qJUGOn4fGe9v5W7K/Z2TZMP220HDNzZ/DzsSUBGbCrFp+ aQl/43Ys6TUz6fTCQYIbzSP9YsjQMBzJEAhVjpVLSd5n0gcH24UjTklUc1mWheOTWXxFPkoLDgA Z8sKRx99Rt9aaxujXV6wxsSMfe4QUWB7gwHz34xk3S1UdIC3Wzpw8mV8WfBHsBqUUnhKGFvr5MV MwVkTRhDHMKQH7ATf/2it7c0y15nz3r/7qsBSS6LvCu8C84EM/xucVie/+6CT+nhYWYD50wG5jP F6Dmczvn9FyiTWTAvdg== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 spamscore=0 lowpriorityscore=0 phishscore=0 impostorscore=0 malwarescore=0 suspectscore=0 clxscore=1015 adultscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 4CD703AA4F8; Tue, 18 Aug 2026 14:50:34 +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=1787064644; cv=none; b=bQTgQUQzE+Y/1D2DtopRwY9JqfTQ6vMx/cx7aGxDn5E/oBrXIvhGzmGLQ+o3/kNFSe00b7/vVqNVF5oJfWh1L5VYkBc2H53aijB44VTvIl8GpG1gESro0Z/h7K2UYiks9NVj/S500TznQrYHKhrjbfrw2Ws14cmDdf9Au2kO8DY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064644; c=relaxed/simple; bh=fMrAaKQDRh0N+MItGWlDhbVi6VQs3PIwzq2RPGUPG9s=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CMb4f9Yk2GWUjw7imGwwAKLnDB7msMV8dNSgU3HlhIAAi3VkOAsqNdBsxS0kzZjcbnfckSPrkCMCJDlfRloct/G0MzPBX5lUIe7HkPhgyKAcSBlsga7S27Nbjz8LNrFrN5556cuIfLkPWDCPkiiV3hLN0hVL6GYhk/RT+DyDJt0= 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=AOt+nruZ; 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="AOt+nruZ" 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 67IE3oCH401813; Tue, 18 Aug 2026 14:50:04 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=8kb35EKUJSqo4IW4m 7fLBLaKUtfNQEPg7W4iTSNshrs=; b=AOt+nruZCuTqEta0rdJzfv/Vs27Y+T7Hu 3rocD6JntdvGEud+eVPO68DTLagEqYaeKwKf/S5okyKr3X0LmDmtziwER9k4HpgS o/fgspxTYR+EKP3uZ2NjzBPFN6zvuNe2ikGY0e4DC24DpzQtrHkU5THCma9hB0xv 0EhjsgiS+wVaQLZ6mnbP0hGF4c3OB+0lTqxXPBqCnTiFFWQkVYxlaITAlChbBIYH hr2jbVLPek4jmOJiCXsGq3rR0m8kNRf6b2im0odlonoxbmDQYTGAq/7Ln/9gfE08 HgglBcuCoVegmugu3OnSG2W4VPZYIGqtKwJPAAub+fX3tzHQt591A== 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 4g2dhm0qmj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:03 +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 67IEfS2e029664; Tue, 18 Aug 2026 14:50:03 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g34ngbhgh-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnxoO46399926 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:59 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 48C5620040; Tue, 18 Aug 2026 14:49:59 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id ED75E20043; Tue, 18 Aug 2026 14:49:58 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:58 +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 Subject: [RFC PATCH v1 07/25] unwind_user/eh_frame: Add support for reading .eh_frame_hdr section Date: Tue, 18 Aug 2026 16:49:36 +0200 Message-ID: <20260818144954.2320378-8-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXwViF9626obSB w5WETyTuX24Ymsf44UKag81wjIk2o+VpPDRJHjBKAaa8UiFCFH5szQco0C5osJhg8EIycDsdfL0 C4l1P28cuR5DdP/31XZGnRG76C1PDMd2sA+04fHTUjeeTdWaJvk5RMxtaTE997evZncenOSGwZi uVRpWFbJBDn58ipyD+SyK219de93XdExyHRMgabEWqzv1i5J3IFFAzVRhcNeWUyaHYksxyducAG Ew8Jf3KeUugcB6BM6ROQi27fxgQ9OBSGAkP0DmkUJBl+DaIdbtoIb/NRr3/0KGAQ/jD4ZXjHHlD 9bkFQm/YfmW/w7vEh0RNnP5ZaRR+VD5ZqBFyfImqo13tTLjqjdyPADb0MNWOK5j2Nojf9SEPatd nkzdqxGo3tK1Zx9AwI31lkXD4mFjfBAv+Dc7qZY/DQMvt1xjBniKDI5kU/NWQ0FGaJks58+3wFP gl+fciXy/DzU+xALqCA== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX5njqBR394blJ OrlvxvwS6bF2tQcfNs+yUiDBiuy8HRANgWeQ3i2Fu2sg74Xtnx0gZIcJ/ydDcFDUPJRpr1yqkwR YIiN8PlAln5dKz8MjpQZeFWUapM0fyY= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a84711c 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=VnNF1IyMAAAA:8 a=meVymXHHAAAA:8 a=SzVkBJ_cOz4MhcCxlBAA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-ORIG-GUID: _cxo-qTalhbuiJCTmRq9fiqoHziktvYR X-Proofpoint-GUID: rsrvSYW_OTm234orC7WykH7-ZU2Hhr_6 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 --- MAINTAINERS | 1 + arch/Kconfig | 3 + include/linux/eh_frame.h | 45 +++++ kernel/unwind/Makefile | 3 +- kernel/unwind/eh_frame.c | 363 +++++++++++++++++++++++++++++++++++++++ kernel/unwind/eh_frame.h | 30 ++++ 6 files changed, 444 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..8d2b638145bd --- /dev/null +++ b/kernel/unwind/eh_frame.c @@ -0,0 +1,363 @@ +// 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 (from + sizeof(__to) > end) \ + 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 =3D 0; + int ret; + + if (encoding =3D=3D DW_EH_PE_omit) + return -EINVAL; + + /* Determine base address based on application */ + switch (application) { + case 0: + /* Absolute */ + 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: + UNSAFE_GET_USER_INC(result, cur, end, Efault); + 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; + table_end =3D table_start + fde_count * entry_size; + if (table_end > sec->eh_frame_hdr_end) + return -EINVAL; + } + +end: + 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 18:33:38 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 756963A9852; Tue, 18 Aug 2026 14:50: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=1787064636; cv=none; b=rKfE43YNgD4hcq7soBKHcyj6GVwWFFb4jrm3ZO4huP/Ah0bnhlQC+mZ9r7gA91a6+eCDWxTNduJO8jlJdXx/d85HSJZ/7zpyPOLWFES9Ij2lGOZVm9tr/KEyBFD6iZ/r/XJHVX+09MoIIGETOBRVbQtnjIv3LnQzldxhXyQcq6Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064636; c=relaxed/simple; bh=lN8qqQ8zjEDTAgZ6kjHsMFZvNSfXO+JEbPkn4/MI/ds=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=dHxEdKysmqfndJLrj2zjb6AqWp/WYtV6SfVMf4TesxAmxK616PmyEOWM/DzkaaUCFam3VaIi3EQfSsGnHvHhdjSPj+EuAdiw7OGZpntpVZyHBhxA/pIFmD6Jxa4KLN/QNyWegXw1MrfujqgFcP8E/VBZZLoSDI0/JcJzqAzrwA8= 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=qTm2wqnr; 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="qTm2wqnr" 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 67IE3xUG402127; Tue, 18 Aug 2026 14:50:05 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=pKBz1o/p432NUkHla qpUldZsAKwtSbndl7l42QkqzZo=; b=qTm2wqnr2CDTSw0peLuJGva+F0mBSzazq dR0gI6/8xCoIcmqs8oWkyhtZxKa5lqMg0P++LUaf8fiCynxcx5QkENh3K6wCdAiO pLniU8PF+gnIvmap6rRtOL+UR1ftf3pwg6xR+yCTcGxtbtP/UPgd4uzG2Pq6IHHp CeWp0VmiW5bNe6UKx5NwYl3r/KO9Ky7kUC7j4avJ9k6AKCvaut6UHwv3X6OT9G4X zZa6pCneO7z2OwzO+0Qs8dhZuYVTnoGWntiCEbGTyPA1VAU3c5Kbphs5WpefQ5Q6 oI2uoYbSUS+2lhIJTxX26/NDTbtdcjusxXY7Eep2siSSaAuOw1f7g== 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 4g2dhm0qmm-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:04 +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 67IEfOqE029642; Tue, 18 Aug 2026 14:50:03 GMT Received: from smtprelay03.fra02v.mail.ibm.com ([9.218.2.224]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g34ngbhgk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay03.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEnx9943712888 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:49:59 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id A4BEA20043; Tue, 18 Aug 2026 14:49:59 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 51D582004B; Tue, 18 Aug 2026 14:49:59 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:59 +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 Subject: [RFC PATCH v1 08/25] unwind_user/eh_frame: Store .eh_frame_hdr section data in per-mm maple tree Date: Tue, 18 Aug 2026 16:49:37 +0200 Message-ID: <20260818144954.2320378-9-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXzI0waxrwv2MS 5IDPuEW8JbHj05nrFWvNRPvtP4ZbfQlasvyw1/F1PlAX64H2dgXQZ9gBuqtSF+5HNcpFWHVvV6r zRGZE+KXQ0NbxqQ1kCHGJn5jG/SpcBEGhMQ+NThJdvJhAtOB8qkja/wz9k5BMB8JYz8G/bF8SUl rzEMfS/SWlBJSLFR63gZpaT+GrAkcwz4Ywiqou+cjZ04RfvgtQThi5W5Vwf359u5haJ9pMC97fB 1K/OW6KziDh2F5VbFaMEnNORpAXAROc7JkkFCuipKhJ6L8eH7oD1tlpz6YfR5ke385l0l5oIWyq T82Pn2o3T6F/5DiGm60OVS1siHnXXZYD2Bwm+B810NBbfPm5J/wrrKZsPnqdhBuhY/MmXdI5/zz 9qoQzZSLi2ELz3yVdSjFQ4j8lxIDnnWABx+n5UDKt5I0xhIV/L6oMXL9ykLDqASwajABwoWiDOh t+K1Jf/Uw6GfBZZvtOQ== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX+rjEIIw/UUnO PgGQh5TxKeUFH7DdGrHKHK31kktoKPX+Sqkd0c7zBVt0mbm3PHJLNBhNMmvJrFZWXkDKLuz3c7P lQwie2OZJCJzla7P/m5carbEt/NL9FQ= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a84711c 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=VnNF1IyMAAAA:8 a=XnyXtB0bseTY-2eMiq0A:9 X-Proofpoint-ORIG-GUID: FMU4cVuGnC3VDc_ukz2lE8oE7K8IE1Cu X-Proofpoint-GUID: OWzBhcfdd0mD-kIJgwxxQIXbHIVGLM86 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 --- arch/x86/include/asm/mmu.h | 2 +- include/linux/eh_frame.h | 20 +++++++++++ include/linux/mm_types.h | 3 ++ kernel/fork.c | 10 ++++++ kernel/unwind/eh_frame.c | 68 ++++++++++++++++++++++++++++++++++++-- mm/init-mm.c | 2 ++ 6 files changed, 101 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..95df4911fd23 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,27 @@ struct eh_frame_section { u8 binary_search_table_enc; }; =20 +#define INIT_MM_EH_FRAME .eh_frame_mt =3D MTREE_INIT(eh_frame_mt, 0), +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 +58,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..c0d71818e197 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(&mm->eh_frame_mt); +#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 8d2b638145bd..7bdf7589466a 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; \ @@ -307,6 +309,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; @@ -349,15 +352,74 @@ 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 mm_struct *mm, + struct eh_frame_section *sec) +{ + if (!mtree_erase(&mm->eh_frame_mt, sec->text_start)) { + dbg("mtree_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; + unsigned long index =3D 0; + bool found =3D false; + int ret =3D 0; + + guard(srcu)(&eh_frame_srcu); + + mt_for_each(&mm->eh_frame_mt, sec, index, ULONG_MAX) { + if (sec->eh_frame_hdr_start =3D=3D eh_frame_hdr_start) { + found =3D true; + ret |=3D __eh_frame_remove_section(mm, sec); + } + } + + 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 18:33:38 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 757AB3A9DB9; Tue, 18 Aug 2026 14:50: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=1787064639; cv=none; b=CIlOGTjIFJdsl8brmt5dJydK19SfYZ1Qr7brukGSYpvcxGKedDIXf8iUtyduVpj040pH5CosrjmqPJzJQsn0JObhhiteTqbheFqKORm8aVFp6U8XIdnXNle9mWoN/jzy4aoqnkHXFVPMkuWgy3G9gCRoHgzlHuZTzxfhKeCDRws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064639; c=relaxed/simple; bh=JS5uSnbG868SLb/wLoTn7Q6qYF10jvEGD5NkM11gFyo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mohzH4ByWrBNXol8lZYu7lb9Rfs1gS4qfz2hq1mM5PCpIWNgYJDKiVxF7au4A35cIQ4HnxOUrWUhp+ije07KwTkDgnvuXRN1sLKMmvnO9iJnzRf6SrrplbzCAG3WRWHunTkm3nnaL7sa6IRIlwzNDLFtpSoROTrYkV+xMuOO8jk= 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=g/Gk6R2V; 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="g/Gk6R2V" 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 67IE3hew542571; Tue, 18 Aug 2026 14:50:06 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=DmYJosP7a3ctaCAQA fHKDxfDl8a84/TUZQJY7oZBI/0=; b=g/Gk6R2VkPT/P5s/lBesST2ujS9SgAosl c/P0hGAyskWeE/obNjyr2ND+gsPAvVinL3FyiY4GNjSuhGAjeJgdAfRvVSfpUseB Us2tphKcSOYdx4OrIKpULkQIKOTEvW8E5euGuk85BpLziY0BxPgs3vIfAG5mZEAv i++JkcN1JYCW6+4rloANMy4g+gNpZvHDeOYEueF+ni/V6XMd8gWY6PDWrpctas0X b3TU9xeEOANaiY6UaEq3YSu7O21CQrzYz/DArbxk1Ndvqh5Tb9+9ilwReGLctXl1 AZopf+3kBO7zhfIug0mrQneb30gPwgrbqLOehVddEbcmoDOsnvpoQ== 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 4g2frt8bsv-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:05 +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 67IEfMpX025410; Tue, 18 Aug 2026 14:50:04 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xh3q58-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo0Mk29819540 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:00 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 15B0120043; Tue, 18 Aug 2026 14:50:00 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id ABAC420040; Tue, 18 Aug 2026 14:49:59 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:49:59 +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 Subject: [RFC PATCH v1 09/25] unwind_user/eh_frame: Add support for reading .eh_frame section Date: Tue, 18 Aug 2026 16:49:38 +0200 Message-ID: <20260818144954.2320378-10-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a84711d cx=c_pps a=3Bg1Hr4SwmMryq2xdFQyZA==:117 a=3Bg1Hr4SwmMryq2xdFQyZA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=VwQbUJbxAAAA:8 a=meVymXHHAAAA:8 a=QVDTdSu5COzsizyIqpwA:9 a=2JgSa4NbpEOStq-L5dxp:22 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXz3hHHTXQTRA+ S+xySZS2yY0+hmGaP5rI/86abLhPYCia6BncWmDFjWJTq9Jp8gw37MpKCe/dKb2hq5HIIQ5Wcjf tobAQV5yFI6mqMzfgAoRBMKTXkZd9so= X-Proofpoint-GUID: Sj404Q0MiNBn0FwaH2wqTEh8EbHWLnrc X-Proofpoint-ORIG-GUID: KmOuiz5-03_xp7Ka98iBBFWzT_Cel-G4 X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX6+aZ25vaPCmO qnFHaJ4AN8xAj3jpmM6FxzuKkT17SofkqnZ5tpzhBERI8HXlT2+Jk/tWASp+0SjMITs3/OT6JWs u0onwHGl2UVttl1YqZvkm82ACFTrd8+EcSUD6GrL+KQCRA3ag8KdcNKknb7GfYhueGm6Vc2xCUv TofqWKFG3KIpAE3cKL7GFnKZXQmetvIlzcjqPmy5ddn6F2RMUco6rGEq3oIw+r63Cb3B1nYW2J4 1Hv68JznCdG1sW5pzZARMTRkUWai1hfTQ1bP2lGXBCpQexkBtSoTHm0xwA/J/cg1g6uvivP0lAR 6i5r/nwvS4pGWtj5pyTky44d1Wrp67LwZdnEWZXNKBvantBSBzFsDP4AB+88cc6CyrZok4zChuO ncrlPedBUH91KdHZHma9YG/bnMktEpEnAcYovKhgGA7x0JkNWV9juG4HbZyX0MedoDrOAepOfhE RqFVP/M/yaxQ1z17R9g== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 --- MAINTAINERS | 2 + include/asm-generic/Kbuild | 1 + include/asm-generic/unwind_user_eh_frame.h | 43 + include/linux/eh_frame.h | 7 + kernel/unwind/eh_frame.c | 943 ++++++++++++++++++++- kernel/unwind/eh_frame.h | 38 + kernel/unwind/eh_frame_debug.h | 19 + 7 files changed, 1048 insertions(+), 5 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..e6d207597206 --- /dev/null +++ b/include/asm-generic/unwind_user_eh_frame.h @@ -0,0 +1,43 @@ +/* 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_AUGSTR_LENGTH +#define EH_FRAME_MAX_AUGSTR_LENGTH 16 +#endif + +#ifndef EH_FRAME_MAX_STATE_STACK +#define EH_FRAME_MAX_STATE_STACK 8 +#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_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 95df4911fd23..e33041e4f9c0 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 @@ -32,6 +33,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) { @@ -58,6 +60,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 7bdf7589466a..5ef8fef06a80 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -13,14 +13,83 @@ #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]; + int stack_depth; +}; + +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; \ @@ -111,6 +180,7 @@ static __always_inline int encoded_pointer_size(u8 enco= ding) } =20 static __always_inline int read_encoded_pointer(struct eh_frame_section *s= ec, + struct eh_frame_fde *fde, unsigned long *addr, unsigned long end, u8 encoding, @@ -140,6 +210,10 @@ static __always_inline int read_encoded_pointer(struct= eh_frame_section *sec, result =3D sec->text_start; break; case DW_EH_PE_funcrel: + if (!fde) + return -EINVAL; + result =3D fde->func_addr; + break; case DW_EH_PE_aligned: return -EOPNOTSUPP; default: @@ -219,6 +293,865 @@ 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 =3D cie_addr; + 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 > 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 */ + 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 > 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, NULL, &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; + } + } + } + + 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; + 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) + return -EINVAL; + end =3D fde_addr + 4 + length; + if (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, fde, &cur, end, fde->cie.fde_addr_enc,= &func_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 */ + u8 range_enc =3D DW_EH_PE_format(fde->cie.fde_addr_enc); + ret =3D read_encoded_pointer(sec, fde, &cur, end, range_enc, &func_size); + if (ret) + return ret; + if (func_addr + func_size > sec->text_end) + return -EINVAL; + + /* Skip augmentation data if present */ + if (fde->cie.aug_data_present) { + unsigned long aug_data_len; + + ret =3D read_uleb128(&cur, end, &aug_data_len); + if (ret) + return ret; + if (cur + aug_data_len > end) + return -EINVAL; + cur +=3D aug_data_len; + } + } + + 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, NULL, &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, NULL, &found_cur, sec->binary_search_t= able_end, + 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); + long offset; + int idx; + + ret =3D read_uleb128(&cur, end, &offset); + if (ret) + return ret; + offset *=3D fde->cie.data_align; + + 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; + + idx =3D reg_to_index(reg); + if (idx >=3D 0) + ctx->state.reg_rule[idx] =3D REG_UNDEFINED_IMPLICIT; + 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; + offset *=3D fde->cie.data_align; + + 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; + + ret =3D read_uleb128(&cur, end, ®); + if (ret) + return ret; + + ctx->state.cfa_rule =3D CFA_REG_OFFSET; + ctx->state.cfa_regnum =3D reg; + break; + } + + case DW_CFA_def_cfa_offset: { + unsigned long offset; + + 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; + + ret =3D read_sleb128(&cur, end, &offset); + if (ret) + return ret; + offset *=3D fde->cie.data_align; + + ctx->state.cfa_offset =3D offset; + 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; + offset =3D _offset * fde->cie.data_align; + + 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; + offset *=3D fde->cie.data_align; + + 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; + offset =3D _offset * fde->cie.data_align; + + 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; + offset *=3D fde->cie.data_align; + + 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; + 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) */ + 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) { + ret =3D __do_cfi_insn(sec, fde, &cur, fde->cie.cfi_insn_end, &ip, targe= t_ip, ctx); + if (ret) + return ret; + } + } + + /* Do not allow remember/restore between CIE and FDE */ + ctx->stack_depth =3D 0; + + /* Process FDE CFI instructions up to target IP */ + 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) { + 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); @@ -258,13 +1191,13 @@ static int eh_frame_read_header(struct eh_frame_sect= ion *sec) return -EINVAL; =20 /* Read pointer to .eh_frame */ - ret =3D read_encoded_pointer(sec, &cur, end, + ret =3D read_encoded_pointer(sec, NULL, &cur, end, eh_frame_ptr_enc, &eh_frame_start); if (ret) return ret; =20 /* Read FDE count */ - ret =3D read_encoded_pointer(sec, &cur, end, + ret =3D read_encoded_pointer(sec, NULL, &cur, end, fde_count_enc, &fde_count); if (ret) return ret; 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 18:33:38 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 46DDA318BA8; Tue, 18 Aug 2026 14:50:31 +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=1787064640; cv=none; b=n8n5YLrRlbMsK42unJouk5HkrBttIhG+byb0E5cUsSiBozF4PZ6NCjCt/g9T8FE9Zow8RT6ik1QxhtmwqTUYVfnUBxIA2QtCr2SEEDqpisVzVrrazULjNy+EAA5p0kGpgJwMwKK0/j39m+3uHarbclTNvJvEH/UtcDbXjfJySQM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064640; c=relaxed/simple; bh=09Zi8Tthhl+ZVVEziNc/E61IazOn+tw78cTGwvV6nKw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=COX+0ZK8uwVFwCKXVwYCiM7Qzu12tZ/BtK8572PyeIx6X2lzeMVMyCFdimVcYV/SojijC/nM8Wl9EXPtyyUSXUHU17euzCe1cQGSX9iBh1CfcjQpJNTpwrwMHqb2YZ2ynqFcgmfMg9J+YpHrzgq/NwEpUthCbzMwoR+8rB9R/4Y= 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=p58qJWui; 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="p58qJWui" 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 67IE3pxL2831707; Tue, 18 Aug 2026 14:50:06 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=p58qJWuiv9fix22KBRnhxClNibK7wO9MF WFeU5rBQEM8BxwDEz5sztZKavpto1RyLUBy9OzsxzESaTkb0Ko23bn9ttfZNJQoc /KoXO4msteHqVb3liHmR9wGnpYfV/2+wqG4TGCQuAHb0fKDuxgkFMhG0hXgg/pY/ IyytsSY0EVkwxEPuuNuAxGJmlXLANFu9kPdICoXoIFuG18rJ0USYX6VMx4UDH2Cs jPfN8yFM3MUanyJn6HNka3hHSsUfGeaTtGahclBUZ09869SXOT/j6Bh26BMwIoNd 8x6l1iKyX5giW6PI/4pPAFd1ry+x+L9PrWlMu4gWQJ79NGDjBGLmw== 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 4g2fsqrvr1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:05 +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 67IEfH1I032407; Tue, 18 Aug 2026 14:50:04 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354ybgc1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo0rY11534722 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:00 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6E65C20040; Tue, 18 Aug 2026 14:50:00 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1C8672004B; Tue, 18 Aug 2026 14:50:00 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:00 +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 Subject: [RFC PATCH v1 10/25] unwind_user/eh_frame: Detect .eh_frame_hdr sections in executables Date: Tue, 18 Aug 2026 16:49:39 +0200 Message-ID: <20260818144954.2320378-11-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX/5nSXbU3GVtB zlNbN+Ld3TAkNbV9FwJ9boImvND0aHqSU7ZBEb7QW2LMQMdfozLXqRHCe79ksy+9SVHVsX3GEO9 9KdOXaftkCkq73PJqRG9uuIXpfmDeuiGo9fRwZnD3fqQC4E6KPfUQiYRAI8E8s78GxI1fQPJxq7 Q9p4sLh4qaKTs7ai+kfCpcZNuLsrSOr/fdwvDAATPqO5t6QNflsMNpJHdnwQf8Qp6YCgBphx48r iD+AnLBca3qYkra/mQAFDhjzRIdoOKZnH9VJ9jtWUjWMft6axiIWjDSYhfWCwciVR7KKLMvDhRm 6fgy9XCbXa2LWifBn2lTLAE3FMUuMFJmelNHG7N39Vf1MZ4TmDbCM2smAY2KLDCf8T5G5oZBWLg wcxUPhQk4FgLOocal3zhgSYnTU6PRKH9STCpMu5LNNOpwxuNyvQR4S43Rbae2jQWL9pKYwltUPO P7/3JPcba1dAAWX6agQ== X-Proofpoint-ORIG-GUID: ClqFjA_j_kL3f2BEpke6kmFIdkqgCqvF X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX0bfV/B1X36Xx dF7VORzxaJkUSmwpZfk2ofpiFtU1mpwad4BNP3tGceLR12VLVu2rfrY99HEJZTTby3Dkdoz/fQ/ PRPj9j91a4Ruzuc87ghm+3WIs7Rt8k4= X-Authority-Analysis: v=2.4 cv=DJe/JSNb c=1 sm=1 tr=0 ts=6a84711d cx=c_pps a=aDMHemPKRhS1OARIsFnwRA==:117 a=aDMHemPKRhS1OARIsFnwRA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=uAbxVGIbfxUO_5tXvNgY:22 a=VnNF1IyMAAAA:8 a=DTHPRnzGk-c2I6QTfOIA:9 X-Proofpoint-GUID: 77TD-xJ2uchAasDAyFIZ00spHfed0Ezv 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 spamscore=0 clxscore=1015 bulkscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 614DF4746B9; Tue, 18 Aug 2026 14:50:40 +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=1787064644; cv=none; b=sdgycnki3Tkuj4+D/w/AGzBbSiIJDAcFHDMSVIofKTOb5S/1uVczBe7KBJwuAqs8mdzOEZBLO4HqZSZc+qvAdY2V1uIUGcc4uCfR/QOZFYSQHURhtQ++R6JYNxINirk2z1b0UDBBtkmopLJBOv7JNT6H7AYaSbpoDjq+rfPCE6c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064644; c=relaxed/simple; bh=AMhQNb4JAsa+jlBSzff6AGFydffy3B//nxd42wH5HfA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=jNka5LmBmRYjmqpTQXXM0rYDHCE6mMHtGtaP/AX1I6H4GUAHWBkoVUQX4MkkfJ5lHHonBZdK2WYJraCEHTI/lvJBvASZX7ZKA7uTE/3TyD8AqVvlmXTGQCBk2pdSY/y1IV9BBp/Y12cHU8wYnLe+GklhJG7s7pR6y1tp7g2iMJU= 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=kJ4qHphw; 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="kJ4qHphw" 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 67IE3ipr2831339; Tue, 18 Aug 2026 14:50:06 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=kJ4qHphw4pL5LFI31hyN/yg5DmdQ9mEXi v0pIhMGdQOFzAuzxco4biEkD9W7OdtwseeDjUWsf6UchwxVkZ5Pw2Id0TP0vAlUl LrM4IocGSbiVYVDTyYrmIs3jh6npwAYzyJ0ZKuTxUrGBi4ySWZUBdOdcI1SFCiPM MuFiMoJK+fEVVtAMuKrxkagKpo8MkImWEEbFVwNoIdB8o+xWyoXp2dZDyVtYWeJI o9p5d3zmOA9B3qz6irvDKXw/ifii3JwnTlH/9bzr4wctFjg7PU092Sy3cFL0W/v8 hUX6cbv/IdSuJhsVyilD0zB/DC+F0CNHDbjCdELE6G1GLxXmSCFtQ== 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 4g2fsqrvr7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +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 67IEfMYm025405; Tue, 18 Aug 2026 14:50:04 GMT Received: from smtprelay04.fra02v.mail.ibm.com ([9.218.2.228]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xh3q5b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay04.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo0No29819544 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:00 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BA8C320040; Tue, 18 Aug 2026 14:50:00 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 7378F20043; Tue, 18 Aug 2026 14:50:00 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:00 +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 Subject: [RFC PATCH v1 11/25] unwind_user/eh_frame: Wire up unwind_user to eh_frame Date: Tue, 18 Aug 2026 16:49:40 +0200 Message-ID: <20260818144954.2320378-12-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX3/UlmZ9W/JP2 WGOeycrYno+H6Fn9R8o1qkq0fuLakg8wCKQ0qU+pX/5F3QEtejPjHMEbrsk1YbTEVUgZMj8yBiV Eu6PHhDjBh9fZoGn5dn5rv4m9//smvHe2UMqG1lqoCXbZvpz6zAg75As29FEtqYvonccxoLK0WP R6ZENaYDivZ1Dm5HAMltsRhiJjfh2j5dGFXx8m6R8Ae4c7QOeEBEiai2OJ1VWCSdNnxr0c9ehtk ILOucnXmFy/blQWVu8AIFeRQh4DDRqDNmSOtKnbm7iy7W1cjxClaPvsYXC2j6BVTv6eXqVlR0pM d2lhnLuPYrWOfSvJGu40U/cbgFDqF+hh+M1FAinCZ8ZPu/nwk2aESkFmkv5e8V8t7mQDCtSHi6l DUgqTAbdhVpqTRo7xk6SkZ0+2J6uA2KdrsXC6sPWmBMHY17h0bsJ5E5G3YSIeI29cWZvU4GVN5o R/p71GY5G4oWlm9kD9g== X-Proofpoint-ORIG-GUID: Fch2np3my5BmMhd0tXmvBuHiLI03faCE X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX6qE0HRT1DzMA L3Qd4uFlIPQcgNd5r4FBR0uakga+/GhAPL4Tt1vOW4XJ9wN4l2aba9sgMbQxp1lxcxaegCCNeDb YVXwXA0/UYyZu3wOVKufXvwQEBylrcA= X-Authority-Analysis: v=2.4 cv=DJe/JSNb c=1 sm=1 tr=0 ts=6a84711e 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=Z71hq_FPCwn_qcrh8uAA:9 X-Proofpoint-GUID: at7WDyMuZ4lCw5N8_ZjgdbBJHfwDgA8t 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 impostorscore=0 spamscore=0 clxscore=1015 bulkscore=0 suspectscore=0 malwarescore=0 phishscore=0 adultscore=0 lowpriorityscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 8C3BF3AAF6C; Tue, 18 Aug 2026 14:50:30 +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=1787064636; cv=none; b=hnzZ31u6pFF3DkTEX+g9SGwpseDhGCSfkpdKHlKfUy8WNtS/Wk+qCtRPAiA5PPqpm9pfnbKtoTLUB9NKd6A8tX0bK2pjreXcrqQJk0661hp0m+hAMcUpvl9nQ/W1JVnabEb+MUCVeaPeDSq4dB+hDO5yHD86N563zcPPfEjJgYQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064636; c=relaxed/simple; bh=mjbWeWD3RUaWpcMHYgyfz+r6AYmiuuZS0pbMDMiJ9i4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b7iRvClHsHQqi6t9kklm6C0g1T2J4NawWsRO9zASRSVkbIzjwdxtnwEuwNj4Znl1fffCCf08U9zfC+cT7PllaeECubV3Ei0bbtFqPmOwmQcxFJVSP/Afi3e15fjCQ8U1RwVxjxeOuPCTEn9AlGazy+w+DXyrny5oDI9wszHMov0= 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=j9wfh/EF; 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="j9wfh/EF" 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 67IE3YcA505135; Tue, 18 Aug 2026 14:50:06 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=wTG9wejM/V/WA1RuS E0To9d2sm5WdPohRXqZOazd4ak=; b=j9wfh/EFpQ7qoximmbUU5XTQgP/aUZ2/u 4Wyzz1SCvCbmjFJSyykbkgUtYi02D6sEqxGKYXSXqnaEVJ1jVEF4MZ9FIn6GwmSb lW0QtpFdCESHa18dRXvoLW6KrSfJNZW6oUAMyiemaRjV4asG2LLPjqA/RGC76nan piu98n97ptp9Btnswyt7KnzAdPCnjn0YRt46UQlNvOVfPbAZWFAZroeOcgwsECxJ +OQkEpqzzmn9pHrUv64u+9nLwoloW+3d7fsyCVzwfJtW18tmXtJhhy/PT4D4z9ZA rrLkiAyzxnliDRiV5fxtzKVCmnl/aSaS1AM67F+eNu95ue5NQLCew== 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 4g2fu4rx29-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +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 67IEfKbW005458; Tue, 18 Aug 2026 14:50:05 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eq3w3x-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:05 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo1hw46989594 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:01 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1CDD020040; Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C073E2004B; Tue, 18 Aug 2026 14:50:00 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:00 +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 Subject: [RFC PATCH v1 12/25] unwind_user/eh_frame: Remove .eh_frame[_hdr] section on detected corruption Date: Tue, 18 Aug 2026 16:49:41 +0200 Message-ID: <20260818144954.2320378-13-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-GUID: der1r54IzDIcCZZ2V4d6xZ3mG-8Gga8K X-Authority-Analysis: v=2.4 cv=NLLlPU6g c=1 sm=1 tr=0 ts=6a84711e 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=sOSzolwKFyyup9Hw6m8A:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX2REDRasiGSI+ b2CWYTfUT2QE2BH4zvYpcjbT57m2gOai8IfbVprBf5h54ejJ+KstLZUaMm0Qd7k7MFAAzN9dpuk x/i3/wNW4YI6494glQOTLmDFedbRKpk= X-Proofpoint-ORIG-GUID: WesP5HBmGJMvL8wanLE9UTqFywAvJrON X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXzZpoiAI9FLve zFD8Ca4Odz6KO7HLaiRs98xdC+7fpXXn/FbFIMfNzemPnAPZAzRoKW53XRxFaN8XI/mRiESCP7v gg3BQRrAl0E0iQG67Rq3PepqYVXMMRUPcSEUlPoJEWwb3vwJO6FBItBaGJMYkiBkdPUUoG8PcRZ +98t0TpLe1fXqBxGIlOW1+ezbN81k9AcYbk2OY0fVOMTHaG63dNuF5VAIr5qJfAapeCdet0gIxS M6UdPuDlsaSO/yQUca5u5Tsla1SmFtBc5Tp3B5+AUcZeniEWxu8qgSv3LgHYsXxjmNbFT2xwsPw zAHWFPGtdxbnUkE2ty6hkB3JucYeqp7prQLy9t4NxnXpeHZAbxn5tq1pkXxpjfpJIwjjf3VsCEt YU89ESZzWaW5vYLessLGz7QCbV0Uk2AOUiKOWGYFzq50rWx7XXCa+A4l4YM8nad6XpWi3A5k5yW ycKedISrcjYtGC55WjQ== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 spamscore=0 lowpriorityscore=0 phishscore=0 impostorscore=0 malwarescore=0 suspectscore=0 clxscore=1015 adultscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 5ef8fef06a80..7657291324c0 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1149,6 +1149,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 18:33:38 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 AB1F22D061C; Tue, 18 Aug 2026 14:50:25 +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=1787064627; cv=none; b=KOsY7qSQm4yDBzF7dgVVQi5CHmDzPN6DbSsr3A/3kOrhRUzwlX2my0E35x5lMZDfIvfXASwEn3ktzNb6rlO8QNi/XVE4WqsuD/lWP9Uclflgn8zRP6psrlLm6pQpKTi2YHmKSIo949QtwPzE/oS3RsApmkMJvQWZgh5oKniPnrw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064627; c=relaxed/simple; bh=3XZ8+FFkuUlTb7Ev+5yyd08oa4ce+P7F59vGHeADNRk=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=LxGkmxgCbhfk+e3fgpVviUNu3hyqkqWzbsXIO+G5TIR9MKRhoUQ4YBl1qg9mq9WiNhEcpXzaWLfLcQj3HcckH8xqAn6JfQa3WhuKmEQJBuESgpbVDjyhze/zLQPQE1Q16NTg+ck4gBqAJMl06+cLeLjKyxMpsdd0LvHlDKseWA4= 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=qg6V/dKC; 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="qg6V/dKC" 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 67IE3cPf542428; Tue, 18 Aug 2026 14:50:07 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=bv8Ybh6/FIjlbgEZa ghAOTI6IsNfSapayGx53KZF0lU=; b=qg6V/dKC+dmRZhZAX5DWJNvXJKwLE/HZO b8tmZhF5qQvmaRzsB+zlr8rFjyaBfRDCxxTx9s9ChZY583B+5Q0jX4fxZwCmlgXV IwnARM4rMypwR/wzbZcrGko8hwl3BUo9DGOG+EBSKRfpkWWvIMb5FQtvqxd+TDci FimSbMjnzR3n2PeSup0S8TAiW1mQsy/cOdF6/KbFXowGG93j0YSAGiDb7UmHVcmU FE01zU40Y3bcIirbJKjK2b4clqmjyHMLh3tkDGCkWNs6l4MxYyyDb5la98oUTw+I rxvVP96AuR2dFcGHp8rXXUd5UHoorysuqx58LIZm6wjFzhyrJUqVg== 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 4g2frt8bt0-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +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 67IEfOTM028585; Tue, 18 Aug 2026 14:50:05 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma22.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g32tw3uw1-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:05 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo1In50397632 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:01 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6AAD02004B; Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 2261920043; Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:01 +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 Subject: [RFC PATCH v1 13/25] unwind_user/eh_frame: Show file name in debug output Date: Tue, 18 Aug 2026 16:49:42 +0200 Message-ID: <20260818144954.2320378-14-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a84711e 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=FE0x1-_S9R1QEdhOvlkA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXzNsLFh3dzp8R wGjYT1DAbKYWCsTsQzsEeBjmOnegGqSPqUvNm/yJi90yr4xiOb2dIs7Koh+5MuCZjIIMoGi7By8 5TmHPRhUF3xpgB1g/AyCthy7+AkrYt4= X-Proofpoint-GUID: nuxLmZv75gVG-zD6bsmwWDAz4saOLbrI X-Proofpoint-ORIG-GUID: unIaWvijCQKKZTD8TUIdAEa3dbYdf91U X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXxoDih1/Ka9E9 D/qf8A/YmKi9N2xYe0d3E9shJIhfACjEmgTqBm6Z4rE04cu7etdf3ZODSU80NQSIlnzLtTlxmzW NrAgLYvETcoel+40KOdVNBFU/W7w0wg2af/V05QHDsUYGF1BV3Sb70lis1fg117C+SCj1pXzDfe Xgue95a23+GmrVy+7pUgnR3jF/YWRsW11jKJJry4NBdgGbW+i32gELjjG8QKcNyDm+08VkSMGJo 3BFQZ6B16rkiMUwsWyY0DurNO7QiZgOfRpP/rYBgXPlStSZ+F4ZT7Gkwj9QEwdKTy1/TBDb+Xuf s7QSHZIzaH0FgiyS0coUAW1L+c0Y7REdqitQb1JWK+1fOGfiMMZY4+77qFCCJjX6vOJeYzBvGMe gPeSr8vRMmDz3ietzDEWu7ZBxHGa6m53aCMuI8VJLvhpo6YKrqs3OBYaDFxCMzBrMwtXjNoC1/z 5R0kISBiX4Z5oQf1ziw== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 e33041e4f9c0..b2f98cd6166f 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 7657291324c0..46ffb535ca53 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1154,15 +1154,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 @@ -1290,6 +1293,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; @@ -1297,8 +1302,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 @@ -1320,7 +1325,7 @@ static int __eh_frame_remove_section(struct mm_struct= *mm, struct eh_frame_section *sec) { if (!mtree_erase(&mm->eh_frame_mt, sec->text_start)) { - dbg("mtree_erase failed: text=3D%lx\n", sec->text_start); + dbg_sec("mtree_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 18:33:38 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 5B9CD47ACC9; Tue, 18 Aug 2026 14:50: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=1787064647; cv=none; b=YxGAOzNumnIhc2sbyAZI0kPg2qkRcQl7eVJm5+KbkcggUs4gR8YbClQSE+QhK9z+heFK5R0u3V2F+yTV/fqTRQgoolrkAgQjHQYgDLnagVSIRpE+Kb2FAPhH4GGxJy9wHvhYZCYVPzD5o73BZ7ULpCcyvu6fCf4pkI+l4liW2rk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064647; c=relaxed/simple; bh=HgqXTNjaQkQm6cTE23s1ZwUulek57QMHF4KLFCYhnfY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rvN1k/EkxUU2plHYslMHdHuaGnYzefnkktJgoH+P0Kv0ATfKRfjT2lyAuBggBT/d4HLmHMbwfUAVrdW9oGWnuoIkPW9Q2Oi+eO1ugDyA9nOJEjlzE+S2UXjz3AJfvNnMa9F2RwGqbeNJVSdNU/AKDgYBpLlgJUjasb8pRC8aUvQ= 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=gMYa67pl; 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="gMYa67pl" 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 67IE40bx402137; Tue, 18 Aug 2026 14:50:07 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=O1e6CFxOxf9L/LPXN k3gG+iLkTQ1jjXbDycl/x4C2sA=; b=gMYa67plXprhf+mJtIQ6utlr9ZPXKuTaG jv/txmyYMXynu3C2wCs5EGqLGjxsyuHc2TobDsiPzaIQq7kzgKqb2EcY4QRZD4uX CJGQHCpasMRSZ44x+skMNuPHkoHxRgrUYVZcbXoP77AtNa56zEInpMY/BBAjdnYb kU6J6PNw8AnOd7vBEXUxsN35Y8vWU+BH15GiHbq+248HbKWOrZpbOQOYCc9W5FET qscgyFdtSChzpd9RWiHEWA+WX5lRSXo9tYYJFM1kwzz+xwrUcPaLtmuNjcnkIU5e QJn8RACqc28j8n8lUoR4ORq5tC4Jzs9Y7KMlnkq/7ELdzWN2OD0uw== 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 4g2dhm0qn2-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +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 67IEfMTA025400; Tue, 18 Aug 2026 14:50:06 GMT Received: from smtprelay02.fra02v.mail.ibm.com ([9.218.2.226]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xh3q5m-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:05 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay02.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo1Xb50397634 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:01 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B830320040; Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 705B02004D; Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:01 +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 Subject: [RFC PATCH v1 14/25] unwind_user/eh_frame: Add .eh_frame[_hdr] validation option Date: Tue, 18 Aug 2026 16:49:43 +0200 Message-ID: <20260818144954.2320378-15-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXxdiWQUmGpLmF Es+Ul7Ut05h3BxA9bQWZ+ESdQm7nnAUvuFNQv0wmGgK9pqVM+Yezu0ECEpmqBeMnexGwnrDRCCr 0NaLChYxner/I5kHidyszNRcuTtL2Yz5wrLY0v8DEGghMSgW9qL1ETzkIrrKdUSkfWHrmuwb3V1 mWvnQy8qb5hFBdVFM+s6aENB63MDq7hOxH5OhsUROfLAIt3tp0fBGqd8o51r6M5zR90MZjVUoCH +UBnMSykVJExnv0nHIven2rAe19NAx8MXUO4FrGdEW7G3q5kAHNO3q+dh8m5u3n03EA2oG/pawD JWs89I/elbQ8PAktF0FgJTcFtktVvKf73v+8HdDaEQylOPFEk1FH1hmqmR8mBggIEk4jT5LT3AI KOif6LQ/W1iYnvRBkW5TPshvCaoHE69eiZN23cdoZcH2lUcDwtllyVrAtzZUkosyjlHA5h7AegS dpfnllP9xJOP1J1uU/g== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX0CGjpXFcH5yb L38p9xrKWEazqqMkubPUNXxYBEszDe0D4+SCBCSCgOuKMv6ad2BlbbY1SCbryH866lza5C+MZ8+ 8W//oX++KwStq54LTtT+raBdp+cx09U= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a84711f 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=rU79QueooZ11dTUg0tsA:9 X-Proofpoint-ORIG-GUID: EMpV_nXwfK9MoGn3zsJoPwCjhCYNKNRx X-Proofpoint-GUID: rzNcgYVZdpiVLSneaMjv_Zb9H1zW4w4i 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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. arch/Kconfig | 22 ++++++++ kernel/unwind/eh_frame.c | 93 ++++++++++++++++++++++++++++++++++ kernel/unwind/eh_frame_debug.h | 4 ++ 3 files changed, 119 insertions(+) diff --git a/arch/Kconfig b/arch/Kconfig index ea969811f798..30d9e876f28a 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 entrire .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 46ffb535ca53..c9161229196c 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1163,6 +1163,95 @@ 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 int i; + + if (!sec->has_binary_search_table) + return 0; + + 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, NULL, &cur, + sec->binary_search_table_end, + table_enc, &func_addr); + if (ret) { + dbg_sec_ehfh(cur, "table[%u]: failed to read function start address\n"= , i); + return ret; + } + if (i && func_addr <=3D prev_func_addr) { + dbg_sec(".eh_frame_hdr: table[%u]: not sorted\n", i); + return -EINVAL; + } + prev_func_addr =3D func_addr; + + /* Read FDE address from table */ + ret =3D read_encoded_pointer(sec, NULL, &cur, + sec->binary_search_table_end, + table_enc, &fde_addr); + if (ret) { + dbg_sec_ehfh(cur, "table[%u]: failed to read FDE pointer\n", i); + return ret; + } + if (fde_addr < sec->eh_frame_start) { + dbg_sec(".eh_frame_hdr: table[%u]: invalid FDE address\n", i); + return -EINVAL; + } + } + + ret =3D __read_fde(sec, fde_addr, &fde); + if (ret) { + dbg_sec(".eh_frame_hdr: table[%u]: failed to read FDE at .eh_frame+%#lx= \n", + i, fde_addr - sec->eh_frame_start); + return ret; + } + if (func_addr !=3D fde.func_addr) { + dbg_sec(".eh_frame_hdr: table[%u]: 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); @@ -1299,6 +1388,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 18:33:38 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 9A0793812FB; Tue, 18 Aug 2026 14:50:27 +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=1787064630; cv=none; b=uv5KzQEXEpM8ifRLyamAafCSZ+un46x+8QH7Ee+LHZ04fHKAYl40knHt0JlaOOpUl1vBVV0HuvTtYFU0a7P7yinQZTro5Ylb8ZpaHdoSL0HPwjz/hsboJfLSVcsCWG6Km+8E355b6Zn7wlJMQ0dIp2ucpkFXlNehp8GTVED+bak= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064630; c=relaxed/simple; bh=XR453XhIO19JWXAk8nUubmPLn12emjh6ohKNJQQpvYs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=MzNM15uFgo1P/bpktRmtemc/J3wfUFLZXlpCqaGnQ+olIKabwPKgZu5zQjRT9ovyXQBZq/V5QEFb7d2k2+NoV5udt5v6d8TqoiidHSPKvr/dghgEGXYua/2sTJ7+u6Y01zS+oJ6UipUdgKlXvSjmGeOlTg03r1GCGaNX4sUMmB0= 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=H6jz3cXo; 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="H6jz3cXo" 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 67IE45jg402315; Tue, 18 Aug 2026 14:50:07 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=GJLD2TZ45N6A1n1Xg MOqI2mQ+OFpWGVkrgw2Ca8i1x0=; b=H6jz3cXoN1A81lDHrCCu7IHNb+jy4WGX3 usd0Q7FXjA+QQme72xeJRyxaR91GVfNVkDsZy6uQer2ORV05YYvXRe0BxrWPEg/F 2p4JVOLyToDmCeIaqRifD/HVj/w4uGFvrMyUuND0tR82GiRBasJuk3xnQJUOclnN D2e3kVRZw+C0cdOBgnersuxySPLbpDKv6aB9TLqLL4mWKMACHr6MsXGogMmQdwNV dRCSqbpRdjIuVxkQhgminmZqLotrggGcslQXpalosGikwcPrxljfVsvN/JoYzfoA tpZ0YeGw9TdAezlRjZwivJjXun46i0CXoU2BRYkkuxFeDETANnVVA== 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 4g2dhm0qn4-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:07 +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 67IEfOd9014762; Tue, 18 Aug 2026 14:50:06 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ek3r7a-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo2dA40501682 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:02 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1307020040; Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BE0D920043; Tue, 18 Aug 2026 14:50:01 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:01 +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 Subject: [RFC PATCH v1 15/25] unwind_user/eh_frame: Duplicate registered .eh_frame[_hdr] section data on clone/fork Date: Tue, 18 Aug 2026 16:49:44 +0200 Message-ID: <20260818144954.2320378-16-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX5jVN3ktEcs1V OhWW2EBXCvWAge5JHXOvKefYmgvaU/dhI6DiFxw7ZbTMqJqEUsFa1huYE+rya0AKfwmgT+Be6XS wj6aIacuuZR2wu1xjgAzg0N7vj8Jf2KWlLVXmNO6PYt3vXr11fjMuMkh0yg2yHz5OmWdL409PD6 EkfjqSWttZH/7+oM9chYfGOLjxA1rn933Em7jcCQKjyDR5npkCtlS9VOPbD+FrGVgpXGbECtxen 0R2zCl9ThJHGxoi8G/P9Q2ZP8nPtYCudTIjvfjfCJtQGWVL6txWK6RZ/PmZof2esPGP8u2YsofN lC+5mllzzMOmdeNBCAxX614ErOgoO1Lvh0Y8FG7CihI3eGy2bjOVDEVRWL9kd+3AKNGY47adP9C oBl1FkjJKHaamHYcHFrIdGFU/j7A1brdH1pQC1ysbxuhimu4dz8EBHzcZzjLfEltcISvEoPx/TH NYIN7cVZzrWjkdqLRog== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX97QOLeRjz0Pq +ffb6p4A+uD0q7hAbL+1vbs6HgvAFL6SSKii0HYL25RC4IvFPXFuRx2k4z1wxrwZVZiWsQaFyC/ Uy3potsp2Sm5dTAR5vOIYd0CzHArLOc= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a84711f cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=D1Fd06331sE75a_1HDMA:9 X-Proofpoint-ORIG-GUID: PZdPFrW3orv6Dc2V2XWL8nrxifOG2bVU X-Proofpoint-GUID: EjqnkSvI_2aQrppzZvaNOp76Fz2yV9HI 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 b2f98cd6166f..65f87c2714d8 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -30,6 +30,7 @@ struct eh_frame_section { }; =20 #define INIT_MM_EH_FRAME .eh_frame_mt =3D MTREE_INIT(eh_frame_mt, 0), +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, @@ -49,6 +50,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 c9161229196c..7f572d1711d3 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1450,6 +1450,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 18:33:38 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 E63663A6EF1; Tue, 18 Aug 2026 14:50:29 +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=1787064635; cv=none; b=gycN40MVUJY5f/ZaS8wTiJCwqWshadtt+8joF1gPkK5iFZFlAKeeVSJYrr8H0gnK7gJYHaN7e7ZDGTkFw8Kat0unVjKPb0x+ZxPaYOcfO4/m6KgTFhXbAwjQIpNw2c5f7bh76HXRQu8KktSpld4XKYm4fkKHz4yhgDTv1ro4JbI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064635; c=relaxed/simple; bh=qpBGjOnxWJLwyFcNvJwhqaVYz+desv9IYZrg0vuSDec=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=j3mMMssLrpO+IFHDR4MTQdYquZ8VQCzW9ScBZvJ01LL5buftfwYWazSGxMNuftZKd014xVUiwKmhL+ms6zLCoaszAGpZFQj76DPGdCC5rlkHawgHoBOA9tdylayQk1l6aeV+36HE8nUZx3eRb4kumDrFRKfYQJgPMkZmw+XClHE= 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=p/AOatu/; 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="p/AOatu/" 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 67IE3e4V542451; Tue, 18 Aug 2026 14:50:08 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=g/+KIf6HT7LAHqydz XWIC4dBo6t+5n60IaqJJ2BxEOc=; b=p/AOatu/sVYTYKHcQCFF/FvKhal8zkRNz 75zdHM30v9FT3T33oYIfYgFg5Zw6/gXhnzrnwJR6v6j0CgfTiQzp9AsROBJAHfY4 s/W/CFBKJj5xIQuux0aAJKl6L3eswXA964w8/Kj71vAWQwl8hAdC3JTDz5mN3KkU QK2KLSgxpGBW/z8WYeEcOQQp6GpgkgIpR+qsfRyYiwERyx/6eo58rCxx1Mo6GLy0 nD53bfgFI3ZZ+tOOQ2puwxsPuog91jPntgAnnGdZ+xxHwnJRvCYqrawCe1h1shIm CQT/dxi7sdm+pSQpiZ9iOV1QU4THNDLZkOkrheembKRVe7DSmCaLQ== 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 4g2frt8bt7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:07 +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 67IEfH1K032407; Tue, 18 Aug 2026 14:50:06 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354ybgc7-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo2Dp51577226 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:02 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6889C20040; Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 194E32004B; Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:02 +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 Subject: [RFC PATCH v1 16/25] unwind_user/eh_frame: Add linear .eh_frame search fallback Date: Tue, 18 Aug 2026 16:49:45 +0200 Message-ID: <20260818144954.2320378-17-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a84711f 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=VnNF1IyMAAAA:8 a=JWffoVpnokn7fAIjgvMA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX58kMGnRX9DxH J29qCD6Zt8FCCJcCNvfx+NxaP7RstjEPHr6iiOV+RHCtQM/K3vXX0jURK3JDZaQanEbwFRteClA QRlXE+0rxpHzXu4SMHHN9maI5HzvmPg= X-Proofpoint-GUID: jlny5mab30eI5TDpItJVE9F8eGd83IqE X-Proofpoint-ORIG-GUID: 3IrNanoOas1yxJNJWARNXtw9jGYIUlfv X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX+plWV7bkeD8F iucRRXNXqCV5TXdHOQK9oWYvgCcpVCgjvgvxjTQQhioKdZ/bBdDLOW1uiDKCGvmaKQzZoyzls4N 5tWVziIj5rypWDFRcKRehb/N8uv9t1u6FUn5GI8q1hD3k4amkU5RkAakC9LLdKUsqtmdvEtkRNw 6be/yD5+dDe1OrdLTCEYT3YhERq5e3JPj8a2xcBfzYTx1OE/zOhwET/Kqqxp1OcmcWw3jWvHCh8 JsMCxNValS3GU23TCP8JooQEGoPfGD8XMqglyuR8r9NoN/NvPN8/ZOdHlK2scLP2+7wOnEd4Nxw Lh0Hl2gweQErB99lBmyYLM3vAwrh9cqmDsDam+rpbKCcD++Y/zooRfhPkWYhg+9kcD+f0zLH/Ux OvwbOZBn2fTqoT0bfsdwyW4SRmKOu4naGSuSZji2FLPvj1evFpPxaFIKhtsWoMMQJPza0MD9cpJ MC2Lsr1yqAKVQPsHcpA== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 Content-Type: text/plain; charset="utf-8" Fallback to a linear .eh_frame search when .eh_frame_hdr does not contain a binary search table. Add validation of the referenced .eh_frame section as well. While testing the .eh_frame validation, it was observed that many ELF binaries contain .eh_frame sections without a zero terminator ("ZERO terminator" in readelf -wf output). For linear search, this is problematic because .eh_frame_hdr only provides a pointer to the start of the .eh_frame section and does not describe its extent. In the absence of a zero terminator, __find_fde_lsearch() may walk beyond the end of the section when there is no FDE for the IP. This was discovered, as it causes the added validation logic in eh_frame_validate_eh_frame() to read past the section boundary. Therefore linear .eh_frame search is guarded by config option EH_FRAME_LINEAR_SEARCH. Signed-off-by: Jens Remus --- Notes (jremus): This patch highlights a potential issue in the linear .eh_frame search path: FDE iteration may read beyond the bounds of the section if it lacks a zero terminator. =20 That said, .eh_frame_hdr sections without a binary search table do not appear to exist in practice, so I currently favor dropping this patch in a follow-up revision. =20 It is not clear under what circumstances .eh_frame is generated without a zero terminator. There have been several GNU linker commits related to the .eh_frame zero terminator over the years, including: - f60e73e9fc09 ("Drop unwanted zero terminators") - 4de1599bcf04 ("ld -r abort in _bfd_elf_write_section_eh_frame") - 2e0ce1c84d32 ("Align eh_frame FDEs according to their encoding") - af471f828cc7 ("PR22048, Incorrect .eh_frame section in libc.so") - 9866ffe25a0f ("Remove .eh_frame zero terminators") =20 Perhaps the zero terminator is expected to originate from crtend.o, though this remains to be verified. =20 IIUC, GCC's libgcc unwinder appears exhibit similar out-of-bounds behavior in its linear .eh_frame search path, if the zero terminator is absent. arch/Kconfig | 9 ++ include/linux/eh_frame.h | 1 + kernel/unwind/eh_frame.c | 183 +++++++++++++++++++++++++++++++-- kernel/unwind/eh_frame_debug.h | 4 + 4 files changed, 188 insertions(+), 9 deletions(-) diff --git a/arch/Kconfig b/arch/Kconfig index 30d9e876f28a..191baf01e948 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -490,6 +490,15 @@ config HAVE_UNWIND_USER_EH_FRAME bool select UNWIND_USER =20 +config EH_FRAME_LINEAR_SEARCH + bool "Enable .eh_frame linear search fallback" + depends on HAVE_UNWIND_USER_EH_FRAME + help + When a .eh_frame_hdr section has no binary search table, fallback + to linear search of the .eh_frame section for a FDE for an IP. + + If unsure, say N. + config EH_FRAME_VALIDATION bool "Enable .eh_frame[_hdr] section debugging" depends on HAVE_UNWIND_USER_EH_FRAME diff --git a/include/linux/eh_frame.h b/include/linux/eh_frame.h index 65f87c2714d8..de68f21e1050 100644 --- a/include/linux/eh_frame.h +++ b/include/linux/eh_frame.h @@ -27,6 +27,7 @@ struct eh_frame_section { unsigned long binary_search_table_end; unsigned long fde_count; u8 binary_search_table_enc; + bool has_binary_search_table; }; =20 #define INIT_MM_EH_FRAME .eh_frame_mt =3D MTREE_INIT(eh_frame_mt, 0), diff --git a/kernel/unwind/eh_frame.c b/kernel/unwind/eh_frame.c index 7f572d1711d3..ac288cec8021 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -509,10 +509,9 @@ static __always_inline int __read_fde(struct eh_frame_= section *sec, return -EFAULT; } =20 - -static __always_inline int __find_fde(struct eh_frame_section *sec, - unsigned long ip, - struct eh_frame_fde *fde) +static __always_inline int __find_fde_bsearch(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) { void __user *table_start_ptr; unsigned long table_size; @@ -590,6 +589,82 @@ static __always_inline int __find_fde(struct eh_frame_= section *sec, return -EFAULT; } =20 +#ifdef CONFIG_EH_FRAME_LINEAR_SEARCH + +static __always_inline int __find_fde_lsearch(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) +{ + unsigned long start =3D sec->eh_frame_start; + unsigned long vma_end =3D sec->eh_frame_vma_end; + unsigned long cur; + int ret; + + /* Linear search through .eh_frame */ + cur =3D start; + while (cur >=3D start && cur < vma_end) { + unsigned long entry_start =3D cur, entry_end; + u32 length, cie_id; + struct eh_frame_fde _fde; + + /* Read CIE/FDE length */ + ret =3D GET_USER_INC(length, cur, vma_end); + if (ret) + return ret; + if (!length) + break; /* End marker */ + if (length =3D=3D EH_FRAME_DWARF64_LENGTH) + return -EINVAL; /* DWARF64, remove .eh_frame */ + entry_end =3D entry_start + 4 + length; + if (entry_end > vma_end) + return -EFAULT; + + /* Read CIE ID / FDE CIE pointer */ + ret =3D GET_USER_INC(cie_id, cur, entry_end); + if (ret) + return ret; + if (cie_id =3D=3D EH_FRAME_CIE_ID) { + /* This is a CIE, skip it */ + cur =3D entry_end; + continue; + } + + /* This is an FDE, check if it covers the IP */ + ret =3D __read_fde(sec, entry_start, &_fde); + if (ret) + return ret; + if (ip >=3D _fde.func_addr && ip < _fde.func_addr + _fde.func_size) { + *fde =3D _fde; + return 0; + } + + cur =3D entry_end; + } + + return -ENOENT; +} + +#else /* !CONFIG_EH_FRAME_LINEAR_SEARCH */ + +static __always_inline int __find_fde_lsearch(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) +{ + return 0; +} + +#endif /* !CONFIG_EH_FRAME_LINEAR_SEARCH */ + +static __always_inline int __find_fde(struct eh_frame_section *sec, + unsigned long ip, + struct eh_frame_fde *fde) +{ + if (sec->has_binary_search_table) + return __find_fde_bsearch(sec, ip, fde); + else + return __find_fde_lsearch(sec, ip, fde); +} + /* Helper to convert DWARF register number to index (FP=3D0, RA=3D1) */ static inline int reg_to_index(unsigned int reg) { @@ -1165,7 +1240,7 @@ int eh_frame_find(unsigned long ip, struct unwind_use= r_frame *frame) =20 #ifdef CONFIG_EH_FRAME_VALIDATION =20 -static int eh_frame_validate_section(struct eh_frame_section *sec) +static int eh_frame_validate_eh_frame_hdr(struct eh_frame_section *sec) { void __user *table_start_ptr; unsigned long table_size; @@ -1246,6 +1321,90 @@ static int eh_frame_validate_section(struct eh_frame= _section *sec) return -EFAULT; } =20 +static int eh_frame_validate_eh_frame(struct eh_frame_section *sec) +{ + unsigned long start =3D sec->eh_frame_start; + unsigned long vma_end =3D sec->eh_frame_vma_end; + unsigned long cur; + int ret; + + cur =3D start; + while (cur >=3D start && cur < vma_end) { + struct eh_frame_cie cie; + struct eh_frame_fde fde; + unsigned long entry_start =3D cur, entry_end; + u32 length, cie_id; + + /* Read CIE/FDE length */ + ret =3D GET_USER_INC(length, cur, vma_end); + if (ret) { + dbg_sec_ehf(cur, "failed to read CIE/FDE length\n"); + return ret; + } + if (!length) + break; /* End marker */ + else if (length =3D=3D EH_FRAME_DWARF64_LENGTH) { + dbg_sec_ehf(cur, "invalid CIE/FDE length (DWARF64)\n"); + return -EINVAL; + } + entry_end =3D entry_start + 4 + length; + + /* Read CIE ID / FDE CIE pointer */ + ret =3D GET_USER_INC(cie_id, cur, entry_end); + if (ret) { + dbg_sec_ehf(cur, "failed to read CIE ID / FDE CIE pointer\n"); + return ret; + } + + if (cie_id =3D=3D EH_FRAME_CIE_ID) { + /* This is a CIE */ + ret =3D __read_cie(sec, entry_start, &cie); + if (ret) { + dbg_sec_ehf(entry_start, "failed to read CIE\n"); + return ret; + } + + } else { + /* This is a FDE */ + ret =3D __read_fde(sec, entry_start, &fde); + if (ret) { + dbg_sec_ehf(entry_start, "failed to read FDE\n"); + return ret; + } + } + + cur =3D entry_end; + } + + return 0; +} + +static int eh_frame_validate_section(struct eh_frame_section *sec) +{ + int ret; + + /* + * Validate .eh_frame_hdr binary search table + * (incl. all referenced FDE and CIE in .eh_frame). + */ + ret =3D eh_frame_validate_eh_frame_hdr(sec); + if (ret) + return ret; + + /* + * Validate .eh_frame CIE and FDE. Skip if linear search + * is disabled, as many .eh_frame sections lack a zero + * terminator and the section end if unknown. + */ + if (IS_ENABLED(CONFIG_EH_FRAME_LINEAR_SEARCH)) { + ret =3D eh_frame_validate_eh_frame(sec); + if (ret) + return ret; + } + + return 0; +} + #else /* !CONFIG_EH_FRAME_VALIDATION */ =20 static int eh_frame_validate_section(struct eh_frame_section *sec) { retur= n 0; } @@ -1266,6 +1425,7 @@ static int eh_frame_read_header(struct eh_frame_secti= on *sec) 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; + bool has_table =3D false; int entry_size; int ret; =20 @@ -1287,16 +1447,17 @@ static int eh_frame_read_header(struct eh_frame_sec= tion *sec) UNSAFE_GET_USER_INC(fde_count_enc, cur, end, Efault); UNSAFE_GET_USER_INC(table_enc, cur, end, Efault); =20 - /* .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, NULL, &cur, end, eh_frame_ptr_enc, &eh_frame_start); if (ret) return ret; =20 + /* Handle binary search table if provided */ + if (fde_count_enc =3D=3D DW_EH_PE_omit || table_enc =3D=3D DW_EH_PE_omit) + goto end; + has_table =3D true; + /* Read FDE count */ ret =3D read_encoded_pointer(sec, NULL, &cur, end, fde_count_enc, &fde_count); @@ -1327,6 +1488,9 @@ static int eh_frame_read_header(struct eh_frame_secti= on *sec) =20 sec->eh_frame_start =3D eh_frame_start; sec->eh_frame_vma_end =3D eh_frame_vma_end; + sec->has_binary_search_table =3D has_table; + if (!has_table) + return 0; sec->binary_search_table_start =3D table_start; sec->binary_search_table_end =3D table_end; sec->binary_search_table_enc =3D table_enc; @@ -1464,6 +1628,7 @@ static void __eh_frame_dup_section(struct eh_frame_se= ction *sec, 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; + sec->has_binary_search_table =3D oldsec->has_binary_search_table; =20 dbg_dup(sec, oldsec); } diff --git a/kernel/unwind/eh_frame_debug.h b/kernel/unwind/eh_frame_debug.h index e72e011ba539..e03fc8bfed86 100644 --- a/kernel/unwind/eh_frame_debug.h +++ b/kernel/unwind/eh_frame_debug.h @@ -17,6 +17,9 @@ #define dbg_sec_ehfh(addr, fmt, ...) \ dbg_sec(".eh_frame_hdr+%#lx: " fmt, ((addr) - sec->eh_frame_hdr_start), #= #__VA_ARGS__) =20 +#define dbg_sec_ehf(addr, fmt, ...) \ + dbg_sec(".eh_frame+%#lx: " fmt, ((addr) - sec->eh_frame_start), ##__VA_AR= GS__) + static inline void dbg_init(struct eh_frame_section *sec) { struct mm_struct *mm =3D current->mm; @@ -57,6 +60,7 @@ static inline void dbg_free(struct eh_frame_section *sec) #define dbg(args...) no_printk(args) #define dbg_sec(args...) no_printk(args) #define dbg_sec_ehfh(args...) no_printk(args) +#define dbg_sec_ehf(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) {} --=20 2.53.0 From nobody Mon Sep 28 18:33:38 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 3D6C73B776D; Tue, 18 Aug 2026 14:50:34 +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=1787064641; cv=none; b=VcB0L8qpA8nxbPD229/nopTj+9tBf6yagYRpJry6h2XaxNUPGYgWgZ2qpQmc9XqueGzZzGMle59KED0gBlJa3CphsoZ16SLm0nXs/SQ+ibDr9/Ca+RNImOHTCX68j30BPqCyDz2PNpzhn9Tdz/2WCrBsw+qXMFlFtzzoiOnNDhw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064641; c=relaxed/simple; bh=Mujhq9PPwuWeYrcXDjr+wrAhWIDWgt09QIXgWZWX9Ig=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tk5oiQbDGjAnmuELU0R+E8Wxdod1d5kcxHpbx0bTKHQ+FJ6bNfJkEnopln+TYkspnaa6jhVhw75JFFLIvNqsE8dddciT3njVLQuyG4iFvS2Z96qkhuPgURUddGp4SvrIPOFLda9ECv1e2NyKLvqkxDlcqLpWFfStj1ADBEozM7s= 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=GoNa/QWy; 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="GoNa/QWy" 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 67IE3Y8U505138; Tue, 18 Aug 2026 14:50:09 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=D0vcBEOOyUGoBu+pm ZMPQX5WLSQAyvRwHJCCq37w9/8=; b=GoNa/QWynkpgP+WOzTG0NuQcD0WKAfVXK J70CuH/e3zfjqBoVsPa/cbjgf8m82jPzUVt0SF9gKuYQK81LxYBaC7dAZlN5rY3S idz2nJUQuZv5u19jSv9gp3TmG9v/KSjGWv6dwY7cS+3kypzPfBh3MeQOlliYHvjg PPpimEs5kjBXR2EAKjexwDV28SHlj0OXBfBV1A7nSAMweP+P9E7fytpJ2G0vtB+J yJN4cq3pKRO5W+H/y5IhldWvBTjQQGPeuPBSOBvvV2F/hk7u9ysztIRdTLpejjuE aaou60f8FuIUk8FtP2XcuI9MNicmjPvBTeow+y1YC4++wqWmUwRCw== 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 4g2fu4rx2p-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +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 67IEfSiI014812; Tue, 18 Aug 2026 14:50:07 GMT Received: from smtprelay07.fra02v.mail.ibm.com ([9.218.2.229]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ek3r7f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:06 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay07.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo2wh51577228 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:02 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B633820040; Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6EA6520043; Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:02 +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 Subject: [RFC PATCH v1 17/25] unwind_user/eh_frame: Ignore DW_CFA_GNU_args_size Date: Tue, 18 Aug 2026 16:49:46 +0200 Message-ID: <20260818144954.2320378-18-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-GUID: SwQbcLL-8v0RRqYKpDrR0IBRTLIR2XoW X-Authority-Analysis: v=2.4 cv=NLLlPU6g c=1 sm=1 tr=0 ts=6a847120 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=U7nrCbtTmkRpXpFmAIza:22 a=VnNF1IyMAAAA:8 a=bNYdn40op4m7Rmrl5ooA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX6ydL08lUhfqB EjVeLJLfCuseowCf9EFYGdH7HJz+Z5F7MCEH9BY/f4K5WNYjhk1/EPOuX2zr8N7v/nTOE0IimhD mMQK/bLUmGOwDVbwv6sZQhUvXr1Viu0= X-Proofpoint-ORIG-GUID: q-1xRGIh6qlvCecDcc-qrIok36DR8wqA X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX5xem2d3GoSHv 8vdSItxff8/kodM96i5JuOkTQYlz8M+0sv31UNAcU4016abpqzO4GXR6Gj+JOqdUdW3Vleyk/it 3Bo3AWMm70lN7HqL7A9vjo+ZXGa+38762lMBThD3dE09z0YeQ2H8QpT/wtfwtAdT3ONMk/ra0TK YDCb6oTcD0wIU0KBe2rLe3MMfiCXz8n9nnoP833stCN84QALFMZ8NQIDswk2tkMqZYbFqsarwor uzZRIIKhSJyX1HnCXnRelib5gn3MagwdIwjtpa3DdcnrTW/jaRxb7ttmdXkmBJCToqja7tBKnOo 2ujdg4/UhbJs5JqfA3Cm8ojYxftRt+4oSu+X2WdhfCDljaolThV0Bc/VKryViDlA7f77K72yaGw a6O7HAvQjwkGdzKstFLh48rRjhIURhxMnnzuCFTeJmKsm/SEBaqtmedmHJj6XYRx+MTyqddCub8 W483aLrJs3hOTuhll+Q== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 spamscore=0 lowpriorityscore=0 phishscore=0 impostorscore=0 malwarescore=0 suspectscore=0 clxscore=1015 adultscore=0 priorityscore=1501 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 ac288cec8021..64176242b7d8 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1012,6 +1012,17 @@ static __always_inline int __do_cfi_insn(struct eh_f= rame_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 18:33:38 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 AB2D030DD10; Tue, 18 Aug 2026 14:50:25 +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=1787064627; cv=none; b=A8gcO5mDtNzRJhzNZjDHACtjkHYB6HhGZKCeHHQd2vmDc+l8XI2/aSENuksjAt28WSQDAnAH2jtR/vgrrt3ogTv8Ewfhum1pqNo5oxAYfXOQ31CgyBAKbQsZwi4u7m1jFklv/m3Md9Ck2YqS9WkfMCPQLlrpWsKACeIaS4fxgHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064627; c=relaxed/simple; bh=VC90WT957RuJBwzw59XGUifCd2WuZNM7egWBYGUnwEw=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sn3iuJ5KolADKguMV/2VB79Rl9vbAzSB6rYttZl5mkwjjzHyrkqQFv9OebgupXysTbLetFsX5DgMyRDZmU1KcAyC1M+i8m8TE2WDvoLcdCW+8tZgMpK9JJWS6/YpzCoNEQn3WrYzvzPhXN9WvhgCkrbWCvAzKXVrD3CwEO1C2qU= 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=m0ZC/bbh; 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="m0ZC/bbh" 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 67IE3bZa3582467; Tue, 18 Aug 2026 14:50:08 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=BpvLWygwKGaH6UwTW knTNvo4Od12Bd4OuLl/hxXL5h8=; b=m0ZC/bbhLLHpUPae8aMAfWXFVTiU3lzgj DoQLwj2SZQwlrPaHJeT1IW2d9F8dbT5NyUfWj4ics9efYkRwSqQbLTTuaqwJqjmN YbuKgvnmfBLqqCVv0YciKc4J+JEfwM+OFm6WJrNdasa+rxLWAfBOpBxRpkel79k6 g7WRn0+bj9T/Kpqwt/94LAoM8v9AAC2cx/7qWD3exCIN3wjcnwEwrQI4DnNaTk9H tOsOyHLxM8JRW2b9xn6pzyrHDan0Ota1OSBVDnnm+xSDHY+tHsATjmeBoeaOBUlp R7lHcnkhjAFnOBlYLTfOVE3rjLVNYhH+rKayKGYjemG6wk1fajUAA== 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 4g2ehe8h14-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +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 67IEfPgp014779; Tue, 18 Aug 2026 14:50:07 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ek3r7g-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:07 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo3Np39584238 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:03 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1838F20043; Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BBA9A2004D; Tue, 18 Aug 2026 14:50:02 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:02 +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 Subject: [RFC PATCH v1 18/25] unwind_user/eh_frame: Add support for DWARF expressions Date: Tue, 18 Aug 2026 16:49:47 +0200 Message-ID: <20260818144954.2320378-19-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX+tmiImle5It7 /e8kTwfxsXdohIt/WvjowMqT3idBxYfC91mOZWSFKhF9g4Shko2X0jTufnT86/2yfrgcP6J234v LYLTpGEXyIf0ZYznJuaujKBzP4yWzl2sALd1kuPEuMYEHvIPULBPzrMzcQq18qTvnAEg3ZFmYk9 ElYNKy6Ayz39qw/vSHY85gcBA3ItcrjgEEEAUFaRbPiP77GQDLuvkseIDuM1DCq4g1JtTfZ4pJR iP3BTX0dDGjl9CgeTsqo2o+/WB+rLWN2L/4B2BuAh7YfOW1Ynycbi+ok2Pwm0955yLmaSc/QQ1u OUI7t4mqytsC0KH0O3mKfZJgiFQjWn9DTkP9yi91jal9VnCCJ6PNbi4yBkqqZGttatJSrklMB1M 88z92Y02chWyNCA8GyVWuWWHworLPnzU0SojVftqZuIOPW46amVi3Yff0KkDHjz5027wkPnL5CU xnuLtJl1JI0UzhM+4mA== X-Authority-Analysis: v=2.4 cv=DY8nbPtW c=1 sm=1 tr=0 ts=6a847120 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=VnNF1IyMAAAA:8 a=CQQWWhfAhHPghX2u-Q4A:9 X-Proofpoint-ORIG-GUID: NM8SFNDVuwQiShy1vP58vaz_KWSS4DiC X-Proofpoint-GUID: 83O2yxdrw8c-6ZqzhCSgH7Vh8YKstR1e X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX2rxd702mVDgh tDRzOizn/aQ+W/or54DH4APT9H62+K26QJiaaDs4c5SOJbzJsq7ogdyOSJzQ5kbIzlqX+1VlCwq S7gomkeWve9PPS15D+wNiFujvxIEAIk= 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 clxscore=1015 spamscore=0 malwarescore=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 --- include/asm-generic/unwind_user_eh_frame.h | 41 +++++++++++++ include/linux/unwind_user_eh_frame_types.h | 37 ++++++++++++ kernel/unwind/eh_frame.c | 70 +++++++++++----------- 3 files changed, 113 insertions(+), 35 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 e6d207597206..da9bc52a645a 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 @@ -10,6 +12,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 8 #endif @@ -39,5 +45,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 64176242b7d8..f7f1234b0437 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]; @@ -839,6 +808,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 > 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; @@ -1005,9 +995,19 @@ static __always_inline int __do_cfi_insn(struct eh_fr= ame_section *sec, if (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 18:33:38 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 2969437E2E9; Tue, 18 Aug 2026 14:50:28 +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=1787064631; cv=none; b=JRiUcRe5Oey3ovar8t5StVwJ44hWJDhsW9afRccpjRscTKA5EKnbiGQHtNOHyj/yEm1vmQA9WwVkd8KHS0Xn8+Ok3JUM1mutGRPC9C3LXm39upN2Q4wyFKpjhZsz1kiw5lI6y0eRUyysbPfJnnDliXpWK0wUYfjUS+HZbMbn4JU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064631; c=relaxed/simple; bh=O0SPzgf2EQOjoZmBiRzcLTE+OD7iWiK8l5BG6BpKfwo=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=GCNW27KIWTXLWTzMt57owHWFAWXwI0twLWpb21ZSpAtp7aw3WPjklZf/wHEUGeSYthFWQfsboVr5OXKphNJYgt3WYErSN5txHi7TtElyxF9ZWNZd9gKuv7kkT8pR2dRzmS0S2wmZJZco77WD9h7wxItGY+dGWYxDUxAFnaH76c4= 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=bYSfc0vk; 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="bYSfc0vk" 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 67IE3c0H542431; Tue, 18 Aug 2026 14:50:09 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=bYSfc0vkPvZ2L/cfRxPp2IVPtQ4uofmNG S5u+d2+OXjE1HWbusrZDiIzh4WBBl0SCU1LTk2hlwy5aXXMkC7fIdx5s5CJrtnu4 SaZBH9BewkZQwMIr/TcIxwEcZxYxVnBcxrGsN+ddQzM2N2n5sYYEI3bYwZbQEocT wKea2pf9c3JF6Xk5VsXEalUx5RKn5WvnmeLxKJPLukge6Iv6xX0k82jwnQYGKvuu FVkXsH9ieN9CEVvE2+MktHs9egN6LCoxrzZyOiUuNfp1XLbiLBnVXGf71icKLPp8 xrut6DtUS4T4SD4UU1Cv1VoDlV8oXHg6a65OTBpIlAMAYWtBLtDTg== 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 4g2frt8btb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +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 67IEfVQE000623; Tue, 18 Aug 2026 14:50:07 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354ybgcb-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:07 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo3Am39584240 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:03 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 67BF220043; Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1DD7E20040; Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:03 +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 , "Steven Rostedt (Google)" Subject: [RFC PATCH v1 19/25] x86/uaccess: Add unsafe_copy_from_user() implementation Date: Tue, 18 Aug 2026 16:49:48 +0200 Message-ID: <20260818144954.2320378-20-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a847120 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-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXwmU4yKF0+OXq +A02kxUYSb4lnoEDiQ/pvHHDdGdHG66SaD+SMoXkdMxAhyYZs5ytG5FL9WFIPKMiwtp/4sA+MPJ K7xwMOph/kRAaJaAmoJjNpkK4pye57I= X-Proofpoint-GUID: zdvb4IvzeITmmDxRy40CtXkrrQhGM4CG X-Proofpoint-ORIG-GUID: QCBfe5MbYwNLOeXWuc-HVAIQVt0I2CQg X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX7sXD/w4YTy5X s7uQdKx8k7xfGYXGyrYaX9gfOT+hj6cyIsJ22ioZlu6Vlia9LLyz15ubW85KovnrjO3mbN68hfD i933NOgrS6wtR6AeZO4v+ZN4w+cbLSIZ0b5ZXPq01XTG0WuPgLsbELGFg6v8KRTqLVzNFiYsruV nUV8WiKpx01RViFbSQqEIDHB/WzRZsdEwuWJFpuFoOnAQE1jtyPVEK5oiNQ4cMpjWdyu+m/zC8Z S/Yy9lc71wNbKUtLL1jH21hNff0oZW77BaBrMF/jNFCB8BiUmTKHuUkNFYcwqqoY7bSXEbbDLkD PJ9DGiJB+wJP3CDPS+g1qQNiaRRi94rkCVNVWfoTWaOVgVWTtZ0TQJQo/f+ZIR+CgEk1XUVOsuN NdNc9tDV/d3au0Ra81lwkRCkpFoJozhs6aFBkEuH0OTeiArEr1mQkpZQ+/T+J5aTQKftw64mt61 X0KYbuph/XYbYftJ68g== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 A6689332614; Tue, 18 Aug 2026 14:50:31 +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=1787064637; cv=none; b=BKJwmzzzraDiKpHVmniBNis5L/NvoStr/ffy4cxnRfB6BGLeGVjiQDSVD3n9OfgweuFMJI2S8406v4af5QINY1S397Jh/vVChwjKmGP0poPu2bjIR5TUcYPvN+P/dkTi2JlQRYuX+ldmOaOdFGqqHlJ9pjJwcpxA/RM9L5bBLLM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064637; c=relaxed/simple; bh=TgiT8Xnhc5VLifuhTHbl67ng/yIBp4wlIbp5EtKoKcg=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Bg8A5L8I5xctox8G8GXrXM9FhN/Q1ano5t9tGwjpEMIbiVtZlGiGQoLlpl+JBsmkX9+VVTRK3jIH9my6HmntCJ9SWtwgrVMaoL1JkdYKRzT8LVFNpwyLwlVjXL2wOsw/U27P0exuTDgBctgY4zRRKo34gRtLSOKTPW9lJKLJCn0= 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=EJWfh785; 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="EJWfh785" 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 67IE3q5E401906; Tue, 18 Aug 2026 14:50: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=Y+mdTmXPgPz0paNvu 3GnRv+WInnbZ0GCjERerrKsAso=; b=EJWfh785Gl9SgiQr7AwbltrX+doRbU/fR LwsRK0IV1N3UOqxq3fJkJ7ne9fVj2nE7BAdanqP4c2koPZa/chLx6OJJUVREu3vv cQJhaYsCd+a+zq7/E8JHERC+V0SbKP1y+Qqz6+YFSp2Lh83HhZtEoYsuIyU3b0rD pQ9fc8Jz5IlMeHSyO+WjYShRjKnsxhhw9dBhL+eb75ZpFU0FycdDj0bpOWDTcjcZ sq4KrpBXQh+voEMzF7AWXOpyrONKmTh6dBfFKIgkEXvHrbp6OjBUhnqsdDlBzF/9 GMFIxh386YTT86+bq+5OcSAYpiYjrLyjD3Sjdkrps+XAOFWZ2iHWw== 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 4g2dhm0qp6-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:13 +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 67IEfOdH014762; Tue, 18 Aug 2026 14:50:12 GMT Received: from smtprelay05.fra02v.mail.ibm.com ([9.218.2.225]) by ppma21.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33ek3r87-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:12 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay05.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo3tT39584242 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:03 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B5EBE20040; Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6D6362004B; Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:03 +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 Subject: [RFC PATCH v1 20/25] unwind_user/eh_frame/x86: Enable eh_frame unwinding on x86 Date: Tue, 18 Aug 2026 16:49:49 +0200 Message-ID: <20260818144954.2320378-21-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX1d8kHklq4oDh qR4gu3EKLxIH2H6af2/tFoGatTv0RSz3dUC6OGuPybXidi/6OguOOpI1qUmpEf+omNupfqXwVV1 m0njASuR8qu1Tzx0isUw0inKwarDPbTPyO80owWXYfwEacJ4wiFcS9mOvYRqeBkgf4ol3PFtg0H nw/YV+TenMASA0/ULS0uCECLbYW/UPZP8wbzEahyFIld3N1FLOuivkxdtTpIblhhDDMjgrMt08w 4m5STs49i4l4nrZ6tZgZaXRV6rke0/kbPrbwY5vlQpDLV73IApD4E17R4anpZlEAKHPray8bKO1 DEyq0KUm9tkx95jpud9s3FqJl2DxdZSlRrG9GDiZnsrzVdr9us4M4wumAjrzU/1b+8vFdv8f5QZ 2XJ4/9D/NV2mbqfOlFx+UeMoi3InQLA3A5+82Ifg+SFS25b84RG9uE6y9T6gbFKCeTOvuKjQneJ pochYYMmYYf/CgHTGlA== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX4dlFwffqua8d 36q2ijmGmJcp32QgX0E0svsuYGUKF4+TARoYPZ9NgqjLj+zJ67kyJVrqWJqYMwn7bbvk4iVygO5 PXvc5nznVBl9532iN6qOm4wCxUlSO4M= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a847125 cx=c_pps a=GFwsV6G8L6GxiO2Y/PsHdQ==:117 a=GFwsV6G8L6GxiO2Y/PsHdQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=Y2IxJ9c9Rs8Kov3niI8_:22 a=VnNF1IyMAAAA:8 a=TKDeGWYlhpvMKGhGT-EA:9 X-Proofpoint-ORIG-GUID: s2pENtJPPp-RNFhBqfL1gEj1gc3OogDn X-Proofpoint-GUID: iZq1MtKPvsvjYKRpHGf-XAOdce5efOHG 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 E56123563F6; Tue, 18 Aug 2026 14:50:30 +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=1787064637; cv=none; b=bUmiIGGPnruc7GAF+JX7TLtqDIt08hyhhX+PA1g4OJEskbopb2I8Ra2f88nq/PoOeeQAL7+XLyFIJ9WS7WUjSZaXODAjJwSROuK4AbX1QTAz2UUIOhA38bi5Hwdj6c9rOxPLFqa5C8K2jioMpA6IXsPv1QPwnnAsVjhrxw0iH90= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064637; c=relaxed/simple; bh=+3LbHmTaeyb9n65LFUSmthJYJBpc+xFIA7hCLqaX+40=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=m37MybOlsgENfbMwJpj5bWt0KUsDaU6jOExTC1bvHD78SLS5YH0M/+ZkqhKX9KMQu1A/wldrghqGGuH67aD4HqRdNyc/fgPJm/Sf/Ophag7ctohkic5Ui2J2vVWnW7OOXKp22742ePmXKqADP7bjD1ZtQl2Kw2pi2vLv0othkAc= 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=Y30Iuvcj; 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="Y30Iuvcj" 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 67IE3nu4401804; Tue, 18 Aug 2026 14:50:09 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=NT/BD775Wlwof0KfO Q/x5DI3MH/iSW4t2nY68gCIbmE=; b=Y30IuvcjHDY6l9vUeIIJh/QQeBVdSs0GT NOjgO4UEbsaP9rSDR9JATQmVNjbSFomfnrnkYW1mEtl0yzaJTsaKas4QKNNilirq +YBK5fGTG8Oq3MzUMWy9vhzqryZLuJagb6Gwiv6umLlf3bIgqI+livUG4yEDa+EL 7yqEJBVwQ48nI22mBgfdvAL5R9mcpJK2ZT+8vzJJ21mw9finrMNW6oLzRbNcHo2F nyBtJksP9Tgu30EsG8tHdR81Z2HxbqU3q/tnJeXtcilXefUYFRlU83AVMTWgo83A Poc3UKn0sV3HslaU2cLh0z1iHVq6j4XyZ0ISo8pUaeg35nyq6i52w== 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 4g2dhm0qne-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:09 +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 67IEfLn7025396; Tue, 18 Aug 2026 14:50:08 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma23.wdc07v.mail.ibm.com (PPS) with ESMTPS id 4g33xh3q5v-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo4Kp27590916 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:04 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 0E9FF2004B; Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BB95620043; Tue, 18 Aug 2026 14:50:03 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:03 +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 Subject: [RFC PATCH v1 21/25] unwind_user/eh_frame/x86: Handle PLT expressions Date: Tue, 18 Aug 2026 16:49:50 +0200 Message-ID: <20260818144954.2320378-22-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX0PVimwSiMcw9 7uWyQkImJx+Wfv/Zko1T8ixGd+SipU3Psv1s1k4FrD3nVcjzsKbyayc3hl4Q11pFPPmtcGL5cj9 iFtxStFtTcdwvtlewK2XppgLOEx02pEIfvbZinp0Om+E5PzrP3YLXwLpxzvWZtt94rwOdp8jmju BuWE5U0TtGRVQW3uLJ5Xk0RLkqLy07qBP8g8DLqAjJVqkIVIBhXYeirkzb8d2+zCkqRKX8o4MyI x9G+vSUjVEKQTukDuAndhVXUp7brg8p+nIqbul2On10MueGzBKBW7x0RxxSmCekagJzUKHTti/G FMxsXtglGE0hyN0FnPCaDAKGc2nYI7w2ggx+YHXdYqWDSAacoSK6HNCiL147DX2SKLPGaIEBrXw cWY8iolHtxHn8uXBUBvOPKsCOp/rRvGmeKFkuvNP3m+6sd+PIl2DAzQw4k2w9tafzyED3azMdQX Zj2Ec298uwJnFAMyqeQ== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX1g1FFITT/DtX S4gLcYs/5SnVsoqfWWWSZtP+c02ovmyx1FMy+UXnz/kmeLPVVGkMVo+7qOcqVTdB/2U0WAlUPja ygCeN1P0YaKnHEFelxwWsp/7aNitBws= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a847121 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=lN3RThuQUzBg4E8S6xQA:9 X-Proofpoint-ORIG-GUID: 4txUEljCoj9PvnfGh3eitMbOegyMWkbU X-Proofpoint-GUID: Fg1UZj_EHgcAEC7mvEYUNKHIPkm15sia 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 f7f1234b0437..19e2bc96ddbc 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 18:33:38 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 53166473C96; Tue, 18 Aug 2026 14:50:40 +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=1787064644; cv=none; b=KGJkIw/CJ5xxwAqYSIVF4K0LzS6AZf4ZskQEjAo40fYPQvTiuMY0b3cIxNDuXo/UXVFxNzx9jpLlPhyqUGCbrMPO9w0+M/GVXOylfCUgHbceg5Xrm3nXj+pyx+zNp1wmwUeEiSqvVZB3TfXHk3qwIICrt9e4Rpm+iCLg2/i8buQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064644; c=relaxed/simple; bh=afu24jH0sWWbgxeRigYWVfRJowKKSgx1IkkKxjAfxp8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=DC/iOuiZaGLQvMNaswJvlSLem7nCh87cTjEE2WMhFNbYuzMLsb4Vn44G3PXS+dz82EV23VFB8pWewwe8+VWdNqBVC+/TOoW1/Nk/xovLuZIGXPVUXVesVqV9F1OHgyySCIwvUAKddPzwxoLvJeVM19rDZiBoGu+OkGNHUmBQ9J0= 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=QXgPdgZc; 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="QXgPdgZc" 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 67IE3emL542458; Tue, 18 Aug 2026 14:50: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=trqYxbRZC1GE+GBw0 4BAIlb5GAbXbEmvr0rCES1W8EM=; b=QXgPdgZcLT41YvNbvAES00LSQZwShYX3Y sP7lQbOgxhXdqwiCTQ5zjCzqf859iCZ2GBztJKJQdlM/IW6HOd+gS5BbKgn5I7P+ P0pEaORze57RC4IOiabwNEwmKdOrq69R9agL2NoIyIoOE2TNDX0OJ6dDFJNrGjd2 FUuzdv/ZzBfaD+8WH2uIVB91gT5PueUFDDAFEhhVM4JBC3FGW4ggaHtB3wZR/xIe WDQJ2Ol8qVUHYE6ucckICUIPd3CS3bjAGsAE6/HCNypk1Htf/QdyYJHvazIZTP7K YSg24C8reGJqzWu/T5OHvTru4dbOxndhQArfQyCx5xQnW1UrdIFKQ== 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 4g2frt8btj-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:09 +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 67IEfIRj032411; Tue, 18 Aug 2026 14:50:08 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma11.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g354ybgch-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo4Ds27590918 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:04 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 650C22004B; Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 144652004D; Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:04 +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 Subject: [RFC PATCH v1 22/25] unwind_user/eh_frame/x86: Handle DRAP expressions Date: Tue, 18 Aug 2026 16:49:51 +0200 Message-ID: <20260818144954.2320378-23-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a847121 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=VnNF1IyMAAAA:8 a=CAsaE8RiOkJQvnkcRxMA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXwMlI6J5YNSJf keo8VDSIyZMezkdaQxf9nHT137R7w7biRm0XGYofsd0C3rNGikZiC7bdZeG4j936qxwdulNvQwG t5sI1fzKjRnONetq4PYj/bULdEjfYiI= X-Proofpoint-GUID: sCeSAK8Xmfdb5zoF9XMtps2esQF0FcnV X-Proofpoint-ORIG-GUID: 2pbdLbsdkSudkokjWPPKIUtu8cGvk_vC X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX0fq23L5yxkCN Q3xNg2pRaS9uK82v0iD9bh7oEYsOcu8s2OR7MyOkLB/Aa81UUHnYqwnMQXjcEJAVvGuPrydRLwR Csfno/qHFRsT/lyQPAcNpUvMFUwRtIdJQjyg3YtT34mtpwTVjqPxsWxETAf8r6jvxSf5xq9G9H+ bVMvmkQjOuiFnGOytw8iSml+w118pnX3vv0QAtGEkKUo2ulU4aUw6doKqmi7naCv67IJSG8D976 rLfaAJNv9dCk1tzPumIDsuqtvWi1uuR+P0mOpIHT9Jw9f41ziJEagN4HKSrG74amYjZvD0N26Y6 3sBsrlPCgMcmT32+fvCQoqnFFixv70VMqqcH15fmHsjTcrmQxlp/BxqWWAnPCENb3kZEdopJKcj B0XzSJIF/BttEIZDSHBw5ITMyLfFwl50hrAuF8j3EkA0uIELGq+xCIVSGuVoDQByK0fR/TFh90N R+6K9YX8HzSRS6tffXQ== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 19e2bc96ddbc..49e8a3e8d794 100644 --- a/kernel/unwind/eh_frame.c +++ b/kernel/unwind/eh_frame.c @@ -1120,18 +1120,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 || @@ -1172,6 +1187,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; } @@ -1206,6 +1231,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 18:33:38 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 C680938B7D9; Tue, 18 Aug 2026 14:50:29 +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=1787064635; cv=none; b=YLiG7e/KlwofXaUefzJL1RlJtXtevP+rajH87E6inLKWXxeBXUg6AwPyCQ9dCEKqp9WR6/RvOiYeYyZgkbuqE4DNBA/9LvMItQhl3TeIldTeNXyDKIFC832omCeqAWYsAcrGyG5Pp0NemYpUVeo/skWyexOeEAE0uTVL+2fwVDc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064635; c=relaxed/simple; bh=QWiO/oVjltZVMmCOotSP7wKcIueRwp06oxRRGGodGAs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lRyXqXj+i+4urjIHeyO5rA9YX3aZSLrlIIoHedSMbnyiTu0ZW/WwD1yO1Apby2X1cxDGQxpel9fe/9AmTO3Eylf95qGCeE+0XjYck0HbvnOQfIWkol5apkTD9UjpAy0fVqz5UtYCFBbvhftk7xJNDXzbceYHwPXVq6yA408BGu4= 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=Ykx/QzoM; 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="Ykx/QzoM" 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 67IE3oCJ401813; Tue, 18 Aug 2026 14:50: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=Y+euVRI6M/Fa6YfSr 8B9MiMOGuuw4vVLdiMUtQIZdas=; b=Ykx/QzoMkTXoNNmvcg3oUw2mpBYPf8enx 0UPFuRpI9lPZgHgXT84ndz+l0DBuTI7CCqHH5bxIWcO2tDVXxU8w590NHaqUsqEO hp4FF9oHzyZY1Rmoszo8F/MCrN5YNg7OfW3Atds5ykqfrEYbXbWVF6fewqIbGUjW 93ErUoc3Ls4zCAyyvd+HWkBZG7rQ3dFr30NMqEevgTR45LQ+Lp59khMhi1xVl4Yt WCytzi108MookoehKFU0BjAmeLGPXbiHbz1B5nPVMZx+uJqL7VfCeo7SFYAY3nn7 9XV4P+WqBJxVE9ASqyCIwatY7fXufr2pMPy48wnjn8ND9DVqIEPKA== 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 4g2dhm0qng-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:09 +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 67IEfKdp005462; Tue, 18 Aug 2026 14:50:08 GMT Received: from smtprelay06.fra02v.mail.ibm.com ([9.218.2.230]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eq3w4b-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay06.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo4RT47317476 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:04 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id BBF7C20043; Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6B0CC2004E; Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:04 +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 Subject: [RFC PATCH v1 23/25] s390/ptrace: Provide frame_pointer() Date: Tue, 18 Aug 2026 16:49:52 +0200 Message-ID: <20260818144954.2320378-24-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX+UXG7ZvKiwxT YH4ZZnBFA/zfTx7Y0FoYRFxuOBghkJkKAgvL9PxAD7e/nM59WaFaAcBEcunR95NKzFdFeqnvJiz QYiO2opTMZTB267fDe2btwD7j4yZDeBto4MXaSe5RPHdSV9BFsaBY4Z/Bjif89ZuluBdoUybs8S whF3y96eLZVlcbQUTcVHCaZJ14O1aX00B17Y8ExrTQw0ywoOKTTnqS84eC+LyUD5sY17pRzZ1Lr oZmTvj83uId8pxjWBvLNTicamsFf7dQaaOYOB91Aj62Llnr8JTDnNyUZ+kz9OlP6tE3QVC5vSiP qC3atWpT3RcfPRL2vIgM/3EO9dSQE3OFj8ICd5RVUnYQ9J+YKrbSF25ecm8Npw6SNiopa7sGcl5 uWy8QldFSIGCV7fq+3ziJRvzzZR+Ef85kKQ7Z3in8ZSfX1gnI7HGWogEzNR48ATwx6a8tvZrMgZ wkrTtRmJqhrSNDWoLLg== X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXztlaixwly7Xw 8ICfhstMuf/XBRkTOenWnhp50g5T4xHyltik5j5OZIM4nP3IK1RylGEK7w1eWj4Ocf5Y25Q+gwA 7zY4mOY4EglWxgUzbVTUGnv06PtiJ7c= X-Authority-Analysis: v=2.4 cv=JKkLdcKb c=1 sm=1 tr=0 ts=6a847121 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=NEAV23lmAAAA:8 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=_uadzYZ_BUT95G4SQMEA:9 X-Proofpoint-ORIG-GUID: J0cydBPEqobJU7znXVoBFXy7bmr0rvK9 X-Proofpoint-GUID: GNqhp0ySPe9BgUf1URAWsMhu9AkWXpKZ 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 bulkscore=0 malwarescore=0 priorityscore=1501 lowpriorityscore=0 clxscore=1015 adultscore=0 impostorscore=0 spamscore=0 phishscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 23FC83AAF43; Tue, 18 Aug 2026 14:50:28 +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=1787064630; cv=none; b=UKaRoyjGNrFEmxSjR0utuMK9Y7GrHVLHwyYWju/6wGALBDVEcEgiPovElZFH/hFxgwxfzVgrcl7xEzNzNBunc6g496xf0/QvxPczWSmd+38Y4+uAXlFJkE5FJ6zEazv2oG4lhlTvj+NesEFOl2/BsRi/tNSGVUqRSaiOJx4+UeU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064630; c=relaxed/simple; bh=ZWia27gK5Uu/rA6TzDzSSPKWN0bclHUCBb817crgoGA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=KgpH7Nzusv0c6Ax5068YDDWQx1IrjEUpC7tSG5rUkk+Vl333lJHnzsrnsto8B0F8jYuriHmFktrRW2VZEKpxd4EL8aUT8/FRPFQ0S1E+ulGcM1wzbOH21TjGNcYE/oZdF0WGl/FtCX3p75wD9Lf8H7Vqwp1qwy4Q4VcQ11pTUSs= 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=fLzk5d3h; 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="fLzk5d3h" 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 67IE3arh542405; Tue, 18 Aug 2026 14:50: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=UBQVMEerwR6B6Lb2m WCr+ZIf4sr/j5+4uJyDzFTYLIY=; b=fLzk5d3h9isQomVDAC7VTCrCX0SUbjrST DAkN/rqW45iSzWHEOpHhEZ/5qjA3VE+xcPDdI1+32nSglA3zpCDpTbiVs09jcMHU d/0yxysOcmsi0Xd0APmWqa4Z4hvFol7+l5/3FTKyXjUCayYsFzJMZHxTFJwZd4qI euztiMIpoa2t3GsyUEX+0a6c0h5bPmbhjK8WS+kpPXzbuKNt3QuUhlT0Xprp60TZ ug9N3QMHP+DDmwR3vcI1lTd65is3KPFmsaNi7OFzQOYjwb0xWpO0X1QDi0V9pZHx Vs7+fuU2HvscltWk09qRmqgjtQx3aspkKn9rp6lkam3PaoBO8+siA== 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 4g2frt8btk-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:09 +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 67IEfKdr005462; Tue, 18 Aug 2026 14:50:08 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma12.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g32eq3w4f-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:08 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo5nI45154698 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:05 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1574520043; Tue, 18 Aug 2026 14:50:05 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id C25E62004B; Tue, 18 Aug 2026 14:50:04 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50:04 +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 Subject: [RFC PATCH v1 24/25] unwind_user/eh_frame/s390: Enable eh_frame unwinding on s390 Date: Tue, 18 Aug 2026 16:49:53 +0200 Message-ID: <20260818144954.2320378-25-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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=OfaoyBTY c=1 sm=1 tr=0 ts=6a847122 cx=c_pps a=bLidbwmWQ0KltjZqbj+ezA==:117 a=bLidbwmWQ0KltjZqbj+ezA==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=RzCfie-kr_QcCd8fBx8p:22 a=VnNF1IyMAAAA:8 a=FmDO2REWYRq66Aip4RwA:9 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX5wVjcZ0xyjdM Lzy7ax1kAVWP3PXDqlOSto11EEVdaGp2Li6i5BBDDZKKDxWjsGtJSKjMxmWhd1N5cvJMxxajgRo 6ntVi8LspUC021Vw3bwtSNX9zL/21Pk= X-Proofpoint-GUID: IgMRSTd4jJA23VIoVhSwaq_Zm3bcp6WG X-Proofpoint-ORIG-GUID: a7c6cSCLn8_yDAVAlxdP3rutPXgUXNHD X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXzMyUJrO2E1W+ UYWKkXpaX66boNbxMAkgjmYKyZu4yA+ZPrr7nDT29A18CdgOOAmXC6bIUP/TUv6VFADZn4sqyZu G2s9ZVgNYqhC3Qm7oy85PvAXCDvXT8M21X6HRhivzmScoxoK/Wb6xci+CufWtuiBBJ0q6qDu4fy LZqgzxh2936fz1aP2aSOLcjSSkhrrjPjg5NDX7AxYBigETiWhhhACFpqiUqKcjSu2VqUJvQq+Sw 9EVFp9mjT9v5rnaQAeNyG7e3lPx+SXBn1Vvmd1vw+bcKnqsTu9graPpQCplgGaTdW2L7KJ0TQof Q7BhVzRroYVamuxv05qGy4gbRqSo+GBvMVXZPdZSa0NuQaqd3E1tXDlucXdwE92FtKEVIc3VTft 7D3eCFUR2xvzABqcpArrqhrIzSeiY2/GoHXVLye1uf0/HyxrX2qeB9BeUaKD42D4ePmvEP0MO4I TBappzOV5viuwLnsYqQ== 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 adultscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 malwarescore=0 bulkscore=0 phishscore=0 priorityscore=1501 spamscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 18:33:38 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 8699E18A6CF; Tue, 18 Aug 2026 14:50:27 +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=1787064629; cv=none; b=sfOVsvmlkiGTIWYvzv27G4ZK2B8JIlabLCVyO6+Kf1FbfqUtlkWiIgDNblVhW6WRfaj95kV4q7VuJtNDA7NKWxGag9NKatP1n9rL5Lijv+hKGhNFM6UxUvO2gJ/C5DPh+yk9CbqqaoFvnbmjCdNC34WcyfTg0NOZnfbtZsP1vTg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787064629; c=relaxed/simple; bh=ryN6HnGgUODfo2mkcg4yfPMF8eu56ctIAsET4LUnJQY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=tNjuO6ILhY8VxuW6qeyikrbMshdnRkOqGjGJvdktHpfSMsebjiCKdtxOe91aw+jVbaegTA57arpfxROPtKJf0CchF0xjxteILpV5SOtpQJ2EqD1TWeXojWuwH4L8vnrlbr6G3PyB8F0RjUn/0WjUAc9A4LJxB2qC+0LqLbJrueQ= 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=nQv+dwXg; 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="nQv+dwXg" 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 67IE3bZb3582467; Tue, 18 Aug 2026 14:50: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=5yHdQpnMEHW0fRNxr xSFOGMVWC51H5fYvAkW31goDsw=; b=nQv+dwXg8JfwEtXMaFkTlWkjjzK07/42q gUNW2QNTWaWmQQfFcW05LLgv45oRaJcGS1kVG99munw9DXdiHuQWyo3kQ3HokJaA nZOlatGVfXiSxze2u+KspW6tZyi/XusiVvW1TubH5NjeMmqILao9JSh+iGNTx59u B7PZQlunMnF/Qv2WzBQ3Qk+ZULOmctWfE9qPG+jXX4IYgnvA/DEcQNsGCNY4TF/B 0wQZoaxPMcrxhTlG83zv4USWRENNvHYUtB+Llv3CO+MllsbmZyYXGXGzbunobPuF UvoCvfN5oUmzBkQ5Tief3PCKyUjYR4OLjgR1Mi5UnmX3o+SRgtnwg== 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 4g2ehe8h1d-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50: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 67IEfQpw029654; Tue, 18 Aug 2026 14:50:09 GMT Received: from smtprelay01.fra02v.mail.ibm.com ([9.218.2.227]) by ppma13.dal12v.mail.ibm.com (PPS) with ESMTPS id 4g34ngbhh3-1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=NOT); Tue, 18 Aug 2026 14:50:09 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (smtpav05.fra02v.mail.ibm.com [10.20.54.104]) by smtprelay01.fra02v.mail.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id 67IEo5Tj45154704 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK); Tue, 18 Aug 2026 14:50:05 GMT Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 6F4F120043; Tue, 18 Aug 2026 14:50:05 +0000 (GMT) Received: from smtpav05.fra02v.mail.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 1B6BD2004D; Tue, 18 Aug 2026 14:50:05 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.87.85.9]) by smtpav05.fra02v.mail.ibm.com (Postfix) with ESMTP; Tue, 18 Aug 2026 14:50: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 Subject: [RFC PATCH v1 25/25] unwind_user/eh_frame: Add prctl() interface for (un)registering .eh_frame_hdr sections Date: Tue, 18 Aug 2026 16:49:54 +0200 Message-ID: <20260818144954.2320378-26-jremus@linux.ibm.com> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260818144954.2320378-1-jremus@linux.ibm.com> References: <20260818144954.2320378-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-Details-Enc: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfX2OBKpR2bYxD+ OW9bmZ7wnqLgPuavr4I4saTZGXCP5j5mrvshJuc3tf5rVI+nXfTPnJSgAA/ZMGFvDE62j0izU05 ewwdqAubJ67R8T1cnNO3EpS4zLE00fjkTUZfHEre+amNMDifsTg/JUd0Y3Jb7BzdWaukI6WDQYP /I29lTd+8/WlQ05SgyKuJamMEt8EvqohQZXDFZ1G2UwuAoZ5NW6tKRhHmMk0geePfj23tTOWLsQ m5l0YwVQq/cmdsQWSXabjOA26el1kkguHoDOBWrjxu1/N2vBdfbBGP0erxOm2Tr/VvI/JyqE+Z8 /kjFfVeIDe3kdoFAs8sF8Qj9DkQwHtn41WRDxMDf88nfYSkCrdNuYkJg60TZI5kVa0Zd5FivMUZ 2sS+Ds94eqcLaso/iVA92LJjQcs9llKIWcvoW6ZZJ/r1kgLWCREyLXnfNEZ6UgLanbDNzEWAAc7 Lwn8DGJl0gu7hIMzfJA== X-Authority-Analysis: v=2.4 cv=DY8nbPtW c=1 sm=1 tr=0 ts=6a847122 cx=c_pps a=AfN7/Ok6k8XGzOShvHwTGQ==:117 a=AfN7/Ok6k8XGzOShvHwTGQ==:17 a=Sv0fKeRqtYgA:10 a=VkNPw1HP01LnGYTKEx00:22 a=RnoormkPH1_aCDwRdu11:22 a=V8glGbnc2Ofi9Qvn3v5h:22 a=VwQbUJbxAAAA:8 a=VnNF1IyMAAAA:8 a=PpU6TSaerSOHJBOlBi4A:9 X-Proofpoint-ORIG-GUID: sA1KAGVjdsh62MYRpLS8y9zWQ5oTrGOh X-Proofpoint-GUID: BHYhF3RH_AEPxDiqnC0BXWMCOYuZpnR1 X-Proofpoint-Spam-Info: AW1haW4tMjYwODE4MDEwNyBTYWx0ZWRfXx8hwRDwFS+so fRjGyI4opnptunebSKCv1W41eoCXb3cm880vLzT1TMcL2pEUM5Aw+9REKFB3Ax8X6qjicOMZ074 u/mwofvxuZy8WOlmmgWIbuvUetq3Fco= 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-18_02,2026-08-18_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 bulkscore=0 clxscore=1015 spamscore=0 malwarescore=0 priorityscore=1501 impostorscore=0 lowpriorityscore=0 phishscore=0 suspectscore=0 adultscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2608180107 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 --- 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 de68f21e1050..540beab5bf61 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 { @@ -39,6 +41,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) @@ -77,6 +85,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 49e8a3e8d794..12279f02381d 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" @@ -1723,3 +1724,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