From patchwork Thu Oct 10 12:55:41 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yury Khrustalev X-Patchwork-Id: 1995439 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=arm.com header.i=@arm.com header.a=rsa-sha256 header.s=selector1 header.b=e1kTwwKI; dkim=pass (1024-bit key) header.d=arm.com header.i=@arm.com header.a=rsa-sha256 header.s=selector1 header.b=e1kTwwKI; dkim-atps=neutral Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=8.43.85.97; helo=server2.sourceware.org; envelope-from=libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org; receiver=patchwork.ozlabs.org) Received: from server2.sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (secp384r1) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4XPVBY4qXfz1xsc for ; Thu, 10 Oct 2024 23:56:37 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D1CF9385701E for ; Thu, 10 Oct 2024 12:56:35 +0000 (GMT) X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from EUR05-VI1-obe.outbound.protection.outlook.com (mail-vi1eur05on2071.outbound.protection.outlook.com [40.107.21.71]) by sourceware.org (Postfix) with ESMTPS id 6B9283857BB9 for ; Thu, 10 Oct 2024 12:56:12 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 6B9283857BB9 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=arm.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 6B9283857BB9 Authentication-Results: server2.sourceware.org; arc=pass smtp.remote-ip=40.107.21.71 ARC-Seal: i=3; a=rsa-sha256; d=sourceware.org; s=key; t=1728564977; cv=pass; b=EnqLbinOs82uC05BqNNuQt+B/JwfV9rlCqw1iS5fSv4FCuxho9eMyOmba32TGKvueEBFHozHhKSgccybt4zcZekGdKmMG1fQUaXierarWtqJoJUoSGknyKcK+12cB/oF90S2sebcfioYOpzH3zEWUnZRfOaCNLtF3LD1nyoNguQ= ARC-Message-Signature: i=3; a=rsa-sha256; d=sourceware.org; s=key; t=1728564977; c=relaxed/simple; bh=cmaLp3eBCtCEB038qi2JbyYE9n/VqFWOaGx8dWt7x38=; h=DKIM-Signature:DKIM-Signature:From:To:Subject:Date:Message-ID: MIME-Version; b=s8JWPP8XrxfCRah88mRxoEwY19Y8VgBy0QL1XNviaSwgMv76Ad2lo2DZx/Y4sWjVQsetzmDaqpVHdbahaO/AUjWVXOXAb4vpIgc+sotK1TGn1ZGBxRAh8i8rAMNVNyPwGIcd/E6VGOXf2sgpkWYVGFtypn31YxLPO8CiP/dYLmE= ARC-Authentication-Results: i=3; server2.sourceware.org ARC-Seal: i=2; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=pass; b=q1wix5TQ+HfqqYvAxBylFR0zVCSCQdzL32ScjHF45xIExYVo8vxghivFNS5/Dr/FjSclyhj2u174TFuq7Q0y16gf1ESCC+d5aM+oa/HWkOwUdH19ffb16+HmbaIEB5iD5zYLfW0ly3aeApvN7Loq9sAWsXJ5zqkxebTFLimerazebc9HhEqMxaPhoXMQlev+UngChY3w7HI62co4YbuwGQFWl+RK6fqnIX2O+aT0zzkfVOMRzmG/fiRwHdqAsFBXRK8zSoKvOFvZ3fYH4GSBW93V9RhPPh7SFLsAUVOVi3zmuf7GKmsYsRzO8nMMvaHI3VuvVaqdurHT/gJdhkxL1A== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=FxId95+P9veYF8egaZBcf+1JyFkkWjzBqCAk4m7rLHs=; b=Te0Us3umQQba7rQwJNxRnAeFtICbDTToy9m1KLIMjlzh3e/FxxC/kGgxoOriLZJwiPSu8Krhm9uTiq3iwkU6XnuzTEM8S+n6bH3FDJ3Zk2S1Jw3PlX3qXQNuibcNIdnpAv5PKaczZPII6OvyghV4MoY+Gmk0P8e3qaYVcVpRRPW3pe0th1ViVKzoKALpJk5YTNz/6R4W/MLksSjv84ZOcwlIHYEScEySCQf9P3iiFISX7ZcV2qSs+8fwCKP7fgAPdOal9CdgxLalWVOfJcHs+x7XuMAMdkt0JfgDr/kjXL69fMS4pb9j3eaF+u5Rf4X1Ccv+7TyZOC5LJu3i3DkHAw== ARC-Authentication-Results: i=2; mx.microsoft.com 1; spf=pass (sender ip is 63.35.35.123) smtp.rcpttodomain=sourceware.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=pass (signature was verified) header.d=arm.com; arc=pass (0 oda=1 ltdi=1 spf=[1,1,smtp.mailfrom=arm.com] dmarc=[1,1,header.from=arm.com]) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arm.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=FxId95+P9veYF8egaZBcf+1JyFkkWjzBqCAk4m7rLHs=; b=e1kTwwKIWahtERtUa99Yml0Ck4UnDUw6uoTofyMIldNUnXr40QAr3mq2wztw3b2qFC9zdEFwSBXu1VOUC2m2irOz345HhI8bxf585omKrLGGcjPQZrOY7ZIvewbJYcPtG6hKlLsvKoHig7qHYTrkgugK4+JDSC4UEny85P93Kbg= Received: from AS9PR06CA0468.eurprd06.prod.outlook.com (2603:10a6:20b:49a::23) by AS2PR08MB8408.eurprd08.prod.outlook.com (2603:10a6:20b:55b::5) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8026.23; Thu, 10 Oct 2024 12:56:03 +0000 Received: from AM1PEPF000252E1.eurprd07.prod.outlook.com (2603:10a6:20b:49a:cafe::d4) by AS9PR06CA0468.outlook.office365.com (2603:10a6:20b:49a::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7828.22 via Frontend Transport; Thu, 10 Oct 2024 12:56:03 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 63.35.35.123) smtp.mailfrom=arm.com; dkim=pass (signature was verified) header.d=arm.com;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 63.35.35.123 as permitted sender) receiver=protection.outlook.com; client-ip=63.35.35.123; helo=64aa7808-outbound-1.mta.getcheckrecipient.com; pr=C Received: from 64aa7808-outbound-1.mta.getcheckrecipient.com (63.35.35.123) by AM1PEPF000252E1.mail.protection.outlook.com (10.167.16.59) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.8048.13 via Frontend Transport; Thu, 10 Oct 2024 12:56:02 +0000 Received: ("Tessian outbound 6c9d48238f96:v473"); Thu, 10 Oct 2024 12:56:02 +0000 X-CheckRecipientChecked: true X-CR-MTA-CID: 951780037d59ab5d X-TessianGatewayMetadata: UN4zsyB8hUmxq0fJiMNc5wfffAgfHmgzjdQsFQQ5GQWaBEs9ykmW00GXJJxFirZ0/q68jY31FfDRV31KPgmTbxYRUB+EagnkSvxu7l00M8LkThIc8N0Ou3F5Ctwa+98b1TEHB1KiOlik0O9NZF+l8fLQgAzn4jF8NYKg+DBICqE= X-CR-MTA-TID: 64aa7808 Received: from L87a023eaa67b.1 by 64aa7808-outbound-1.mta.getcheckrecipient.com id F33E61DE-5BCD-4254-AACB-DA03B8C09159.1; Thu, 10 Oct 2024 12:55:56 +0000 Received: from EUR05-VI1-obe.outbound.protection.outlook.com by 64aa7808-outbound-1.mta.getcheckrecipient.com with ESMTPS id L87a023eaa67b.1 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384); Thu, 10 Oct 2024 12:55:56 +0000 ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=hk0sJXE2fvOuDhlhEVkPgZdPiSQC9KgpwvywRxeHxaP05X4UBTXFqW14nfxXm35t02cdvsG87pwh/atjHfAgGWivY+y4mWQw+4ED+J1ZiOUkV95m+5msyzeV6see+XPNjftZlM+OGLOvYuLdLr6UZgio/LgYV9vrCRrSRSwL2Utg7FBNMxnE8VnwXMVxqRON02QuxC6N/cX81kGagZYahy9o7p2pF4TbaZkdXkBxOMLE3AL3IWQw5or4ryb5HCf6Pu1ovUvruiUcLQHMGPTrH2t1xWe2D26MpKHNkfEdetnvnqQKkkM9EaHKfUn1B85IS0yWBKExvvACT4LDrjZyAw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=FxId95+P9veYF8egaZBcf+1JyFkkWjzBqCAk4m7rLHs=; b=uNAE0t9Lj7POG4sZEUglHFEAn1eEUTNqnKlwETk3I+kZHCmQKRJASwJ40HH7AoCoLsglImuT5d8Y/UK+YAclOf/yY3PKXcSDbFUKOhYfm5ZQUM1i/Wq2vxkU9QcxskCaHUrorLGdR75qP+Mqv/xIBVH/X06YZmR3V5bpBFzLlGEiI+enFCLzjdmKIJ8AOgCJx+ER+OyBloiOBQSg8hsIpjSQ1ZG+9xrP/R/RwN/9WZjgZgdbkw57PcJUWM642uEzQwGYNtFy0ATnAYvrSuxdETxMoWGIzW9kDn/FmMzhLShKbpl5B94YFyx5SvcIvYCCfmNFnL93yZPMbDszkCfoNQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 40.67.248.234) smtp.rcpttodomain=sourceware.org smtp.mailfrom=arm.com; dmarc=pass (p=none sp=none pct=100) action=none header.from=arm.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=arm.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=FxId95+P9veYF8egaZBcf+1JyFkkWjzBqCAk4m7rLHs=; b=e1kTwwKIWahtERtUa99Yml0Ck4UnDUw6uoTofyMIldNUnXr40QAr3mq2wztw3b2qFC9zdEFwSBXu1VOUC2m2irOz345HhI8bxf585omKrLGGcjPQZrOY7ZIvewbJYcPtG6hKlLsvKoHig7qHYTrkgugK4+JDSC4UEny85P93Kbg= Received: from AS4PR10CA0013.EURPRD10.PROD.OUTLOOK.COM (2603:10a6:20b:5dc::20) by VI0PR08MB10510.eurprd08.prod.outlook.com (2603:10a6:800:201::15) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8048.16; Thu, 10 Oct 2024 12:55:51 +0000 Received: from AM2PEPF0001C712.eurprd05.prod.outlook.com (2603:10a6:20b:5dc:cafe::ed) by AS4PR10CA0013.outlook.office365.com (2603:10a6:20b:5dc::20) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8048.18 via Frontend Transport; Thu, 10 Oct 2024 12:55:51 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 40.67.248.234) smtp.mailfrom=arm.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=arm.com; Received-SPF: Pass (protection.outlook.com: domain of arm.com designates 40.67.248.234 as permitted sender) receiver=protection.outlook.com; client-ip=40.67.248.234; helo=nebula.arm.com; pr=C Received: from nebula.arm.com (40.67.248.234) by AM2PEPF0001C712.mail.protection.outlook.com (10.167.16.182) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.20.7918.13 via Frontend Transport; Thu, 10 Oct 2024 12:55:50 +0000 Received: from AZ-NEU-EXJ01.Arm.com (10.240.25.132) by AZ-NEU-EX04.Arm.com (10.251.24.32) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Thu, 10 Oct 2024 12:55:50 +0000 Received: from AZ-NEU-EX04.Arm.com (10.251.24.32) by AZ-NEU-EXJ01.Arm.com (10.240.25.132) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Thu, 10 Oct 2024 12:55:49 +0000 Received: from udebian.localdomain (10.1.26.166) by mail.arm.com (10.251.24.32) with Microsoft SMTP Server id 15.1.2507.39 via Frontend Transport; Thu, 10 Oct 2024 12:55:48 +0000 From: Yury Khrustalev To: CC: , , , , , Szabolcs Nagy Subject: [PATCH v4] aarch64: Add support for memory protection keys Date: Thu, 10 Oct 2024 13:55:41 +0100 Message-ID: <20241010125541.354067-1-yury.khrustalev@arm.com> X-Mailer: git-send-email 2.39.5 MIME-Version: 1.0 X-EOPAttributedMessage: 1 X-MS-TrafficTypeDiagnostic: AM2PEPF0001C712:EE_|VI0PR08MB10510:EE_|AM1PEPF000252E1:EE_|AS2PR08MB8408:EE_ X-MS-Office365-Filtering-Correlation-Id: 826236d1-c545-43af-014e-08dce92ae5a6 x-checkrecipientrouted: true NoDisclaimer: true X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam-Untrusted: BCL:0; ARA:13230040|1800799024|376014|36860700013|82310400026; X-Microsoft-Antispam-Message-Info-Original: yoEFd+ajhwZ3266EXkf2VZYTRY3hV3oq4ATL3QaVV8MGUQ9xEQ2Ig+SyWgT1nkA+lGGm7Jpnr0YYBzTaq9xSV7VmGsYNNC4S/5PCg3Qe/c+n3UBhMsGOUuShTwS5pPbtROjsNMhIiOMK+oANV0N1CzElbko1hLzMWsg3kRARAOjTL5V7kOGTwSLsZsqyHUGmIkyHLy7SmqHlZcPlu7RG74Y/OoE3xmuJ2UMZ4SJQLVuIftnKqiBdKNI1etKW5PMHYZBVb0EsRflMCoCiR9OjAlv3VidSVnURKdICJYoAOiuxT9EHOCh+St6dEEaoI6gXhBu+cu2UJxShFFWR0KceST2KOyqaO7vQ0GO47FgludGyn+xGQTIBgylPAOkSF2mZ21laZlibfkFAn0Isy9e4bHO2x5HV0zy8dTach1h30Z8BPEw4pteYfGI6+9P8HwCePoa4cikxqS7LNJTEW7l8+u7/Dc/hBbT6wTL/1TLPtK4ZKGh6nwkE3u3CHYRKJEwv68Z1x+4d2/J5uo0mN8K5WM24ufEYT0Y2Dp2v+RWIq0CgXksM3FOkFG27t1pkWNf0AKxcl7ZIFoiure/b9rN+x4gUBCBgxLeYoMCIFVAeybxohANSYzAv5YBVajg2IOUn1+9tewL3gQqaFEWplRWhcRG0/6TCsQezZx6aG+tHvXUACodZ7eH/xvU3OCwBb1bMk7u7Hl15/YCvXfcOfevKLI7hOTBFAMbQ1KfNKJmwFLfXy2LzPeQSifnMhkAD0VbmY84277Ccl5qqlUV37/v78MTUFFYij8L2DSte9LfvD4V4lK3fFaXG75A9vTDGL3PrURzF/YUY2iAqNJFP2X6DXd5gjN/4TCgjs4g+5c/vppZUAIiTsXe6aLc1qgkBZIYQBKh4MQXx+yayqulZnuG8xW9EDKMG1nHnl+NgXJkbPTV+1mIIV5/NdGwOhbmrpCzslMaDSSuARlErF7Fmnlz18RamO43qjEV51c46kCzZhLqG8HaeKZ1PS/78duPmsZpA7HKTG1EGsVxQEl6FISRC5PpDBVh/9nECmeIVoeMkFNXe4q9c/y08koVr3xPFal5B9t3LJXg0Vo2NxAQGOBU3SqQZpq+N8C1no0DFL1Ixx5ewVpeQc0PNd+xtgqYC5DV35znTYqLIyo45IFP9KgkxwPXAHNYvg3XLEYhuqq8S6EyMecN9CD3xrYx1HzTakN6XP/b/5R1DFL7E0/qBCZ3Uv9LAQJynia4zpCnC3UlwamwyO1z6VIwIU8RDom2mjjoIQzvT6Nct+BUyzZEkiqmEgQ2pd70Mbrsj/bIh0nqS6aum9DfkTS3A7oycwaWP75bWscZnh9PWsQp2Me3uWT+PrlpkpVDvHwhWdPC+ZdWXD/YEcfj7ZlEW/971yYUsWLLw X-Forefront-Antispam-Report-Untrusted: CIP:40.67.248.234; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:nebula.arm.com; PTR:InfoDomainNonexistent; CAT:NONE; SFS:(13230040)(1800799024)(376014)(36860700013)(82310400026); DIR:OUT; SFP:1101; X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI0PR08MB10510 X-MS-Exchange-SkipListedInternetSender: ip=[2603:10a6:20b:5dc::20]; domain=AS4PR10CA0013.EURPRD10.PROD.OUTLOOK.COM X-MS-Exchange-Transport-CrossTenantHeadersStripped: AM1PEPF000252E1.eurprd07.prod.outlook.com X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id-Prvs: cf129eb2-67c9-46df-934e-08dce92ade76 X-Microsoft-Antispam: BCL:0; ARA:13230040|35042699022|376014|1800799024|36860700013|82310400026; X-Microsoft-Antispam-Message-Info: Rd67o+X6ITSh1y9nLhtfG/PdWT0UqDFk31g963/uQ8WFJcCfOFJyZPVru2x188LD2smpgxYCz35lqG7k1fD2yCHZa48yt/Y0Cam3W9w1/MCLdIMTwOaJHoAU6KTzOLkO+fg3Hf8opLC15V+TgD1wits8JCOKi3cazFBEgl3ndvrBH/L+9pH7jHPoIYULYfRknM+oDFgQG2Y1cIv3pXUfYvhcO4HBqiYdvWK+n70xW6yavLc3focJemW6qag/eOAHNKzhkzJFtN3k5lN2aE8zH2M9SAVxpUvXlUGc9BgFdncjcJNw5L7gD350idmpIK/yJ5slhxVAOn5DyZEjuOkCqD2g9SfPRLofqtlKfLVe80v11FV2FHsAU/d3L5u+3bzWaIyxiO0FJ8gZbz3r31LPVqUK0qdNzqzjlIGeqwD6V93yldzTai9EAFaG0aYgaFqawVWlwkqTO+vp5cVEWX107VTn+/bR4yOM8ZrLv6lFpHXobTuwpmwbBlsFrGDu43dSGEc+rkaaC51ChFm2KqKHJV5tSytPKHL8JbPzN6bJNW4DTuEswSJWRiw8iBoWtpM+F3a7JuOJ/da4tj51psBmDsCwZwLbzmTIm2GooYpwC3LQ9x5evrFQtrhHsxWagaaxYdLUw1JHfJkHJA/GgyIC7+QSPyU5sU6AhxEUXGrgo9KyfZvPx0307m2ckw7jxDLz+LHOXndedlPpPGrOnTYhR7FT3ETuWe6GX0IOOWKhXrSN1JUglH1xSVXPUh8QlEmyUk5HA7/7dFe49t/oqBLJezS74PPGw+C+tz3iUkDofqiKTNaEeJUbP+W+QAr1fUcKpbbv5rboLoKMgPU5PrAt3ug6vzD3HKFYE5GJ0fPGyoCGU8TW8/whKVv6y2qajDRD8mXPPXXxhBpyxLla/JK0dJ/zEVi/gbTTWQX61C6O0nGQrJMysreRviyVQxUuWNTVeCbkunrnxO2JbxtVc9wyw54Kn8DjhOND0jacjCV1x+GZqFDGR2t1NvfIEkXZyOHRFA+YYBKemr62CX8w7/LJEiIWyJZVuFz9ytiAimQSsUunly7G2zIj9qHLvFnQMMF2ivhEoqcbj2t9RNVx8DqBLQr2ZpYc1RF453wdTcUGT6qCqsGsn4wVG/QdAkFWcOASGmpmwTfLrKNla+dY5JX4OHHRqzkzDgBpuKw5rMXePiJcOQa2BYCdvYKth1SpgH0BTUJLeiYNMsMJ8Yvc7B+KFuqyPenlkUF/eleqE5BIhy8mHkyItwnheMUa5gBVo//gC334QgtgYgbFRuQytZo4IEAfkE7mUqhRb34pwekDboQF/xnZnnpseByGaMQiG+ku6e/gvSMppV/C37rTpo+M1ppxBf3Zcza+b1wgjYv3hJfCj4rqed31pigi/l8DEJqc X-Forefront-Antispam-Report: CIP:63.35.35.123; CTRY:IE; LANG:en; SCL:1; SRV:; IPV:CAL; SFV:NSPM; H:64aa7808-outbound-1.mta.getcheckrecipient.com; PTR:ec2-63-35-35-123.eu-west-1.compute.amazonaws.com; CAT:NONE; SFS:(13230040)(35042699022)(376014)(1800799024)(36860700013)(82310400026); DIR:OUT; SFP:1101; X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 10 Oct 2024 12:56:02.9746 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 826236d1-c545-43af-014e-08dce92ae5a6 X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=f34e5979-57d9-4aaa-ad4d-b122a662184d; Ip=[63.35.35.123]; Helo=[64aa7808-outbound-1.mta.getcheckrecipient.com] X-MS-Exchange-CrossTenant-AuthSource: AM1PEPF000252E1.eurprd07.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS2PR08MB8408 X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FORGED_SPF_HELO, GIT_PATCH_0, KAM_SHORT, RCVD_IN_MSPIKE_H2, SPF_HELO_PASS, SPF_NONE, TXREP, UNPARSEABLE_RELAY autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~incoming=patchwork.ozlabs.org@sourceware.org This patch adds support for memory protection keys on AArch64 targets where it can be implemented by hardware with enabled Permission Overlay Extension introduced in Armv8.9 / Armv9.4 [1]. 1. Internal functions "pkey_read" and "pkey_write" to access data associated with memory protection keys. 2. Implementation of API functions "pkey_get" and "pkey_set" for the AArch64 target. 3. AArch64-specific PKEY flags for READ and EXECUTE (see below). 4. New target-specific test that checks behaviour of pkeys on AArch64 targets. 5. This patch also extends existing generic test for pkeys. 6. HWCAP constant for Permission Overlay Extension feature. To support more accurate mapping of underlying permissions to the PKEY flags, we introduce additional AArch64-specific flags. The full list of flags is: - PKEY_UNRESTRICTED: 0x0 (for completeness) - PKEY_DISABLE_ACCESS: 0x1 (existing flag) - PKEY_DISABLE_WRITE: 0x2 (existing flag) - PKEY_DISABLE_EXECUTE: 0x4 (new flag, AArch64 specific) - PKEY_DISABLE_READ: 0x8 (new flag, AArch64 specific) The problem here is that PKEY_DISABLE_ACCESS has unusual semantics as it overlaps with existing PKEY_DISABLE_WRITE and new PKEY_DISABLE_READ. For this reason mapping between permission bits RWX and "restrictions" bits awxr (a for disable access, etc) becomes complicated: - PKEY_DISABLE_ACCESS disables both R and W - PKEY_DISABLE_{WRITE,READ} disables W and R respectively - PKEY_DISABLE_EXECUTE disables X Combinations like the one below are accepted although they are redundant: - PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE Reverse mapping tries to retain backward compatibility and ORs PKEY_DISABLE_ACCESS whenever both flags PKEY_DISABLE_READ and PKEY_DISABLE_WRITE would be present. This will break code that compares pkey_get output with == instead of using bitwise operations. The latter is more correct since PKEY_* constants are essentially bit flags. It should be noted that PKEY_DISABLE_ACCESS does not prevent execution. Co-authored-by: Szabolcs Nagy [1] DDI 0487K.a Arm Architecture Reference Manual for A-profile architecture --- This patch is intended to work with and has been tested on a model using Linux kernel from linux-next [2] (any next/ branch starting with next/20240924). Support for this was added in b9b9d72de32bcb63ed4d9761907a3e5f352c6f9a (available in linux-next). Changes in v4: - Updated documentation for pkey_set and pkey_get - The rights argument in the pkey_alloc() and pkey_set() renamed to restrictions - Some of the PKEY_* flags combinations were resulting in error, fixed now - Fixed code style issues as per [3] Link to v3: https://inbox.sourceware.org/libc-alpha/20240926121315.20096-1-yury.khrustalev@arm.com/ Since I've added changes to the generic test "misc/tst-pkey" that runs on several targets, I've tested this change on aarch64-linux-gnu and x86_64-linux-gnu using native build and on the following targets using cross-build (build-many-glibcs.py): - aarch64_be-linux-gnu - arm-linux-gnueabi - armeb-linux-gnueabi - arm-linux-gnueabihf - armeb-linux-gnueabihf - powerpc-linux-gnu - powerpc64-linux-gnu - x86_64-linux-gnu and no regressions have been found. OK for trunk? [2] https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git [3] https://inbox.sourceware.org/libc-alpha/e62999fe-83c2-4954-b6d5-6b0e4fd9d405@linaro.org/ --- manual/memory.texi | 40 ++-- sysdeps/unix/sysv/linux/aarch64/Makefile | 3 + sysdeps/unix/sysv/linux/aarch64/arch-pkey.h | 53 +++++ sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h | 1 + sysdeps/unix/sysv/linux/aarch64/bits/mman.h | 8 + sysdeps/unix/sysv/linux/aarch64/pkey_get.c | 73 +++++++ sysdeps/unix/sysv/linux/aarch64/pkey_set.c | 113 +++++++++++ .../sysv/linux/aarch64/tst-aarch64-pkey.c | 181 ++++++++++++++++++ sysdeps/unix/sysv/linux/bits/mman-shared.h | 9 +- sysdeps/unix/sysv/linux/pkey_set.c | 2 +- sysdeps/unix/sysv/linux/tst-pkey.c | 57 ++++-- 11 files changed, 510 insertions(+), 30 deletions(-) create mode 100644 sysdeps/unix/sysv/linux/aarch64/arch-pkey.h create mode 100644 sysdeps/unix/sysv/linux/aarch64/pkey_get.c create mode 100644 sysdeps/unix/sysv/linux/aarch64/pkey_set.c create mode 100644 sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c diff --git a/manual/memory.texi b/manual/memory.texi index 3710d7ec66..c16181d166 100644 --- a/manual/memory.texi +++ b/manual/memory.texi @@ -3166,7 +3166,7 @@ context switch, so it is more efficient. @standards{Linux, sys/mman.h} @safety{@prelim{}@mtsafe{}@assafe{}@acunsafe{@acucorrupt{}}} Allocate a new protection key. The @var{flags} argument is reserved and -must be zero. The @var{restrictions} argument specifies access rights +must be zero. The @var{restrictions} argument specifies access restrictions which are applied to the current thread (as if with @code{pkey_set} below). Access rights of other threads are not changed. @@ -3251,16 +3251,22 @@ not @math{-1}. @end table @end deftypefun -@deftypefun int pkey_set (int @var{key}, unsigned int @var{rights}) +@deftypefun int pkey_set (int @var{key}, unsigned int @var{restrictions}) @standards{Linux, sys/mman.h} @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} -Change the access rights of the current thread for memory pages with the -protection key @var{key} to @var{rights}. If @var{rights} is zero, no -additional access restrictions on top of the page protection flags are -applied. Otherwise, @var{rights} is a combination of the following -flags: +Change the access restrictions of the current thread for memory pages with the +protection key @var{key} to @var{restrictions}. If @var{restrictions} is +@code{PKEY_UNRESTRICTED} (zero), no additional access restrictions on top of +the page protection flags are applied. Otherwise, @var{restrictions} is a +combination of the following flags: @vtable @code +@item PKEY_DISABLE_READ +@standards{Linux, sys/mman.h} +Subsequent attempts to read from memory with the specified protection +key will fault. At present only AArch64 platforms with enabled Permission +Overlay Extension support this type of restriction. + @item PKEY_DISABLE_WRITE @standards{Linux, sys/mman.h} Subsequent attempts to write to memory with the specified protection @@ -3269,7 +3275,15 @@ key will fault. @item PKEY_DISABLE_ACCESS @standards{Linux, sys/mman.h} Subsequent attempts to write to or read from memory with the specified -protection key will fault. +protection key will fault. On AArch64 platforms with enabled Permission +Overlay Extension this restriction value has the same effect as combination +of @code{PKEY_DISABLE_READ} and @code{PKEY_DISABLE_WRITE}. + +@item PKEY_DISABLE_EXECUTE +@standards{Linux, sys/mman.h} +Subsequent attempts to execute from memory with the specified protection +key will fault. At present only AArch64 platforms with enabled Permission +Overlay Extension support this type of restriction. @end vtable Operations not specified as flags are not restricted. In particular, @@ -3291,17 +3305,21 @@ function: @table @code @item EINVAL The system does not support the access rights restrictions expressed in -the @var{rights} argument. +the @var{restrictions} argument. @end table @end deftypefun @deftypefun int pkey_get (int @var{key}) @standards{Linux, sys/mman.h} @safety{@prelim{}@mtsafe{}@assafe{}@acsafe{}} -Return the access rights of the current thread for memory pages with -protection key @var{key}. The return value is zero or a combination of +Return the access rights restrictions of the current thread for memory pages +with protection key @var{key}. The return value is zero or a combination of the @code{PKEY_DISABLE_}* flags; see the @code{pkey_set} function. +The returned value should be checked for presence or absence of specific flags +using bitwise operations. Comparing the returned value with any of the flags +or their combination using equals will almost certainly fail. + Calling the @code{pkey_get} function with a protection key which was not allocated by @code{pkey_alloc} results in undefined behavior. This means that calling this function on systems which do not support memory diff --git a/sysdeps/unix/sysv/linux/aarch64/Makefile b/sysdeps/unix/sysv/linux/aarch64/Makefile index 40b9a2e5de..1fdad67fae 100644 --- a/sysdeps/unix/sysv/linux/aarch64/Makefile +++ b/sysdeps/unix/sysv/linux/aarch64/Makefile @@ -1,5 +1,8 @@ ifeq ($(subdir),misc) sysdep_headers += sys/elf.h +tests += \ + tst-aarch64-pkey \ + # tests endif ifeq ($(subdir),stdlib) diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-pkey.h b/sysdeps/unix/sysv/linux/aarch64/arch-pkey.h new file mode 100644 index 0000000000..270dd9bd96 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/arch-pkey.h @@ -0,0 +1,53 @@ +/* Helper functions for manipulating memory protection keys. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#ifndef _ARCH_PKEY_H +#define _ARCH_PKEY_H + +#include + +#define S1POE_PERM_NO_ACCESS 0b0000UL +#define S1POE_PERM_R 0b0001UL +#define S1POE_PERM_X 0b0010UL +#define S1POE_PERM_RX 0b0011UL +#define S1POE_PERM_W 0b0100UL +#define S1POE_PERM_RW 0b0101UL +#define S1POE_PERM_WX 0b0110UL +#define S1POE_PERM_RWX 0b0111UL + +#define S1POE_PERM_MASK 0b1111UL + +#define S1POE_BITS_PER_POI 4UL + +/* Return the value of the POR_EL0 register. */ +static __always_inline unsigned long +pkey_read (void) +{ + unsigned long r; + __asm__ volatile ("mrs %0, s3_3_c10_c2_4" : "=r" (r)); + return r; +} + +/* Overwrite the POR_EL0 register with VALUE. */ +static __always_inline void +pkey_write (unsigned long value) +{ + __asm__ volatile ("msr s3_3_c10_c2_4, %0" : : "r" (value)); +} + +#endif /* _ARCH_PKEY_H */ diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h b/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h index 8dceaa1a52..2fa158fcc0 100644 --- a/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h +++ b/sysdeps/unix/sysv/linux/aarch64/bits/hwcap.h @@ -118,3 +118,4 @@ #define HWCAP2_SME_SF8FMA (1UL << 60) #define HWCAP2_SME_SF8DP4 (1UL << 61) #define HWCAP2_SME_SF8DP2 (1UL << 62) +#define HWCAP2_POE (1UL << 63) diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/mman.h b/sysdeps/unix/sysv/linux/aarch64/bits/mman.h index c5b6c69d43..288dff064b 100644 --- a/sysdeps/unix/sysv/linux/aarch64/bits/mman.h +++ b/sysdeps/unix/sysv/linux/aarch64/bits/mman.h @@ -26,6 +26,14 @@ #define PROT_BTI 0x10 #define PROT_MTE 0x20 +#ifdef __USE_GNU +# define PKEY_UNRESTRICTED 0x0 +# define PKEY_DISABLE_ACCESS 0x1 +# define PKEY_DISABLE_WRITE 0x2 +# define PKEY_DISABLE_EXECUTE 0x4 +# define PKEY_DISABLE_READ 0x8 +#endif + #include /* Include generic Linux declarations. */ diff --git a/sysdeps/unix/sysv/linux/aarch64/pkey_get.c b/sysdeps/unix/sysv/linux/aarch64/pkey_get.c new file mode 100644 index 0000000000..6875bdd177 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/pkey_get.c @@ -0,0 +1,73 @@ +/* Reading the per-thread memory protection key, AArch64 version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +int +pkey_get (int key) +{ + if (key < 0 || key > 15) + { + __set_errno (EINVAL); + return -1; + } + unsigned long int por_el0 = pkey_read (); + unsigned long int perm = (por_el0 >> (S1POE_BITS_PER_POI * key)) + & S1POE_PERM_MASK; + + /* The following mapping between POR permission bits (4 bits) + and PKEY flags is supported: + + -WXR POR to PKEY_ mapping + 0000 => DISABLE_ACCESS | DISABLE_READ | DISABLE_WRITE | DISABLE_EXECUTE + 0001 => DISABLE_WRITE | DISABLE_EXECUTE (read-only) + 0010 => DISABLE_ACCESS | DISABLE_READ | DISABLE_WRITE (execute-only) + 0011 => DISABLE_WRITE (read-execute) + 0100 => DISABLE_READ | DISABLE_EXECUTE (write-only) + 0101 => DISABLE_EXECUTE (read-write) + 0110 => DISABLE_READ (execute-write) + 0111 => UNRESTRICTED (no restrictions, read-write-execute) + else => undefined behavior + + Note that pkey_set and pkey_alloc would only set these specific + values. The PKEY_DISABLE_ACCESS flag is redundant as it implies + PKEY_DISABLE_READ | PKEY_DISABLE_WRITE but is kept for backward + compatibility. */ + + if (perm == S1POE_PERM_NO_ACCESS) + return PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE + | PKEY_DISABLE_READ; + if (perm == S1POE_PERM_R) + return PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE; + if (perm == S1POE_PERM_X) + return PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE; + if (perm == S1POE_PERM_RX) + return PKEY_DISABLE_WRITE; + if (perm == S1POE_PERM_W) + return PKEY_DISABLE_READ | PKEY_DISABLE_EXECUTE; + if (perm == S1POE_PERM_RW) + return PKEY_DISABLE_EXECUTE; + if (perm == S1POE_PERM_WX) + return PKEY_DISABLE_READ; + if (perm == S1POE_PERM_RWX) + return PKEY_UNRESTRICTED; + + return PKEY_DISABLE_ACCESS; // undefined behavior +} diff --git a/sysdeps/unix/sysv/linux/aarch64/pkey_set.c b/sysdeps/unix/sysv/linux/aarch64/pkey_set.c new file mode 100644 index 0000000000..12161127a4 --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/pkey_set.c @@ -0,0 +1,113 @@ +/* Changing the per-thread memory protection key, AArch64 version. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include + +#define MAX_PKEY_RIGHTS (PKEY_DISABLE_ACCESS | \ + PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE | PKEY_DISABLE_READ) + +int +pkey_set (int key, unsigned int restrictions) +{ + if (key < 0 || key > 15 || restrictions > MAX_PKEY_RIGHTS) + { + __set_errno (EINVAL); + return -1; + } + unsigned long mask = S1POE_PERM_MASK << (S1POE_BITS_PER_POI * key); + unsigned long por_el0 = pkey_read (); + unsigned long perm; + + /* POR ot PKEY mapping: -WXR + PKEY_UNRESTRICTED => 0111 (read-write-execute) + PKEY_DISABLE_ACCESS => removes R and W access + PKEY_DISABLE_READ => removes R access + PKEY_DISABLE_WRITE => removes W access + PKEY_DISABLE_EXECUTE => removes X access + + Either of PKEY_DISABLE_ACCESS or PKEY_DISABLE_READ removes R access. + Either of PKEY_DISABLE_ACCESS or PKEY_DISABLE_WRITE removes W access. + Using PKEY_DISABLE_ACCESS along with only one of PKEY_DISABLE_READ or + PKEY_DISABLE_WRITE is considered to be in error. + + Furthermore, for avoidance of doubt: + + PKEY flags Permissions + rxwa -WXR + 1111 => 0000 S1POE_PERM_NO_ACCESS + 1110 => 0000 S1POE_PERM_NO_ACCESS + 1101 => EINVAL + 1100 => 0100 S1POE_PERM_W + 1011 => 0010 S1POE_PERM_X + 1010 => 0010 S1POE_PERM_X + 1001 => EINVAL + 1000 => 0110 S1POE_PERM_WX + 0111 => EINVAL + 0110 => 0001 S1POE_PERM_R + 0101 => 0000 S1POE_PERM_NO_ACCESS + 0100 => 0101 S1POE_PERM_RW + 0011 => EINVAL + 0010 => 0011 S1POE_PERM_RX + 0001 => 0010 S1POE_PERM_X + 0000 => 0111 S1POE_PERM_RWX */ + switch (restrictions) + { + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + | PKEY_DISABLE_EXECUTE: + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_EXECUTE: + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_EXECUTE: + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE: + case PKEY_DISABLE_READ | PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE: + perm = S1POE_PERM_NO_ACCESS; + break; + case PKEY_DISABLE_READ | PKEY_DISABLE_EXECUTE: + perm = S1POE_PERM_W; + break; + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ: + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE: + case PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE: + case PKEY_DISABLE_READ | PKEY_DISABLE_WRITE: + case PKEY_DISABLE_ACCESS: + perm = S1POE_PERM_X; + break; + case PKEY_DISABLE_READ: + perm = S1POE_PERM_WX; + break; + case PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE: + perm = S1POE_PERM_R; + break; + case PKEY_DISABLE_EXECUTE: + perm = S1POE_PERM_RW; + break; + case PKEY_DISABLE_WRITE: + perm = S1POE_PERM_RX; + break; + case PKEY_UNRESTRICTED: + perm = S1POE_PERM_RWX; + break; + default: + __set_errno (EINVAL); + return -1; + } + + por_el0 = (por_el0 & ~mask) | (perm << (S1POE_BITS_PER_POI * key)); + pkey_write (por_el0); + return 0; +} diff --git a/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c b/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c new file mode 100644 index 0000000000..8b77a28c8f --- /dev/null +++ b/sysdeps/unix/sysv/linux/aarch64/tst-aarch64-pkey.c @@ -0,0 +1,181 @@ +/* AArch64 tests for memory protection keys. + Copyright (C) 2024 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static sig_atomic_t sigusr1_handler_ran; +static int pkey; + +/* On AArch64 access is revoked during signal handling for + pkey > 0 because POR is reset to the default value 0x7. */ +static void +sigusr1_handler (int signum) +{ + TEST_COMPARE (signum, SIGUSR1); + TEST_COMPARE (pkey_get (pkey) & PKEY_DISABLE_ACCESS, PKEY_DISABLE_ACCESS); + TEST_COMPARE (pkey_get (pkey) & PKEY_DISABLE_READ, PKEY_DISABLE_READ); + TEST_COMPARE (pkey_get (pkey) & PKEY_DISABLE_WRITE, PKEY_DISABLE_WRITE); + TEST_COMPARE (pkey_get (pkey) & PKEY_DISABLE_EXECUTE, PKEY_DISABLE_EXECUTE); + sigusr1_handler_ran += 1; +} + +static int +do_test (void) +{ + pkey = pkey_alloc (0, PKEY_UNRESTRICTED); + if (pkey < 0) + { + if (errno == ENOSYS || errno == EINVAL) + FAIL_UNSUPPORTED + ("kernel or CPU does not support memory protection keys"); + FAIL_EXIT1 ("pkey_alloc: %m"); + } + + long int pagesize = xsysconf (_SC_PAGESIZE); + + int *page = xmmap (NULL, pagesize, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, + -1); + pkey = pkey_alloc (0, PKEY_UNRESTRICTED); + + /* On AArch64 pkey == 0 is reserved and should never be allocated. */ + TEST_VERIFY (pkey > 0); + TEST_COMPARE (pkey_get(pkey), PKEY_UNRESTRICTED); + + /* Check that access is revoked during signal handling + with initial rights being set to no restrictions. */ + TEST_COMPARE (pkey_mprotect ((void *) page, pagesize, PROT_READ + | PROT_WRITE, pkey), 0); + xsignal (SIGUSR1, &sigusr1_handler); + xraise (SIGUSR1); + xsignal (SIGUSR1, SIG_DFL); + TEST_COMPARE (sigusr1_handler_ran, 1); + + /* Check that access is revoked during signal handling + with initial rights being set to PKEY_DISABLE_WRITE. */ + TEST_COMPARE (pkey_set (pkey, PKEY_DISABLE_WRITE), 0); + xsignal (SIGUSR1, &sigusr1_handler); + xraise (SIGUSR1); + xsignal (SIGUSR1, SIG_DFL); + TEST_COMPARE (sigusr1_handler_ran, 2); + + /* Check that all combinations of PKEY flags used in pkey_set + result in consistent values obtained via pkey_get. + Note that whenever flags PKEY_DISABLE_READ and PKEY_DISABLE_WRITE + are set, the PKEY_DISABLE_ACCESS is also set. */ + unsigned int rrs[][2] = { + { + PKEY_UNRESTRICTED, // restriction being set + PKEY_UNRESTRICTED // expected restriction + }, + { + PKEY_DISABLE_ACCESS, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + }, + { + PKEY_DISABLE_WRITE, + PKEY_DISABLE_WRITE + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + }, + { + PKEY_DISABLE_EXECUTE, + PKEY_DISABLE_EXECUTE + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_EXECUTE, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + | PKEY_DISABLE_EXECUTE + }, + { + PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE, + PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + | PKEY_DISABLE_EXECUTE + }, + { + PKEY_DISABLE_READ, + PKEY_DISABLE_READ + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + }, + { + PKEY_DISABLE_WRITE | PKEY_DISABLE_READ, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_READ, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_READ + }, + { + PKEY_DISABLE_EXECUTE | PKEY_DISABLE_READ, + PKEY_DISABLE_EXECUTE | PKEY_DISABLE_READ + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_EXECUTE | PKEY_DISABLE_READ, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + | PKEY_DISABLE_EXECUTE + }, + { + PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE | PKEY_DISABLE_READ, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_READ | PKEY_DISABLE_WRITE + | PKEY_DISABLE_EXECUTE + }, + { + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE + | PKEY_DISABLE_READ, + PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE | PKEY_DISABLE_EXECUTE + | PKEY_DISABLE_READ + }, + }; + + for (int k = 0; k < (sizeof(rrs) / 2 / sizeof(unsigned int)); k++) { + TEST_COMPARE (k, rrs[k][0]); + TEST_COMPARE (pkey_set (pkey, rrs[k][0]), 0); + TEST_COMPARE (pkey_get (pkey), rrs[k][1]); + } + + /* Check that restrictions above maximum allowed value are rejected. */ + TEST_COMPARE (pkey_set (pkey, 16), -1); + TEST_COMPARE (errno, EINVAL); + + TEST_COMPARE (pkey_free(pkey), 0); + + xmunmap ((void *) page, pagesize); + + return 0; +} + +#include diff --git a/sysdeps/unix/sysv/linux/bits/mman-shared.h b/sysdeps/unix/sysv/linux/bits/mman-shared.h index d8ed4436b6..a270a55966 100644 --- a/sysdeps/unix/sysv/linux/bits/mman-shared.h +++ b/sysdeps/unix/sysv/linux/bits/mman-shared.h @@ -44,6 +44,7 @@ /* Access rights for pkey_alloc. */ # ifndef PKEY_DISABLE_ACCESS +# define PKEY_UNRESTRICTED 0x0 # define PKEY_DISABLE_ACCESS 0x1 # define PKEY_DISABLE_WRITE 0x2 # endif @@ -59,16 +60,16 @@ int memfd_create (const char *__name, unsigned int __flags) __THROW; int mlock2 (const void *__addr, size_t __length, unsigned int __flags) __THROW; /* Allocate a new protection key, with the PKEY_DISABLE_* bits - specified in ACCESS_RIGHTS. The protection key mask for the + specified in RESTRICTIONS. The protection key mask for the current thread is updated to match the access privilege for the new key. */ -int pkey_alloc (unsigned int __flags, unsigned int __access_rights) __THROW; +int pkey_alloc (unsigned int __flags, unsigned int __restrictions) __THROW; /* Update the access rights for the current thread for KEY, which must have been allocated using pkey_alloc. */ -int pkey_set (int __key, unsigned int __access_rights) __THROW; +int pkey_set (int __key, unsigned int __restrictions) __THROW; -/* Return the access rights for the current thread for KEY, which must +/* Return the restrictions for the current thread for KEY, which must have been allocated using pkey_alloc. */ int pkey_get (int __key) __THROW; diff --git a/sysdeps/unix/sysv/linux/pkey_set.c b/sysdeps/unix/sysv/linux/pkey_set.c index 30463ef89b..cd1f806803 100644 --- a/sysdeps/unix/sysv/linux/pkey_set.c +++ b/sysdeps/unix/sysv/linux/pkey_set.c @@ -20,7 +20,7 @@ #include int -__pkey_set (int key, unsigned int access_rights) +__pkey_set (int key, unsigned int restrictions) { __set_errno (ENOSYS); return -1; diff --git a/sysdeps/unix/sysv/linux/tst-pkey.c b/sysdeps/unix/sysv/linux/tst-pkey.c index 297a7fbc02..b8b577af0f 100644 --- a/sysdeps/unix/sysv/linux/tst-pkey.c +++ b/sysdeps/unix/sysv/linux/tst-pkey.c @@ -120,7 +120,7 @@ sigusr1_handler (int signum) TEST_COMPARE (signum, SIGUSR1); for (int i = 0; i < key_count; ++i) TEST_VERIFY (pkey_get (keys[i]) == PKEY_DISABLE_ACCESS - || pkey_get (keys[i]) == i); + || (pkey_get (keys[i]) & i) == i); sigusr1_handler_ran = 1; } @@ -185,12 +185,13 @@ do_test (void) xmunmap (page, pagesize); } + /* Create thread before setting up key in the current thread. */ xpthread_barrier_init (&barrier, NULL, 2); bool delayed_thread_check_access = true; pthread_t delayed_thread = xpthread_create (NULL, &delayed_thread_func, &delayed_thread_check_access); - keys[0] = pkey_alloc (0, 0); + keys[0] = pkey_alloc (0, PKEY_UNRESTRICTED); if (keys[0] < 0) { if (errno == ENOSYS) @@ -212,19 +213,47 @@ do_test (void) ("glibc does not support memory protection keys"); FAIL_EXIT1 ("pkey_get: %m"); } + + /* Check that initial rights that are set via pkey_alloc + can be accessed via pkey_get. */ + { + int pkey = -1; + pkey = pkey_alloc (0, PKEY_DISABLE_ACCESS); + TEST_COMPARE (pkey_get (pkey) & PKEY_DISABLE_ACCESS, PKEY_DISABLE_ACCESS); + pkey_free (pkey); + pkey = pkey_alloc (0, PKEY_DISABLE_WRITE); + TEST_COMPARE (pkey_get (pkey) & PKEY_DISABLE_WRITE, PKEY_DISABLE_WRITE); + pkey_free (pkey); + } + + /* Check that unallocated pkey is not accepted by the + pkey_mprotect function. */ + { + int pkey = -1; + pkey = pkey_alloc (0, PKEY_DISABLE_WRITE); + pkey_free (pkey); + int *page = xmmap (NULL, pagesize, PROT_NONE, + MAP_ANONYMOUS | MAP_PRIVATE, -1); + TEST_COMPARE (pkey_mprotect (page, pagesize, PROT_READ, pkey), -1); + TEST_COMPARE (errno, EINVAL); + xmunmap (page, pagesize); + } + for (int i = 1; i < key_count; ++i) { + /* i == 1 corresponds to PKEY_DISABLE_ACCESS + i == 2 corresponds to PKEY_DISABLE_WRITE */ keys[i] = pkey_alloc (0, i); if (keys[i] < 0) FAIL_EXIT1 ("pkey_alloc (0, %d): %m", i); /* pkey_alloc is supposed to change the current thread's access rights for the new key. */ - TEST_COMPARE (pkey_get (keys[i]), i); + TEST_COMPARE (pkey_get (keys[i]) & i, i); } /* Check that all the keys have the expected access rights for the current thread. */ for (int i = 0; i < key_count; ++i) - TEST_COMPARE (pkey_get (keys[i]), i); + TEST_COMPARE (pkey_get (keys[i]) & i, i); /* Allocate a test page for each key. */ for (int i = 0; i < key_count; ++i) @@ -241,12 +270,12 @@ do_test (void) pthread_barrier_wait (&barrier); struct thread_result *result = xpthread_join (delayed_thread); for (int i = 0; i < key_count; ++i) - TEST_COMPARE (result->access_rights[i], - PKEY_DISABLE_ACCESS); + TEST_COMPARE (result->access_rights[i] & + PKEY_DISABLE_ACCESS, PKEY_DISABLE_ACCESS); struct thread_result *result2 = xpthread_join (result->next_thread); for (int i = 0; i < key_count; ++i) - TEST_COMPARE (result->access_rights[i], - PKEY_DISABLE_ACCESS); + TEST_COMPARE (result->access_rights[i] & + PKEY_DISABLE_ACCESS, PKEY_DISABLE_ACCESS); free (result); free (result2); } @@ -257,12 +286,12 @@ do_test (void) pthread_t get_thread = xpthread_create (NULL, get_thread_func, NULL); struct thread_result *result = xpthread_join (get_thread); for (int i = 0; i < key_count; ++i) - TEST_COMPARE (result->access_rights[i], i); + TEST_COMPARE (result->access_rights[i] & i, i); free (result); } for (int i = 0; i < key_count; ++i) - TEST_COMPARE (pkey_get (keys[i]), i); + TEST_COMPARE (pkey_get (keys[i]) & i, i); /* Check that in a signal handler, there is no access. */ xsignal (SIGUSR1, &sigusr1_handler); @@ -281,7 +310,7 @@ do_test (void) printf ("info: checking access for key %d, bits 0x%x\n", i, pkey_get (keys[i])); for (int j = 0; j < key_count; ++j) - TEST_COMPARE (pkey_get (keys[j]), j); + TEST_COMPARE (pkey_get (keys[j]) & j, j); if (i & PKEY_DISABLE_ACCESS) { TEST_VERIFY (!check_page_access (i, false)); @@ -304,7 +333,7 @@ do_test (void) if (i == allowed_key) { if (do_write) - TEST_COMPARE (pkey_set (keys[i], 0), 0); + TEST_COMPARE (pkey_set (keys[i], PKEY_UNRESTRICTED), 0); else TEST_COMPARE (pkey_set (keys[i], PKEY_DISABLE_WRITE), 0); } @@ -331,7 +360,7 @@ do_test (void) inherit that access. */ for (int i = 0; i < key_count; ++i) { - TEST_COMPARE (pkey_set (keys[i], 0), 0); + TEST_COMPARE (pkey_set (keys[i], PKEY_UNRESTRICTED), 0); TEST_VERIFY (check_page_access (i, false)); TEST_VERIFY (check_page_access (i, true)); } @@ -355,7 +384,7 @@ do_test (void) not what happens in practice. */ { /* The limit is in place to avoid running indefinitely in case - there many keys available. */ + there are many keys available. */ int *keys_array = xcalloc (100000, sizeof (*keys_array)); int keys_allocated = 0; while (keys_allocated < 100000)