From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mout02.posteo.de (mout02.posteo.de [185.67.36.66]) by mx.groups.io with SMTP id smtpd.web12.8886.1627050429243364290 for ; Fri, 23 Jul 2021 07:27:10 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@posteo.de header.s=2017 header.b=Enj2Z7Je; spf=pass (domain: posteo.de, ip: 185.67.36.66, mailfrom: mhaeuser@posteo.de) Received: from submission (posteo.de [89.146.220.130]) by mout02.posteo.de (Postfix) with ESMTPS id 298D2240105 for ; Fri, 23 Jul 2021 16:27:05 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.de; s=2017; t=1627050426; bh=+NfV7Iouf2RDBhYCm1whAUsVdSGWdDd5jZ1l81mC47A=; h=Subject:To:Cc:From:Date:From; b=Enj2Z7JeZF+nZmPDqnB1KcyWb3GLn6gzNvSAKMhu93pbWiLcf6Xqyz+B1FJ7HvCZk Apjosi/hD4BUKZJ7kdYuoq+cvC50NIbN8Gjs8Iqk6dRNech1zVx0db85uYFNwTeeJZ tlCLurGnWFf+lNRb35W1eJ3DVR9tPjRr7oIXJR+gUxXB74uFNwq3K+YzHAu08sCJhx jCwIFXTo5TD8Ucwtud4Ku+N0Qrp85ns+uJ0RTaFhI1flVGedmJwbh8NKpvYtMll8uk yt3GXtoGGlu6uLHbov2HzXXlZT6ZHR88hXqoawsTmmWi5H9SC8vu+r1uJTiS+o4MfI Mgd0muAPLkZYQ== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4GWWqD0V3jz6tmN; Fri, 23 Jul 2021 16:27:03 +0200 (CEST) Subject: Re: ArmVirt and Self-Updating Code To: Ard Biesheuvel Cc: Bret Barkelew , Thomas Abraham , "Ard Biesheuvel (TianoCore)" , "Lindholm, Leif" , Laszlo Ersek , Sami Mujawar , "devel@edk2.groups.io" , nd References: <36b32106-da0e-bfd5-10cf-6c9bb86173d1@posteo.de> From: =?UTF-8?B?TWFydmluIEjDpHVzZXI=?= Message-ID: <39afb072-3e01-6946-9387-e414a8f62f8d@posteo.de> Date: Fri, 23 Jul 2021 14:27:00 +0000 MIME-Version: 1.0 In-Reply-To: Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-GB Content-Transfer-Encoding: quoted-printable On 23.07.21 16:09, Ard Biesheuvel wrote: > On Fri, 23 Jul 2021 at 12:47, Marvin H=C3=A4user w= rote: >> On 23.07.21 12:13, Ard Biesheuvel wrote: >>> On Fri, 23 Jul 2021 at 11:55, Marvin H=C3=A4user = wrote: >>>> On 22.07.21 17:14, Ard Biesheuvel wrote: >>>>> On Thu, 22 Jul 2021 at 16:54, Bret Barkelew wrote: >>>>>> Expanding audience to the full dev list=E2=80=A6 >>>>>> >>>>>> See below=E2=80=A6 >>>>>> >>>>>> >>>>>> >>>>>> - Bret >>>>>> >>>>>> >>>>>> >>>>>> From: Thomas Abraham >>>>>> Sent: Wednesday, July 7, 2021 11:07 PM >>>>>> To: Bret Barkelew; Ard Biesheuvel (TianoCore); Lindholm, Leif; Las= zlo Ersek; Marvin H=C3=A4user; Sami Mujawar >>>>>> Cc: nd >>>>>> Subject: [EXTERNAL] RE: ArmVirt and Self-Updating Code >>>>>> >>>>>> >>>>>> >>>>>> + Sami >>>>>> >>>>>> >>>>>> >>>>>> From: Bret Barkelew >>>>>> Sent: Thursday, July 8, 2021 11:05 AM >>>>>> To: Thomas Abraham; Ard Biesheuvel (TianoC= ore); Lindholm, Leif; Laszl= o Ersek; Marvin H=C3=A4user >>>>>> Subject: ArmVirt and Self-Updating Code >>>>>> >>>>>> >>>>>> >>>>>> All, >>>>>> >>>>>> >>>>>> >>>>>> Marvin asked me a question on the UEFI Talkbox Discord that=E2=80=99= s a little beyond my ken=E2=80=A6 >>>>>> >>>>>> >>>>>> >>>>>> =E2=80=9CThere is self-relocating code in ArmVirtPkg: >>>>>> >>>>>> https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d178= 9b85b2cff1aaf/ArmVirtPkg/PrePi/PrePi.c#L133-L165 >>>>>> >>>>>> According to comments in the ASM, it seems like this is for Linux-= based RAM boot (I saw further stuff for KVM, so it makes sense I guess?).= It seems unfortunate it cannot be mapped into a known address range so t= hat self-relocation is not necessary, but that's out of my scope to under= stand. >>>>>> >>>>> "Mapping" implies that the MMU is on, but this code boots with the = MMU >>>>> off. Unlike x86, ARM does not define any physical address ranges th= at >>>>> are guaranteed to be backed by DRAM, so a portable image either nee= ds >>>>> to be fully position independent, or carry the metadata it needs to >>>>> relocate itself as it is invoked. >>>> And I understood it right that the idea is to use "-fpie" to >>>> 1) have all control flow instructions be position-independent (i.e. >>>> jumps, calls, etc; ARM docs don't spill it out, but vaguely imply th= is >>>> always is possible?), and >>> The primary reason to use -fpie and PIE linking is to ensure that the >>> resulting ELF executable contains a RELA section that describes every >>> location in the binary where a memory address is stored that needs to >>> be updated according to the actual placement in memory. The side >>> effect of -fpie is that position independent global references are >>> emitted (i.e., ADRP/ADD instructions which are relative to the progra= m >>> counter). However, the AArch64 compiler uses those by default anyway, >>> so for this it is not strictly needed. >>> >>>> 2) emit a GOT, which ends up being converted to PE/COFF Relocations = (-> >>>> self-relocation), for global data that cannot be referenced relative= ly? >>>> Is there any way to know/force that no symbol in GOT is accessed up >>>> until the end of the self-relocation process? Do you maybe have one final comment regarding that second question,=20 please? :) Let's drop "GOT" and make it "any instruction that requires prior=20 relocation to function correctly". >>> It is not really a GOT. Actually, a GOT is undesirable, as it forces >>> global variables to be referenced via an absolute address, even when = a >>> relative reference could be used. >> Hmm, the GCC docs say a GOT is used for "all constant addresses" (I to= ok >> it as "absolute"?), it is kind of vague. I understood it this way: >> 1) no-pie emits relocations that can target the .text and .data sectio= ns >> for instructions that embed and variables that hold an absolute addres= s >> (I thought this was RELA?) >> 2) pie emits a GOT such that there are no relocations as described in >> 1), because all absolute addresses are indirected by GOT (just GOT >> references are relocated) >> > Correct. And this works really well for shared libraries, where all > text and data sections can be shared between processes, as they will > not be modified by the loader. All locations targeted by relocations > will be nicely lumped together in the GOT. > > However, for bare metal style programs, there is no sharing, and there > is no advantage to lumping anything together. It is much better to use > relative references where possible, and simply apply relocations > wherever needed across the text and data sections, > >> If I understood the process right, but the term (GOT) is wrong, sorry, >> that is what I gathered from the docs. :) >> I have a x86 + PE background, so ARM + ELF is a bit of a learning curv= e... >> > The GOT is a special data structure used for implicit variable > accesses, i.e., global vars used in the code. Statically initialized > pointer variables are the other category, which are not code, and for > which the same considerations do not apply, given that the right value > simply needs to be stored in the variable before the program starts. > >>> For instance, a statically initialized pointer always carries an >>> absolute address, and so it always needs an entry in the RELA table >>> >>> E.g., >>> >>> int foo =3D 10; // external linkage >>> static int *bar =3D &foo; >>> >>> In this case, there is no way to use relative addressing because the >>> address of foo is taken at build time. >>> >>> However, if bar would be something like >>> >>> static int *bar() { return &foo; } >>> >>> the address is only taken at runtime, and the compiler can use a >>> relative reference instead, and no RELA entry is needed. With a GOT, >>> we force the compiler to allocate a variable that holds the absolute >>> address, which we would prefer to avoid. >> And this is not forced by whatever table -fpie uses, as per my >> understanding above? >> > The selection of 'code model' as it is called is controlled by GCC's > -mcmodel=3D argument, which defaults to 'small' on AArch64, regardless > of whether you use PIC/PIE or not. Aha, makes sense, thanks! Best regards, Marvin >>>>>> =E2=80=9CNow, StandaloneMmPkg has similar (self-)relocation code t= oo:https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d1789b85= b2cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Stan= daloneMmCoreEntryPoint.c#L379-L386 >>>>>> >>>>>> Because I cannot find such elsewhere, I assume it must be for the = same ARM virtualised environment as above. >>>>> No. >>>>> >>>>>> The binary it applies the Relocations to is documented to be the S= tandalone MM core, but in fact SecCore is located: >>>>>> >>>>>> https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d178= 9b85b2cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/= SetPermissions.c#L131-L158 >>>> As per your comments below, I think SecCore should not be located he= re. >>>> Is the Standalone MM core of *type* SecCore in the FFS (without *bei= ng* >>>> SecCore)? This confused me the most. >>>> >>> If the FFS SecCore section type is used here, it does not mean that >>> the image is a SEC image in the strict PI sense. >>> >>> Perhaps we were just too lazy to add a new type to the FFS spec? >> That is what I meant to imply with the middle question (well, not >> necessarily "lazy", for ARM there simply seems to not be any reason to >> distinguish if the environments are fully separate), just wanted to ma= ke >> sure I understand what the code does before modifying it. >> >> Thank you again! >> >> Best regards, >> Marvin >> >>>>>> =E2=80=9CThis yields the following questions to me: >>>>>> >>>>>> 1) What even invokes Standalone MM on ARM? It is documented it is = spawned during SEC, but I could not find any actual invocation. >>>>>> >>>>> It is not spawned by the normal world code that runs UEFI. It is a >>>>> secure world component that runs in a completely different executio= n >>>>> context (TrustZone). The code does run with the MMU enabled from th= e >>>>> start, but running from an a priori fixed offset was considered to = be >>>>> a security hazard, so we added self relocation support. >>>>> >>>>> The alternative would have been to add metadata to the StMmCore >>>>> component that can be interpreted by the secure world component tha= t >>>>> loads it, but this would go beyond any existing specs, and make >>>>> portability more problematic. >>>>> >>>>>> 2) Why does Standalone MM (self-)relocation locate SecCore? Should= it not already have been relocated with the code from ArmPlatformPkg? Is= Standalone MM embedded into ARM SecCore? >>>>>> >>>>> No and no. Standalone MM has nothing to do with the code that runs = as >>>>> part of UEFI itself. ArmPlatformPkg is completely separate from >>>>> StandaloneMmPkg. >>>>> >>>>>> 3) Why is SecCore the only module relocated? Are all others guaran= teed to be "properly" loaded? >>>>>> >>>>> SecCore contains a PE/COFF loader, so all subsequent modules are >>>>> loaded normally. This is similar to the ArmVirtQemuKernel >>>>> self-relocating SEC module, which only relocates itself in this >>>>> manner, and relies on standard PE/COFF metadata for loading other >>>>> modules. >>>> Interesting... this definitely is vastly different from the x86 side= of >>>> things. I think most things became very clear. Thanks a lot! >>>> >>>>>> 4) Is there maybe some high-level documented about the ARM boot fl= ow? It seems to be significantly different from the x86 routes quite vast= ly.=E2=80=9D >>>>>> >>>>> trustedfirmware.org may have some useful documentation. >>>> I'll check it some time, hopefully this weekend. Thanks! >>>> >>> My pleasure.