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.web11.1253.1627758524561708161 for ; Sat, 31 Jul 2021 12:08:45 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="body hash did not verify" header.i=@posteo.de header.s=2017 header.b=PgY1A7g/; 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 ACC29240109 for ; Sat, 31 Jul 2021 21:08:41 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.de; s=2017; t=1627758521; bh=0dUL7kLUB5cDywFJF4MBSlstUavFSmkWJllquo3rXFU=; h=Subject:To:Cc:From:Date:From; b=PgY1A7g/9NDgnqLNUNqYg3Q6X3eeqxwzq0XZVS2mV+N7LZ8E2PoTnVA2mDkLxRHpa /zWY9cvDXNxHq15rkLfNCE6TREcCFxV6x7Ee6l3CX0X9F16IJ5OW46v9KvImqUnSTH gxH2EW5dnSdnX/9JtVfUdcNNXHB2+FkMV8KAxEf+TGUfM1iU064Dmy1kuwQA4mXLSZ rwTlzRhtjc6/tNn4jwMSCZyAHCY+bUriqJxCrm8+xdSNyaVYhKSd3r96muCAGmrY3F peVOoEz4sqOH6XmMz7tXqlg5On/R1wTDhbR3CO0BuBV+Qz+ER96RLcOo7ka12W9Qgo SpUNWy+NNERng== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4GcYhS2mXRz6tnD; Sat, 31 Jul 2021 21:08:40 +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> <39afb072-3e01-6946-9387-e414a8f62f8d@posteo.de> From: =?UTF-8?B?TWFydmluIEjDpHVzZXI=?= Message-ID: Date: Sat, 31 Jul 2021 19:08:39 +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:34, Ard Biesheuvel wrote: > On Fri, 23 Jul 2021 at 16:27, Marvin H=C3=A4user w= rote: >> >> >> On 23.07.21 16:09, Ard Biesheuvel wrote: >>> On Fri, 23 Jul 2021 at 12:47, Marvin H=C3=A4user = wrote: >>>> On 23.07.21 12:13, Ard Biesheuvel wrote: >>>>> On Fri, 23 Jul 2021 at 11:55, Marvin H=C3=A4user wrote: > ... >>>>>> 2) emit a GOT, which ends up being converted to PE/COFF Relocation= s (-> >>>>>> self-relocation), for global data that cannot be referenced relati= vely? >>>>>> Is there any way to know/force that no symbol in GOT is accessed u= p >>>>>> until the end of the self-relocation process? >> Do you maybe have one final comment regarding that second question, >> please? :) > The RELA section is not converted into PE/COFF relocations. This would > not achieve a lot, given that no prior PE/COFF loader exists to > process them. There is a snippet of asm code in the startup code that > processes the R_AARCH64_RELATIVE relocation entries before calling > into C code. I searched for said ASM code till my fingers fell asleep and at last=20 found this:=20 https://github.com/tianocore/edk2/commit/b16fd231f6d8124fa05a0f086840934b= 8709faf9#diff-3d563cc4775c7720900f4895bf619eed06291044aaa277fcc57eddc7618= 351a1L12-R148 If I understand the commit message correctly, it is basically "pray the=20 C code does not use globals at all", which is fair enough, so maybe I=20 should document this in my proposed new library? I trust that this is=20 enough of a constraint for both ARM and AArch64, because I do not know=20 them at all. What worries me is that StandaloneMmCore has no such ASM entry point at=20 all and instead it's just executing C directly. Also, it is not passed=20 the "-fno-jump-tables" flag that is commented to be important in the=20 commit linked above. Best regards, Marvin > This also gives us the guarantee that no GOT indirections are > dereferenced, given that our asm code simply does not do that. > >> Let's drop "GOT" and make it "any instruction that requires prior >> relocation to function correctly". >> > The thing to keep in mind here is that R_AARCH64_RELATIVE relocations > never target instructions, but only memory locations that carry > absolute addresses. This could be locations in .rodata or .data > (global vars carrying pointer values), or GOT entries. > >>>>> It is not really a GOT. Actually, a GOT is undesirable, as it force= s >>>>> global variables to be referenced via an absolute address, even whe= n a >>>>> relative reference could be used. >>>> Hmm, the GCC docs say a GOT is used for "all constant addresses" (I = took >>>> 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 sect= ions >>>> for instructions that embed and variables that hold an absolute addr= ess >>>> (I thought this was RELA?) >>>> 2) pie emits a GOT such that there are no relocations as described i= n >>>> 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 ther= e >>> is no advantage to lumping anything together. It is much better to us= e >>> 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, sorr= y, >>>> that is what I gathered from the docs. :) >>>> I have a x86 + PE background, so ARM + ELF is a bit of a learning cu= rve... >>>> >>> 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 valu= e >>> 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 th= e >>>>> 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 absolut= e >>>>> 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, regardles= s >>> of whether you use PIC/PIE or not. >> Aha, makes sense, thanks! >> >> Best regards, >> Marvin >> >>>>>>>> =E2=80=9CNow, StandaloneMmPkg has similar (self-)relocation code= too:https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d1789b= 85b2cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/St= andaloneMmCoreEntryPoint.c#L379-L386 >>>>>>>> >>>>>>>> Because I cannot find such elsewhere, I assume it must be for th= e same ARM virtualised environment as above. >>>>>>> No. >>>>>>> >>>>>>>> The binary it applies the Relocations to is documented to be the= Standalone MM core, but in fact SecCore is located: >>>>>>>> >>>>>>>> https://github.com/tianocore/edk2/blob/17143c4837393d42c484b42d1= 789b85b2cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch6= 4/SetPermissions.c#L131-L158 >>>>>> As per your comments below, I think SecCore should not be located = here. >>>>>> Is the Standalone MM core of *type* SecCore in the FFS (without *b= eing* >>>>>> 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 = make >>>> 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 i= s 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 execut= ion >>>>>>> context (TrustZone). The code does run with the MMU enabled from = the >>>>>>> start, but running from an a priori fixed offset was considered t= o 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 t= hat >>>>>>> loads it, but this would go beyond any existing specs, and make >>>>>>> portability more problematic. >>>>>>> >>>>>>>> 2) Why does Standalone MM (self-)relocation locate SecCore? Shou= ld 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 run= s as >>>>>>> part of UEFI itself. ArmPlatformPkg is completely separate from >>>>>>> StandaloneMmPkg. >>>>>>> >>>>>>>> 3) Why is SecCore the only module relocated? Are all others guar= anteed 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 si= de of >>>>>> things. I think most things became very clear. Thanks a lot! >>>>>> >>>>>>>> 4) Is there maybe some high-level documented about the ARM boot = flow? It seems to be significantly different from the x86 routes quite va= stly.=E2=80=9D >>>>>>>> >>>>>>> trustedfirmware.org may have some useful documentation. >>>>>> I'll check it some time, hopefully this weekend. Thanks! >>>>>> >>>>> My pleasure.