From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by mx.groups.io with SMTP id smtpd.web10.9174.1627050875054230983 for ; Fri, 23 Jul 2021 07:34:35 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=PCgyaGK8; spf=pass (domain: kernel.org, ip: 198.145.29.99, mailfrom: ardb@kernel.org) Received: by mail.kernel.org (Postfix) with ESMTPSA id E2F6160F02 for ; Fri, 23 Jul 2021 14:34:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1627050873; bh=09vujGvTjSUse/A/4loKghgg0IZjsYzEW+xkCB/Mw28=; h=References:In-Reply-To:From:Date:Subject:To:Cc:From; b=PCgyaGK8YGUfuytNIQO9yCT7pHaLGmcWdgd8Ll7DLqiDN2jkN6b2wcBbzHgYKkJbI nNKCTD3+YF6v1MTvVzGevOUI1ME6L5O0U8vlAs2NrIYQDfnukW6Aa0dWl+lKdRffQc PQ5fqUkohIfJzeP4WwNJl4QQdksva/bQHWjGru1om0luRrrRlyWwdyWsNIRym8jNAe JFe3JiJMlMyhe7TDQi2KZGdN/Y+fzKkFh3lLrQTeybDKNBKh+zb8RM7rwSA4o7l2UF +b0bgyfWVO7kqZ+JM958I0JnCBlV4Iew6D5mAZDw63SZFNEYnpP8xZ2gQB4YZOlCxd 1qQSs9FNj7RNQ== Received: by mail-oi1-f173.google.com with SMTP id t128so2061780oig.1 for ; Fri, 23 Jul 2021 07:34:33 -0700 (PDT) X-Gm-Message-State: AOAM5308w7VGAUZjn+WK6oX4ioq2xdBGi0vF6L2+liKjnawDCLAKEW30 iy8DR/dGxGx59roiYvdHNNWpJ7WAdhYtVTjLeTk= X-Google-Smtp-Source: ABdhPJzftw5iCP1clTd9CBVq700TIN5hDnZg0+dkukHglxR3D2I3uKvMKN3Xpi228XzetFWHS8xKabAuOT7Q5S3R4Zk= X-Received: by 2002:aca:d64d:: with SMTP id n74mr9061607oig.47.1627050873284; Fri, 23 Jul 2021 07:34:33 -0700 (PDT) MIME-Version: 1.0 References: <36b32106-da0e-bfd5-10cf-6c9bb86173d1@posteo.de> <39afb072-3e01-6946-9387-e414a8f62f8d@posteo.de> In-Reply-To: <39afb072-3e01-6946-9387-e414a8f62f8d@posteo.de> From: "Ard Biesheuvel" Date: Fri, 23 Jul 2021 16:34:22 +0200 X-Gmail-Original-Message-ID: Message-ID: Subject: Re: ArmVirt and Self-Updating Code To: =?UTF-8?Q?Marvin_H=C3=A4user?= Cc: Bret Barkelew , Thomas Abraham , "Ard Biesheuvel (TianoCore)" , "Lindholm, Leif" , Laszlo Ersek , Sami Mujawar , "devel@edk2.groups.io" , nd Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Fri, 23 Jul 2021 at 16:27, Marvin H=C3=A4user wrote= : > > > > 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: ... > >>>> 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, > 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. 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 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/17143c4837393d42c484b42d1789b85b2= cff1aaf/StandaloneMmPkg/Library/StandaloneMmCoreEntryPoint/AArch64/Standalo= neMmCoreEntryPoint.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/Se= tPermissions.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 S= tandalone 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 vastly= .=E2=80=9D > >>>>>> > >>>>> trustedfirmware.org may have some useful documentation. > >>>> I'll check it some time, hopefully this weekend. Thanks! > >>>> > >>> My pleasure. >