From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751797AbdGFNyT (ORCPT ); Thu, 6 Jul 2017 09:54:19 -0400 Received: from mx1.redhat.com ([209.132.183.28]:36296 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750896AbdGFNyS (ORCPT ); Thu, 6 Jul 2017 09:54:18 -0400 DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com D7A1C267CE Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx06.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=bhe@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com D7A1C267CE Date: Thu, 6 Jul 2017 21:54:13 +0800 From: Baoquan He To: Kees Cook Cc: LKML , "H. Peter Anvin" , Thomas Gleixner , Ingo Molnar , "x86@kernel.org" , "Kees Cook , Arnd Bergmann , Thomas Garnier Subject: Re: [PATCH] x86/boot/KASLR: Skip relocation handling in no kaslr case Message-ID: <20170706135413.GL19994@x1> References: <1498314309-18502-1-git-send-email-bhe@redhat.com> <20170627232412.GA15537@x1> <20170706132827.GJ19994@x1> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20170706132827.GJ19994@x1> User-Agent: Mutt/1.7.0 (2016-08-17) X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.30]); Thu, 06 Jul 2017 13:54:18 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 07/06/17 at 09:28pm, Baoquan He wrote: > > > Do you mean the handling in boot/compressed/head_64.S? Whatever it does, > > > it's only for physical address. The virtual address mapping is not > > > touched. Here virt_addr respresents the offset between > > > 0xffffffff80000000, 0xffffffffc0000000. And if skip the relocation > > > handling, we can see that the '_text' will be mapped to > > > 0xffffffff81000000 forever, no matter where physical address of '_text' > > > is. So here LOAD_PHYSICAL_ADDR is default value of 'virt_addr'. > > > > So, this isn't always true. The output address is the address assigned > > by head_*.S for the extraction destination. We can't just change that, > > since it's based on where to perform the extraction, etc. All the > > logic in there is designed to make sure we're actually >= > > LOAD_PHYSICAL_ADDR: > > > > cmpl $LOAD_PHYSICAL_ADDR, %ebx > > jge 1f > > #endif > > movl $LOAD_PHYSICAL_ADDR, %ebx > > 1: > > Yes, here it's trying to do an adjustment. To align the original loading > address if it's not aligned to CONFIG_PHYSICAL_ALIGN, and to make it be > LOAD_PHYSICAL_ADDR if it's smaller than LOAD_PHYSICAL_ADDR. Other than > those, nothing else be done. So let me conclude the possible original > 'output' value: > 1) default case > It's LOAD_PHYSICAL_ADDR Which is the default loading address. > 2) kexec/kdump > The output will be at the top of the available physical ram. > 3) Modified bootloader > Which could put kernel anywhere by modifying code of bootloader. This > is the case that we need do above alignment and adjustment to avoid > unpleasant kernel error. > > Except of above 3 cases, physical address of kernel could be changed by > physical address randomization. > 4) physical address randomization > > However, for virtual address, there are only two chances to decide: > 1) arch/x86/kernel/vmlinux.lds.S > we just map .text at __START_KERNEL > #define __PHYSICAL_START ALIGN(CONFIG_PHYSICAL_START, \ > CONFIG_PHYSICAL_ALIGN) > > #define __START_KERNEL (__START_KERNEL_map + __PHYSICAL_START) > 2) handle_relocations :: boot/compressed/misc.c > In handle_relocations(), we DO pass in the physical 'output', but that > is used to calculate 'map' which is used to position those memory > unit where the referenced address need be relocated. > > So later, in arch/x86/kernel/head_64.S, we will store the delta which is > between 16M and the actual kernel loading address into phys_base. So as Here I was wrong about phys_base. It has been changed in the latest code in Linus's tree. Please check arch/x86/kernel/head64.c: void __head __startup_64(unsigned long physaddr) { ... load_delta = physaddr - (unsigned long)(_text - __START_KERNEL_map); ... /* Fixup phys_base */ p = fixup_pointer(&phys_base, physaddr); *p += load_delta; } Here physaddr should be 'output' which is the place kernel decompressed at. > long as we can translate physical address and virtual address of kernel > by below formula, everything is going very well. > > y = x - __START_KERNEL_map + phys_base. > > We really don't need to tie physical address and virtual address of > kernel together in any cases. They can be randomized or not randomized > completely separately. As long as we keep above translation formula > working well, everything need not be worried.