From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1760079AbcILPFz (ORCPT ); Mon, 12 Sep 2016 11:05:55 -0400 Received: from mail-bn3nam01on0086.outbound.protection.outlook.com ([104.47.33.86]:43776 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1759874AbcILPFo (ORCPT ); Mon, 12 Sep 2016 11:05:44 -0400 Authentication-Results: google.com; dkim=none (message not signed) header.d=none;google.com; dmarc=none action=none header.from=amd.com; Subject: Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible To: Borislav Petkov References: <20160822223529.29880.50884.stgit@tlendack-t1.amdoffice.net> <20160822223722.29880.94331.stgit@tlendack-t1.amdoffice.net> <20160909155305.bmm2fvw7ndjjhqvo@pd.tnic> CC: , , , , , , , , , =?UTF-8?B?UmFkaW0gS3LEjW3DocWZ?= , Arnd Bergmann , Jonathan Corbet , Matt Fleming , Joerg Roedel , Konrad Rzeszutek Wilk , Andrey Ryabinin , Ingo Molnar , Andy Lutomirski , "H. Peter Anvin" , Paolo Bonzini , Alexander Potapenko , Thomas Gleixner , Dmitry Vyukov From: Tom Lendacky Message-ID: <23855fb4-05b0-4c12-d34f-4d5f45f3b015@amd.com> Date: Mon, 12 Sep 2016 10:05:36 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: <20160909155305.bmm2fvw7ndjjhqvo@pd.tnic> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Originating-IP: [165.204.77.1] X-ClientProxiedBy: SN1PR12CA0019.namprd12.prod.outlook.com (10.162.96.157) To DM5PR12MB1148.namprd12.prod.outlook.com (10.168.236.143) X-MS-Office365-Filtering-Correlation-Id: 12a5e8d4-672c-4670-4feb-08d3db1e4390 X-Microsoft-Exchange-Diagnostics: 1;DM5PR12MB1148;2:htcAOYSMtzOyW1OS8oAxOvTY4CKR+ae9VAuo8lbIiCIBNGsP5o5AK4QFiF0Oi8bw+139ENDLjStrMpuAdx8MX4LSsD1gZOITxr/vQgnSd1ETDywjMlJ1ti0MKoVoemHJPFsuL3PztmIQmxtY96miDYWsTuH6pM9pnoaoFRe+4tmq5oVyjc6blHP6N0LslWYJ;3:0vH/PYDfQRWibT4cSvodrkK0vORapJDPzpN6MXKwE7m9xQEPWvpX0mCDqzWakF0wHtWesrz6VKbZhoZ8qPpyVdjghjl6FQ8zm/2kUZ3KlCZcz8aSWwfRxaOPJL8X7xWW X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:DM5PR12MB1148; X-Microsoft-Exchange-Diagnostics: 1;DM5PR12MB1148;25:Ah8+oWh5YlKgelZwCIf/IMEy3Fm9wjUZo0EyZR/XFg5QKwFoM7PB4MWnywQdnQGq6mGsbk4X14ZXLZK72Vlx2z4ijb/JP1Mc7yMDWvgO4AZK7Nvc9vahFVtlmeht6Owag6HwzUdxqzsqmrO9tWNUn9BmKBukZ1OXJTctvuFgIYcKIjrl4C0hqNTE0UemjgPFWaI+o3q/sX24N62bwWZop1e1c0s1sOW07eaBRBNxQdhkwRYw2Fp7jFhGazXWdec5LwFR5wjjtQzCfH5zk9Sn3NMqm9LguJ9Xt6xNM2ho3b5pzDo/yAdI93Z4xvPztumSVqDmcH8gAqlGJsYOF30FqneNjf0U0S7uRn5fygxSHX1YK7uEDzrGH0sbBMsW8sGQ9F/DJFc18G6Fhht3SGrl2rVQbWMxzHw4qA+2zMLM4XLmQ/gYbYbYG1E2/9f6c+fXI1c0n8HtKrbqI8Iu1BomuW4nBUOjVJcQ1tg+ZTWdTC4ofYDqkBHNhJXlaRLijgpFwaHtsfJGQgCSR8S//c9Z0vlcT3/SYzG2OXDyEZuX5uMeqxxtI3/tyfZ6P2+hu1NTgs8HCkybOaGxQJKJ+xQBLNyFQa7id79gplEEvN4WOEN3TjhdlV9TeAVhsFwgmDKs01qzabU0wXzonzzg/8w+sv/eq1pdPe/+WbEsZatXfj945xHLQHaEwCI62j763ryaB4If3z+XqqdP9ey/Hh+nCw==;31:olA8Ou+3w1Nd1udkRc1MVXP4py95bxslmy2gOuoUNCgjJ4KYbl11vL+yeb0dr+WtDcU0E6xBshnrm/a9lj2wSP100ZzGrb+x2pJCRa497cd5nrGkvfhgBkK8+KguPKhccyO9qiE8XRXL5txz20uduiVri2KWz6ruw447AEje1L2+e942hGT0T5SsSCvc2/833dTvWaEQe54K8/VgSoYy1AZ7mIcP3BxZ9ZLshAlW15o= X-Microsoft-Exchange-Diagnostics: 1;DM5PR12MB1148;20:Qsc4Yt5tYT7F1plby6oDFjJ6e6dm0cFHsmQPKPhNRC/Q1G1OBED8qeDnYCJfqRpwc3ZoQUJXV18kCV6Jg6+NCLdnT5+tlj9zYcbf4jrMul+zmNj3KuXAUhBD3KLuMu7K78Lss2ULelt6BYgHpiJO4aCvgmD8m6F5BmfTB5ST4PKkiE8Sg/eJNwlnZ29ilWWboTxicc98vjp1nIaSGE0KTPgu6Vj2wsGkCR4ITG5cFFl4HzEjJVWm679Mw87HXFTF92A6nmF430EBINxbqKct8JECU1bByFmGLj3LGhK5EWqm7125eie/lCQ4ZRvEjWjTd1NhaBmz80COCUChxOn+n7xpd1NOrnVq5wHTgtDlgnyt6jTvAH9XeHoFQp/1l0on7+M4IEg5DGrxmnBjrIUThAu3oxR72AU7eYkGhBtda7fNlqJYnrd0R3YSQuEZo0CXnh+p/gMW04SxyaQE0qaJNI4Dya9RgAtz1XeH7FpB1ffdAO4m7I7qsS56kdh6W57l;4:sYqh0izBC40gzgJbGA254wj+Q7MgszpTSboy5Jcv7LvqWmGJioX/37iE2v+JECX0AYZk+9LF/xxCBoeJlyt5WYmicMVb1NrX0c9+/KlN6iQw/N6n25YFtT2dzh6KMcty6y3CJDKTTMYxvaGunjkg4Ogr0W8O6K0Ywcvkw2MzEag4l523UqA9Ohx0Afods8eEPb5IZ8fB/BSYc4kfnqTt5Rvf0ZG1ZPSFkQx7rSEU1Ah9Vnj9Uj722nQBBH6jDVDljnT/C8x7j5AWO7GxnasGRCwaVOrRLLaw09lk/2LVlslUQ3UdLYjOaznuJzhXtbDZxGIDGAVriiNv8ndgpKHLIuFi5ghmn/wwWPbU/SUiEV6l/rBO9psPATvjG2RYu+6s+p6L0PBbggGuRiO01EAbOMPyivQrxOAtoaCT7L2R08nttmH06VFfqz8ecWT5MAWO X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(767451399110); X-Exchange-Antispam-Report-CFA-Test: BCL:0;PCL:0;RULEID:(6040176)(601004)(2401047)(8121501046)(5005006)(10201501046)(3002001)(6055026);SRVR:DM5PR12MB1148;BCL:0;PCL:0;RULEID:;SRVR:DM5PR12MB1148; X-Forefront-PRVS: 006339698F X-Forefront-Antispam-Report: SFV:NSPM;SFS:(10009020)(4630300001)(6049001)(6009001)(7916002)(24454002)(377454003)(64126003)(83506001)(23676002)(50466002)(33646002)(65826007)(87386001)(7416002)(230700001)(5004840100003)(42186005)(2906002)(4326007)(6116002)(86362001)(77096005)(19580395003)(50986999)(3846002)(8676002)(31696002)(189998001)(305945005)(19580405001)(110136002)(2950100001)(586003)(5660300001)(4001520100001)(36756003)(81166006)(92566002)(66066001)(47776003)(54356999)(7736002)(31686004)(7846002)(76176999)(65806001)(65956001)(4001350100001)(217873001);DIR:OUT;SFP:1101;SCL:1;SRVR:DM5PR12MB1148;H:[10.236.18.82];FPR:;SPF:None;LANG:en; X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtETTVQUjEyTUIxMTQ4OzIzOkl2VnRxSVZmbWVFVEx5ZldUeWNZSWhEQUdt?= =?utf-8?B?ZUwvak4rVzdURVRhbUxNNWNjNkNLTko3aW1pbUpVUC9OVGlGbW5JTWJVY0d1?= =?utf-8?B?VXJzTUNpN1Z4TmNtMy9wK2pzbmdqK1hIeXpVRFhPWVIvMEdQRy9paGFDQ0pn?= =?utf-8?B?RUcxV1NDOVBrSUdBRkxhS1dtQzZjMEl5WC9sREdWTk5Tb3dnU1ozSWJDOGlJ?= =?utf-8?B?VDhTQnFVbWlkVURoOWZaa05JRkhXYVdXNWkyUjdzbFd5L2NKa3lBK0MyVkdL?= =?utf-8?B?N3UydkQ3Q1lSYWlia3QzcDdDK1JmamMreU90dkdiRVJMZlcwbUhCNDRjaWJI?= =?utf-8?B?SGN5amZYQXAxNGExbkluNXdZWDZDa0NxY2hSUUJFY0dPNGY3TGxneUNLQVJW?= =?utf-8?B?OE9lWHpuZVRpVjNTRzVCQjFLRjhsdHZlOWRNZEdXYVI2YTA0OU14aVI5TUtD?= =?utf-8?B?L0VTYlltdFZNOEc0b3dwcm53ZzB5YzZOVmE0dFJBNFUrRDRyMGpGNWZaL2Ry?= =?utf-8?B?TGllVzZlYzdMcXBXU2d4NStCenh6eG4wYmxSQ2dlR3VNaVF3YnBuT2VuY1dV?= =?utf-8?B?SmpzYnhOajVpOVRnTlF3ODE2SGsyUHlnZ2VScjNqSHZpSHB5cVJvUjFzU3Y0?= =?utf-8?B?dE9VSkJRYi80RnIwOEpIVDRxaGtYM243aFduMEtqdXh5ZmFiN2lidmNjSXdr?= =?utf-8?B?eWpxMFQvTHZJd25PNE1aU3NKUnZ1d1ppUXlPMVAwbXRHVUNONHlRdDhyZkcw?= =?utf-8?B?UmtDKzJseHJtQWJ2MEd0aHRVZC8xMWZQOWtRdGxMdXRxMnVoZjVRQ0x4VmY0?= =?utf-8?B?VVpiN1FVa0F3cWo3S3k4UVpxS2JBOVJoTHZGVkp2UmdBV1lUQVRZbER5dzBr?= =?utf-8?B?cFhsbUp2WDJob2Jqa2poSjF1TXZ1eitxYk5tZ0NXRnBkUEpYYnVKZFlRaDRw?= =?utf-8?B?a216S0l5Wk93a3hEQnBIZ0psbHZvRGkremtZQkdZNWdHVTJldmpxVCthL2g0?= =?utf-8?B?T05MMHN2VCtOcTRNWGxZZS9QdnJoVk9vWU1USWdNV0U1cUFRQ0pTWElKZFpQ?= =?utf-8?B?Ky9vaThRWmM0cFhQeXU5Z1Y0U1hpLzJoOURmNis2eXZtbEx0bzh6WHlMS0Ru?= =?utf-8?B?TE5zMHdIWnZpOVREaXRpU1NkY3RQRDZ6UXJoVW5SekE4TEFFblU1TGJ2UDBq?= =?utf-8?B?YzRSWTdNQmJza1JrcTN6OW1HeTRnRkJhbVBBdGd0Y0NTSnBoSmNYa0UyaFNj?= =?utf-8?B?a0UxMEVUQ3dnSHRyMUk1M3VJTnpiaWpRT1ZVbWtUbktEUGZhRDRWMUxPTGN5?= =?utf-8?B?Ums4OWVGSHp3Q0JEdFZpSEFnck9DOWF4bE0wZTN0OFJscXdwVm5xY0UzWUFO?= =?utf-8?B?WDBXZTlBWDFmankwb3d5aFNOZGpDeGtHZ2xmMVgzbmoyaUVtQXhEakxya2Qw?= =?utf-8?B?SmhaTGg0NDdMUEt0TUZWU1dVSE4zVkNCb0h1d3VKYUlUY1FEdklLcUxFckRH?= =?utf-8?B?RmJiemd3ZDdZeDVubmlpMnMvenpUTTZiQnAvcUFLQlBnZHNKdmlGUFhYRU9o?= =?utf-8?B?RlNkZ1c0UngzT0RvL20rNnNIS2ZpRWJWVWVyVmMyMmUxR1F6a0RFT1lXZ0cz?= =?utf-8?B?U2hadCs4VXl1dThVeDFKQ25ZU01hekFDY0dhdjNteFVpaU5zTDd6dnQ2V2J2?= =?utf-8?Q?v4iBNV1rg19eX0pOJk=3D?= X-Microsoft-Exchange-Diagnostics: 1;DM5PR12MB1148;6:GO/5wYqeNZ2ch3Dw5uGItpnFXLccY6FtcAymFj2X2iq/weRAIHSgiLFLZNc7e8Ofoq2Vq9MNPIdYHukQFmog75GIYMTcBC/cAKuwjJ5+TqKV/XKoDjvfHyVHsqCJy+If1MkC7tqU0FKRTOrGVGpqh39vtSHECKNst9BXYlveKnMqsxdSpdqAbUYV17g4UlbjmpRZuzlMPds7JHiCUM0vc+QWoxiY12iyIhR9kQqibuTaEAxIlm60dwckMVzepfMrKor9Jgwrfxtvs37+um9cLcmRLw1bhnJgaldx/5AFfQCbQQqnYl3ty63SlHfZBg4UDwiqQDBK17w5gmJT0hY6Zw==;5:0ri2IZcQjOUJ4KO+Qbu9U+LeMudUbDwQCR0cHeyk/N4mYhsUKVoWfPIaVXJCuaOZemM1pqpSjqL4iiXRUT8q3CnOwpGiRNQKhQF+zVbWwzUPCiYugbn/F0m0/curjL0kLXuzeDDtREWAZpMyXqZ0TQ==;24:BzgEV9PrvpG3FUlCYK2pVQUGRhNIcZkNh8NjtYPhLv19T5jtUavMw7GezoyYWzQTaqNTRCrhGG89tFMFK7jg6j6jxIQlEsWg894oSoaTGL4=;7:jwaXrzyPqMkbU+oWP6ZnsHWUG2h8H7j4doYDUiBjkQfV4qe3U7F6cetf5kslYhhu7NnH8MS22z9/8ZMuzHT9R3XjxBXeYFyDJthOv8Hnx3fvE+97tMd3OSKU2a6nzbtEJ+hpuniSv1p/OSdY0DlbN5A3CaAUvh2MwwPd0ptAJuOyhguiTOQ2aSqOVQRux+3XAkrzEyjTNXFVKKRJALOW1BZMANLff0PEU7NaY1oDtmJnBXGrX+85oqt4bvhLmufq SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1;DM5PR12MB1148;20:Oja7QfbkwTn59X8yk1VsS0V7XatoDklNf7Xh24nqsQRveFD+ofZN4KIfUJYn5eLiFCfW3uW5lOP7GtjT3H92st/y5IPlHvohq/qowtrH/WvbUkOlkKCFKw3UzncFwSbM+VCYIX/WxaXdp0vZoiFO9H8nhMG1xJ8YKLmCw1q0sYibveEfPk3Z0qvsB3dx+wQXHllHBDIyG8+GD9tS+beDKdxitj3LTHqFoCv6vIBS7tv1c2FJiDJfLloCjAGhoSEn X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Sep 2016 15:05:40.7355 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR12MB1148 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 09/09/2016 10:53 AM, Borislav Petkov wrote: > On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote: >> Encrypt memory areas in place when possible (e.g. zero page, etc.) so >> that special handling isn't needed afterwards. >> >> Signed-off-by: Tom Lendacky >> --- >> arch/x86/kernel/head64.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-- >> arch/x86/kernel/setup.c | 8 ++++ >> 2 files changed, 96 insertions(+), 5 deletions(-) > > ... > >> +int __init early_make_pgtable(unsigned long address) >> +{ >> + unsigned long physaddr = address - __PAGE_OFFSET; >> + pmdval_t pmd; >> + >> + pmd = (physaddr & PMD_MASK) + early_pmd_flags; >> + >> + return __early_make_pgtable(address, pmd); >> +} >> + >> +static void __init create_unencrypted_mapping(void *address, unsigned long size) >> +{ >> + unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET; >> + pmdval_t pmd_flags, pmd; >> + >> + if (!sme_me_mask) >> + return; >> + >> + /* Clear the encryption mask from the early_pmd_flags */ >> + pmd_flags = early_pmd_flags & ~sme_me_mask; >> + >> + do { >> + pmd = (physaddr & PMD_MASK) + pmd_flags; >> + __early_make_pgtable((unsigned long)address, pmd); >> + >> + address += PMD_SIZE; >> + physaddr += PMD_SIZE; >> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE; >> + } while (size); >> +} >> + >> +static void __init __clear_mapping(unsigned long address) > > Should be called something with "pmd" in the name as it clears a PMD, > i.e. __clear_pmd_mapping or so. Ok. > >> +{ >> + unsigned long physaddr = address - __PAGE_OFFSET; >> + pgdval_t pgd, *pgd_p; >> + pudval_t pud, *pud_p; >> + pmdval_t *pmd_p; >> + >> + /* Invalid address or early pgt is done ? */ >> + if (physaddr >= MAXMEM || >> + read_cr3() != __sme_pa_nodebug(early_level4_pgt)) >> + return; >> + >> + pgd_p = &early_level4_pgt[pgd_index(address)].pgd; >> + pgd = *pgd_p; >> + >> + if (!pgd) >> + return; >> + >> + /* >> + * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches >> + * __early_make_pgtable where the entry was created. >> + */ >> + pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); >> + pud_p += pud_index(address); >> + pud = *pud_p; >> + >> + if (!pud) >> + return; >> + >> + pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); >> + pmd_p[pmd_index(address)] = 0; >> +} >> + >> +static void __init clear_mapping(void *address, unsigned long size) >> +{ >> + if (!sme_me_mask) >> + return; >> + >> + do { >> + __clear_mapping((unsigned long)address); >> + >> + address += PMD_SIZE; >> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE; >> + } while (size); >> +} >> + >> +static void __init sme_memcpy(void *dst, void *src, unsigned long size) >> +{ >> + create_unencrypted_mapping(src, size); >> + memcpy(dst, src, size); >> + clear_mapping(src, size); >> +} >> + > > In any case, this whole functionality is SME-specific and should be > somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so... I can look into that. The reason I put this here is this is all the early page fault support that is very specific to this file. I modified an existing static function to take advantage of the mapping support. > >> /* Don't add a printk in there. printk relies on the PDA which is not initialized >> yet. */ >> static void __init clear_bss(void) >> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data) >> char * command_line; >> unsigned long cmd_line_ptr; >> >> - memcpy(&boot_params, real_mode_data, sizeof boot_params); >> + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params); > > checkpatch.pl: > > WARNING: sizeof boot_params should be sizeof(boot_params) > #155: FILE: arch/x86/kernel/head64.c:208: > + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params); I can fix that. > >> sanitize_boot_params(&boot_params); >> cmd_line_ptr = get_cmd_line_ptr(); >> if (cmd_line_ptr) { >> command_line = __va(cmd_line_ptr); >> - memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); >> + sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); >> } >> } >> >> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c >> index 1489da8..1fdaa11 100644 >> --- a/arch/x86/kernel/setup.c >> +++ b/arch/x86/kernel/setup.c >> @@ -114,6 +114,7 @@ >> #include >> #include >> #include >> +#include >> >> /* >> * max_low_pfn_mapped: highest direct mapped pfn under 4GB >> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void) >> !ramdisk_image || !ramdisk_size) >> return; /* No initrd provided by bootloader */ >> >> + /* >> + * This memory is marked encrypted by the kernel but the ramdisk >> + * was loaded in the clear by the bootloader, so make sure that >> + * the ramdisk image is encrypted. >> + */ >> + sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image); > > What happens if we go and relocate the ramdisk? I.e., the function above > this one: relocate_initrd(). We have to encrypt it then too, I presume. Hmmm, maybe... With the change to the early_memremap() the initrd is now identified as BOOT_DATA in relocate_initrd() and so it will be mapped and copied as non-encyrpted data. But since it was encrypted before the call to relocate_initrd() it will copy encrypted bytes which will later be accessed encrypted. That isn't clear though, so I'll rework reserve_initrd() to perform the sme_early_mem_enc() once at the end whether the initrd is re-located or not. Thanks, Tom > From mboxrd@z Thu Jan 1 00:00:00 1970 From: Tom Lendacky Subject: Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible Date: Mon, 12 Sep 2016 10:05:36 -0500 Message-ID: <23855fb4-05b0-4c12-d34f-4d5f45f3b015@amd.com> References: <20160822223529.29880.50884.stgit@tlendack-t1.amdoffice.net> <20160822223722.29880.94331.stgit@tlendack-t1.amdoffice.net> <20160909155305.bmm2fvw7ndjjhqvo@pd.tnic> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <20160909155305.bmm2fvw7ndjjhqvo-fF5Pk5pvG8Y@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org Errors-To: iommu-bounces-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org To: Borislav Petkov Cc: linux-efi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, kvm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, =?UTF-8?B?UmFkaW0gS3LEjW3DocWZ?= , Matt Fleming , x86-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org, Alexander Potapenko , "H. Peter Anvin" , linux-arch-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, Jonathan Corbet , linux-doc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, kasan-dev-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org, Ingo Molnar , Andrey Ryabinin , Arnd Bergmann , Andy Lutomirski , Thomas Gleixner , Dmitry Vyukov , linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org, Paolo Bonzini List-Id: linux-efi@vger.kernel.org On 09/09/2016 10:53 AM, Borislav Petkov wrote: > On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote: >> Encrypt memory areas in place when possible (e.g. zero page, etc.) so >> that special handling isn't needed afterwards. >> >> Signed-off-by: Tom Lendacky >> --- >> arch/x86/kernel/head64.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-- >> arch/x86/kernel/setup.c | 8 ++++ >> 2 files changed, 96 insertions(+), 5 deletions(-) > > ... > >> +int __init early_make_pgtable(unsigned long address) >> +{ >> + unsigned long physaddr = address - __PAGE_OFFSET; >> + pmdval_t pmd; >> + >> + pmd = (physaddr & PMD_MASK) + early_pmd_flags; >> + >> + return __early_make_pgtable(address, pmd); >> +} >> + >> +static void __init create_unencrypted_mapping(void *address, unsigned long size) >> +{ >> + unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET; >> + pmdval_t pmd_flags, pmd; >> + >> + if (!sme_me_mask) >> + return; >> + >> + /* Clear the encryption mask from the early_pmd_flags */ >> + pmd_flags = early_pmd_flags & ~sme_me_mask; >> + >> + do { >> + pmd = (physaddr & PMD_MASK) + pmd_flags; >> + __early_make_pgtable((unsigned long)address, pmd); >> + >> + address += PMD_SIZE; >> + physaddr += PMD_SIZE; >> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE; >> + } while (size); >> +} >> + >> +static void __init __clear_mapping(unsigned long address) > > Should be called something with "pmd" in the name as it clears a PMD, > i.e. __clear_pmd_mapping or so. Ok. > >> +{ >> + unsigned long physaddr = address - __PAGE_OFFSET; >> + pgdval_t pgd, *pgd_p; >> + pudval_t pud, *pud_p; >> + pmdval_t *pmd_p; >> + >> + /* Invalid address or early pgt is done ? */ >> + if (physaddr >= MAXMEM || >> + read_cr3() != __sme_pa_nodebug(early_level4_pgt)) >> + return; >> + >> + pgd_p = &early_level4_pgt[pgd_index(address)].pgd; >> + pgd = *pgd_p; >> + >> + if (!pgd) >> + return; >> + >> + /* >> + * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches >> + * __early_make_pgtable where the entry was created. >> + */ >> + pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); >> + pud_p += pud_index(address); >> + pud = *pud_p; >> + >> + if (!pud) >> + return; >> + >> + pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); >> + pmd_p[pmd_index(address)] = 0; >> +} >> + >> +static void __init clear_mapping(void *address, unsigned long size) >> +{ >> + if (!sme_me_mask) >> + return; >> + >> + do { >> + __clear_mapping((unsigned long)address); >> + >> + address += PMD_SIZE; >> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE; >> + } while (size); >> +} >> + >> +static void __init sme_memcpy(void *dst, void *src, unsigned long size) >> +{ >> + create_unencrypted_mapping(src, size); >> + memcpy(dst, src, size); >> + clear_mapping(src, size); >> +} >> + > > In any case, this whole functionality is SME-specific and should be > somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so... I can look into that. The reason I put this here is this is all the early page fault support that is very specific to this file. I modified an existing static function to take advantage of the mapping support. > >> /* Don't add a printk in there. printk relies on the PDA which is not initialized >> yet. */ >> static void __init clear_bss(void) >> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data) >> char * command_line; >> unsigned long cmd_line_ptr; >> >> - memcpy(&boot_params, real_mode_data, sizeof boot_params); >> + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params); > > checkpatch.pl: > > WARNING: sizeof boot_params should be sizeof(boot_params) > #155: FILE: arch/x86/kernel/head64.c:208: > + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params); I can fix that. > >> sanitize_boot_params(&boot_params); >> cmd_line_ptr = get_cmd_line_ptr(); >> if (cmd_line_ptr) { >> command_line = __va(cmd_line_ptr); >> - memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); >> + sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); >> } >> } >> >> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c >> index 1489da8..1fdaa11 100644 >> --- a/arch/x86/kernel/setup.c >> +++ b/arch/x86/kernel/setup.c >> @@ -114,6 +114,7 @@ >> #include >> #include >> #include >> +#include >> >> /* >> * max_low_pfn_mapped: highest direct mapped pfn under 4GB >> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void) >> !ramdisk_image || !ramdisk_size) >> return; /* No initrd provided by bootloader */ >> >> + /* >> + * This memory is marked encrypted by the kernel but the ramdisk >> + * was loaded in the clear by the bootloader, so make sure that >> + * the ramdisk image is encrypted. >> + */ >> + sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image); > > What happens if we go and relocate the ramdisk? I.e., the function above > this one: relocate_initrd(). We have to encrypt it then too, I presume. Hmmm, maybe... With the change to the early_memremap() the initrd is now identified as BOOT_DATA in relocate_initrd() and so it will be mapped and copied as non-encyrpted data. But since it was encrypted before the call to relocate_initrd() it will copy encrypted bytes which will later be accessed encrypted. That isn't clear though, so I'll rework reserve_initrd() to perform the sme_early_mem_enc() once at the end whether the initrd is re-located or not. Thanks, Tom > From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-yw0-f199.google.com (mail-yw0-f199.google.com [209.85.161.199]) by kanga.kvack.org (Postfix) with ESMTP id 89E486B0038 for ; Mon, 12 Sep 2016 11:05:44 -0400 (EDT) Received: by mail-yw0-f199.google.com with SMTP id u124so312643661ywg.3 for ; Mon, 12 Sep 2016 08:05:44 -0700 (PDT) Received: from NAM01-BN3-obe.outbound.protection.outlook.com (mail-bn3nam01on0081.outbound.protection.outlook.com. [104.47.33.81]) by mx.google.com with ESMTPS id k12si1291243qtc.139.2016.09.12.08.05.43 for (version=TLS1 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 12 Sep 2016 08:05:43 -0700 (PDT) Subject: Re: [RFC PATCH v2 10/20] x86: Insure that memory areas are encrypted when possible References: <20160822223529.29880.50884.stgit@tlendack-t1.amdoffice.net> <20160822223722.29880.94331.stgit@tlendack-t1.amdoffice.net> <20160909155305.bmm2fvw7ndjjhqvo@pd.tnic> From: Tom Lendacky Message-ID: <23855fb4-05b0-4c12-d34f-4d5f45f3b015@amd.com> Date: Mon, 12 Sep 2016 10:05:36 -0500 MIME-Version: 1.0 In-Reply-To: <20160909155305.bmm2fvw7ndjjhqvo@pd.tnic> Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Sender: owner-linux-mm@kvack.org List-ID: To: Borislav Petkov Cc: linux-arch@vger.kernel.org, linux-efi@vger.kernel.org, kvm@vger.kernel.org, linux-doc@vger.kernel.org, x86@kernel.org, linux-kernel@vger.kernel.org, kasan-dev@googlegroups.com, linux-mm@kvack.org, iommu@lists.linux-foundation.org, =?UTF-8?B?UmFkaW0gS3LEjW3DocWZ?= , Arnd Bergmann , Jonathan Corbet , Matt Fleming , Joerg Roedel , Konrad Rzeszutek Wilk , Andrey Ryabinin , Ingo Molnar , Andy Lutomirski , "H. Peter Anvin" , Paolo Bonzini , Alexander Potapenko , Thomas Gleixner , Dmitry Vyukov On 09/09/2016 10:53 AM, Borislav Petkov wrote: > On Mon, Aug 22, 2016 at 05:37:23PM -0500, Tom Lendacky wrote: >> Encrypt memory areas in place when possible (e.g. zero page, etc.) so >> that special handling isn't needed afterwards. >> >> Signed-off-by: Tom Lendacky >> --- >> arch/x86/kernel/head64.c | 93 ++++++++++++++++++++++++++++++++++++++++++++-- >> arch/x86/kernel/setup.c | 8 ++++ >> 2 files changed, 96 insertions(+), 5 deletions(-) > > ... > >> +int __init early_make_pgtable(unsigned long address) >> +{ >> + unsigned long physaddr = address - __PAGE_OFFSET; >> + pmdval_t pmd; >> + >> + pmd = (physaddr & PMD_MASK) + early_pmd_flags; >> + >> + return __early_make_pgtable(address, pmd); >> +} >> + >> +static void __init create_unencrypted_mapping(void *address, unsigned long size) >> +{ >> + unsigned long physaddr = (unsigned long)address - __PAGE_OFFSET; >> + pmdval_t pmd_flags, pmd; >> + >> + if (!sme_me_mask) >> + return; >> + >> + /* Clear the encryption mask from the early_pmd_flags */ >> + pmd_flags = early_pmd_flags & ~sme_me_mask; >> + >> + do { >> + pmd = (physaddr & PMD_MASK) + pmd_flags; >> + __early_make_pgtable((unsigned long)address, pmd); >> + >> + address += PMD_SIZE; >> + physaddr += PMD_SIZE; >> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE; >> + } while (size); >> +} >> + >> +static void __init __clear_mapping(unsigned long address) > > Should be called something with "pmd" in the name as it clears a PMD, > i.e. __clear_pmd_mapping or so. Ok. > >> +{ >> + unsigned long physaddr = address - __PAGE_OFFSET; >> + pgdval_t pgd, *pgd_p; >> + pudval_t pud, *pud_p; >> + pmdval_t *pmd_p; >> + >> + /* Invalid address or early pgt is done ? */ >> + if (physaddr >= MAXMEM || >> + read_cr3() != __sme_pa_nodebug(early_level4_pgt)) >> + return; >> + >> + pgd_p = &early_level4_pgt[pgd_index(address)].pgd; >> + pgd = *pgd_p; >> + >> + if (!pgd) >> + return; >> + >> + /* >> + * The use of __START_KERNEL_map rather than __PAGE_OFFSET here matches >> + * __early_make_pgtable where the entry was created. >> + */ >> + pud_p = (pudval_t *)((pgd & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); >> + pud_p += pud_index(address); >> + pud = *pud_p; >> + >> + if (!pud) >> + return; >> + >> + pmd_p = (pmdval_t *)((pud & PTE_PFN_MASK) + __START_KERNEL_map - phys_base); >> + pmd_p[pmd_index(address)] = 0; >> +} >> + >> +static void __init clear_mapping(void *address, unsigned long size) >> +{ >> + if (!sme_me_mask) >> + return; >> + >> + do { >> + __clear_mapping((unsigned long)address); >> + >> + address += PMD_SIZE; >> + size = (size < PMD_SIZE) ? 0 : size - PMD_SIZE; >> + } while (size); >> +} >> + >> +static void __init sme_memcpy(void *dst, void *src, unsigned long size) >> +{ >> + create_unencrypted_mapping(src, size); >> + memcpy(dst, src, size); >> + clear_mapping(src, size); >> +} >> + > > In any case, this whole functionality is SME-specific and should be > somewhere in an SME-specific file. arch/x86/mm/mem_encrypt.c or so... I can look into that. The reason I put this here is this is all the early page fault support that is very specific to this file. I modified an existing static function to take advantage of the mapping support. > >> /* Don't add a printk in there. printk relies on the PDA which is not initialized >> yet. */ >> static void __init clear_bss(void) >> @@ -122,12 +205,12 @@ static void __init copy_bootdata(char *real_mode_data) >> char * command_line; >> unsigned long cmd_line_ptr; >> >> - memcpy(&boot_params, real_mode_data, sizeof boot_params); >> + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params); > > checkpatch.pl: > > WARNING: sizeof boot_params should be sizeof(boot_params) > #155: FILE: arch/x86/kernel/head64.c:208: > + sme_memcpy(&boot_params, real_mode_data, sizeof boot_params); I can fix that. > >> sanitize_boot_params(&boot_params); >> cmd_line_ptr = get_cmd_line_ptr(); >> if (cmd_line_ptr) { >> command_line = __va(cmd_line_ptr); >> - memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); >> + sme_memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE); >> } >> } >> >> diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c >> index 1489da8..1fdaa11 100644 >> --- a/arch/x86/kernel/setup.c >> +++ b/arch/x86/kernel/setup.c >> @@ -114,6 +114,7 @@ >> #include >> #include >> #include >> +#include >> >> /* >> * max_low_pfn_mapped: highest direct mapped pfn under 4GB >> @@ -376,6 +377,13 @@ static void __init reserve_initrd(void) >> !ramdisk_image || !ramdisk_size) >> return; /* No initrd provided by bootloader */ >> >> + /* >> + * This memory is marked encrypted by the kernel but the ramdisk >> + * was loaded in the clear by the bootloader, so make sure that >> + * the ramdisk image is encrypted. >> + */ >> + sme_early_mem_enc(ramdisk_image, ramdisk_end - ramdisk_image); > > What happens if we go and relocate the ramdisk? I.e., the function above > this one: relocate_initrd(). We have to encrypt it then too, I presume. Hmmm, maybe... With the change to the early_memremap() the initrd is now identified as BOOT_DATA in relocate_initrd() and so it will be mapped and copied as non-encyrpted data. But since it was encrypted before the call to relocate_initrd() it will copy encrypted bytes which will later be accessed encrypted. That isn't clear though, so I'll rework reserve_initrd() to perform the sme_early_mem_enc() once at the end whether the initrd is re-located or not. Thanks, Tom > -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@kvack.org. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: email@kvack.org