linux-arm-kernel.lists.infradead.org archive mirror
 help / color / mirror / Atom feed
* [Query] arm64: Right approach to support Image.gz file type via kexec_file_load()
@ 2019-06-19 21:23 Bhupesh Sharma
  2019-06-20 15:28 ` James Morse
  0 siblings, 1 reply; 4+ messages in thread
From: Bhupesh Sharma @ 2019-06-19 21:23 UTC (permalink / raw)
  To: linux-arm-kernel, Will Deacon
  Cc: Mark Rutland, matthewgarrett, Ard Biesheuvel, Catalin Marinas,
	kexec, AKASHI Takahiro, James Morse, Bhupesh SHARMA

Hi,

Since most distributions use 'make zinstall' rule inside 
'arch/arm64/boot/Makefile' (see [1] for details) to install the arm64 
Image.gz compressed file inside the boot destination directory (for e.g. 
/boot), currently we cannot use kexec_file_load() to load vmlinuz (or 
Image.gz):

# file /boot/vmlinuz
/boot/vmlinuz: gzip compressed data, was "Image", <..snip..>, max 
compression, from Unix, original size 21945120

Now, since via kexec_file_load() we pass the 'fd' of Image.gz 
(compressed file) via the following command line ...

# kexec -s -l /boot/vmlinuz-`uname -r` --initrd=/boot/initramfs-`uname 
-r`.img --reuse-cmdline

... kernel returns -EINVAL error value, as it is not able to locate the 
magic number  =0x644d5241, which is expected in the 64-byte header of 
the decompressed kernel image (see [2] for details):

The decompressed kernel image contains a 64-byte header as follows:
<..snip..>
   u32 magic	= 0x644d5241;	/* Magic number, little endian, "ARM\x64" */
<..snip..>

I can figure out two ways to address this:

1. Add support in user-space kexec-tools (for which I have a RFC patch 
ready), which handles an 'Image.gz' being passed via kexec_file_load(), 
using an approach as follows:

a). Copy the contents of Image.gz to a temporary file.
b). Decompress (gunzip-decompress) the contents inside the temporary file.
c). Pass the 'fd' of the temporary file to the kernel space. So 
basically the kernel space still gets a decompressed kernel image to 
load via kexec_tools

This seems to have the following pros and cons, which I can think of:

Pros:
  - Changes can be handled in the user-space (kexec_tools) and no 
changes are required in kernel space for handling the 
unsigned/non-secure boot case.

Cons:
  - One obvious issue is how to handle the signed kernel Image.gz, 
because signature verification is managed inside the kernel, so handling 
a signed Image.gz would require kernel intervention eventually.
  - Passing decompressed image from user-space requires the kernel to 
read large amount of data from the user-space.

2. Add support in kernel (for which I have a RFC patch ready), which 
handles an 'Image.gz' being passed via kexec_file_load(), using an 
approach as follows:

a). Define a 'arch_kexec_kernel_image_probe' for arm64, which overrides 
the __weak definition in 'kernel/kexec_file.c'
b). Inside 'arch_kexec_kernel_image_probe' for arm64, check if we have 
been passed a  magic header  0x1f, 0x8b (\037 \213) which indicates a 
'gzip format' Image file.
b). Decompress the contents inside a buffer using a decompress_kernel() 
-> gunzip() -> inflate() logic.

This seems to have the following pros and cons, which I can think of:

Pros:
  - Handling signed Image.gz becomes easier in the kernel itself.

Cons:
  - One needs to add a decompress_kernel() -> gunzip() -> inflate() 
kind-of logic in kernel space to handle gzipp'ed image for arm64.

So, I was wondering which approach should be more suitable - fixing this 
in user-space v/s fix this in kernel-space.

Please let me know so that I can send out a RFC patch for the same.

[1]. https://github.com/torvalds/linux/blob/master/arch/arm64/boot/Makefile
[2]. https://www.kernel.org/doc/Documentation/arm64/booting.txt

Thanks,
Bhupesh

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Query] arm64: Right approach to support Image.gz file type via kexec_file_load()
  2019-06-19 21:23 [Query] arm64: Right approach to support Image.gz file type via kexec_file_load() Bhupesh Sharma
@ 2019-06-20 15:28 ` James Morse
  2019-06-24  5:59   ` Bhupesh Sharma
  0 siblings, 1 reply; 4+ messages in thread
From: James Morse @ 2019-06-20 15:28 UTC (permalink / raw)
  To: Bhupesh Sharma
  Cc: Mark Rutland, matthewgarrett, Ard Biesheuvel, Catalin Marinas,
	Will Deacon, AKASHI Takahiro, Bhupesh SHARMA, kexec,
	linux-arm-kernel

Hi Bhupesh,

On 19/06/2019 22:23, Bhupesh Sharma wrote:
> Since most distributions use 'make zinstall' rule inside 'arch/arm64/boot/Makefile' (see
> [1] for details) to install the arm64 Image.gz compressed file inside the boot destination
> directory (for e.g. /boot), currently we cannot use kexec_file_load() to load vmlinuz (or
> Image.gz):

It's not just kexec_file_load(), we don't support booting from compressed or elf image
formats either: the bootloader has to decompress any Image.gz before it can run it.


> ... kernel returns -EINVAL error value, as it is not able to locate the magic number 
> =0x644d5241, which is expected in the 64-byte header of the decompressed kernel image


> I can figure out two ways to address this:
> 
> 1. Add support in user-space kexec-tools (for which I have a RFC patch ready), which
> handles an 'Image.gz' being passed via kexec_file_load(), using an approach as follows:
> 
> a). Copy the contents of Image.gz to a temporary file.
> b). Decompress (gunzip-decompress) the contents inside the temporary file.
> c). Pass the 'fd' of the temporary file to the kernel space. So basically the kernel space
> still gets a decompressed kernel image to load via kexec_tools

Sounds reasonable.
(I guess you need to decompress it first to know the size to pass to kexec_file_load(),
hence the intermediate copy)


> This seems to have the following pros and cons, which I can think of:
> 
> Pros:
>  - Changes can be handled in the user-space (kexec_tools) and no changes are required in
> kernel space for handling the unsigned/non-secure boot case.
> 
> Cons:
>  - One obvious issue is how to handle the signed kernel Image.gz, because signature
> verification is managed inside the kernel, so handling a signed Image.gz would require
> kernel intervention eventually.

How do you sign an Image.gz? Isn't the signature written into the PE header?


>  - Passing decompressed image from user-space requires the kernel to read large amount of
> data from the user-space.

The kernel can't decompress itself, so this large amount of data has to be moved at some
point.


> 2. Add support in kernel (for which I have a RFC patch ready), which handles an 'Image.gz'
> being passed via kexec_file_load(), using an approach as follows:
> 
> a). Define a 'arch_kexec_kernel_image_probe' for arm64, which overrides the __weak
> definition in 'kernel/kexec_file.c'
> b). Inside 'arch_kexec_kernel_image_probe' for arm64, check if we have been passed a 
> magic header  0x1f, 0x8b (\037 \213) which indicates a 'gzip format' Image file.
> b). Decompress the contents inside a buffer using a decompress_kernel() -> gunzip() ->
> inflate() logic.
> 
> This seems to have the following pros and cons, which I can think of:
> 
> Pros:
>  - Handling signed Image.gz becomes easier in the kernel itself.

I don't follow: you can't boot this, so why would you sign it?


> Cons:
>  - One needs to add a decompress_kernel() -> gunzip() -> inflate() kind-of logic in kernel
> space to handle gzipp'ed image for arm64.

We support gzipped initramfs so the code already exists. More of a problem is kdump (which
we don't yet support), which has to fit in the reserved crashkernel region, and we won't
know the size of the compressed image until we've decompressed it. (its just fiddly)


> So, I was wondering which approach should be more suitable - fixing this in user-space v/s
> fix this in kernel-space.

As user-space can do this, I think it should!


Thanks,

James

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Query] arm64: Right approach to support Image.gz file type via kexec_file_load()
  2019-06-20 15:28 ` James Morse
@ 2019-06-24  5:59   ` Bhupesh Sharma
  2019-06-24 17:35     ` James Morse
  0 siblings, 1 reply; 4+ messages in thread
From: Bhupesh Sharma @ 2019-06-24  5:59 UTC (permalink / raw)
  To: James Morse
  Cc: Mark Rutland, Ard Biesheuvel, Catalin Marinas, matthewgarrett,
	Will Deacon, AKASHI Takahiro, Bhupesh SHARMA, kexec,
	linux-arm-kernel

Hi James,

Many thanks for your inputs. Please see my comments inline:

On 06/20/2019 08:58 PM, James Morse wrote:
> Hi Bhupesh,
> 
> On 19/06/2019 22:23, Bhupesh Sharma wrote:
>> Since most distributions use 'make zinstall' rule inside 'arch/arm64/boot/Makefile' (see
>> [1] for details) to install the arm64 Image.gz compressed file inside the boot destination
>> directory (for e.g. /boot), currently we cannot use kexec_file_load() to load vmlinuz (or
>> Image.gz):
> 
> It's not just kexec_file_load(), we don't support booting from compressed or elf image
> formats either: the bootloader has to decompress any Image.gz before it can run it.

That's correct.

>> ... kernel returns -EINVAL error value, as it is not able to locate the magic number
>> =0x644d5241, which is expected in the 64-byte header of the decompressed kernel image
> 
> 
>> I can figure out two ways to address this:
>>
>> 1. Add support in user-space kexec-tools (for which I have a RFC patch ready), which
>> handles an 'Image.gz' being passed via kexec_file_load(), using an approach as follows:
>>
>> a). Copy the contents of Image.gz to a temporary file.
>> b). Decompress (gunzip-decompress) the contents inside the temporary file.
>> c). Pass the 'fd' of the temporary file to the kernel space. So basically the kernel space
>> still gets a decompressed kernel image to load via kexec_tools
> 
> Sounds reasonable.
> (I guess you need to decompress it first to know the size to pass to kexec_file_load(),
> hence the intermediate copy)

That's correct.

>> This seems to have the following pros and cons, which I can think of:
>>
>> Pros:
>>   - Changes can be handled in the user-space (kexec_tools) and no changes are required in
>> kernel space for handling the unsigned/non-secure boot case.
>>
>> Cons:
>>   - One obvious issue is how to handle the signed kernel Image.gz, because signature
>> verification is managed inside the kernel, so handling a signed Image.gz would require
>> kernel intervention eventually.
> 
> How do you sign an Image.gz? Isn't the signature written into the PE header?

That's correct, normally in user-land one uses standard signing 
utilities like the sbsign tools (see [1]). For example I use the 
following method to sign the decompressed kernel Image:

$ sbsign --key ${KEY} --cert ${CERT} Image --output Image.signed

I generally use 'certs/signing_key.pem' [which is intended to be used
for module signing (CONFIG_MODULE_SIG)], as ${KEY} and ${CERT} for test 
purposes.

Now if CONFIG_KEXEC_VERIFY_SIG is enabled, kexec_file_load() invokes an 
arch-defined (and hence file-format-specific) hook function to check for 
the validity of kernel binary. So a normal 'kexec -s' invocation with 
the signed Image works fine with the current upstream code (and latest 
upstream kexec-tools)

$ kexec -s -l Image.signed --initrd=/boot/initramfs-`uname -r`.img 
--reuse-cmdline

The problem happens when we have a Image.gz instead of a decompressed 
Image in distro environments.

Now the process becomes a lot more complicated:

- User uses sbsign tool to sign Image.gz, lets call the resulting file 
as Image.gz.signed

- kexec_file_load() is invoked using a command line resembling something 
like:

$ kexec -s -l Image.gz.signed --initrd=/boot/initramfs-`uname -r`.img 
--reuse-cmdline

- Now since kexec_tools (user land) has no support for parsing the 
signature appended before the Image.gz file (using which it creates a 
decompressed Image file) and then to re-sign the resulting Image file 
(before it is passed as a fd to the syscall), I am not sure how this can 
be handled in user-land appropriately.

[1] https://build.opensuse.org/package/show/home:jejb1:UEFI/sbsigntools

>>   - Passing decompressed image from user-space requires the kernel to read large amount of
>> data from the user-space.
> 
> The kernel can't decompress itself, so this large amount of data has to be moved at some
> point.
> 
> 
>> 2. Add support in kernel (for which I have a RFC patch ready), which handles an 'Image.gz'
>> being passed via kexec_file_load(), using an approach as follows:
>>
>> a). Define a 'arch_kexec_kernel_image_probe' for arm64, which overrides the __weak
>> definition in 'kernel/kexec_file.c'
>> b). Inside 'arch_kexec_kernel_image_probe' for arm64, check if we have been passed a
>> magic header  0x1f, 0x8b (\037 \213) which indicates a 'gzip format' Image file.
>> b). Decompress the contents inside a buffer using a decompress_kernel() -> gunzip() ->
>> inflate() logic.
>>
>> This seems to have the following pros and cons, which I can think of:
>>
>> Pros:
>>   - Handling signed Image.gz becomes easier in the kernel itself.
> 
> I don't follow: you can't boot this, so why would you sign it?


Because that's what most distributions do normally (I share some signing
rules as a reference below) - if the gzipped EFI images are present then 
they sign them via
pesign tool (see 
<http://manpages.ubuntu.com/manpages/bionic/man1/pesign.1.html>)

  %if %{signkernel}
     # Sign the image if we're using EFI
     # aarch64 kernels are gziped EFI images
     KernelExtension=${KernelImage##*.}
     if [ "$KernelExtension" == "gz" ]; then
         SignImage=${KernelImage%.*}
     else
         SignImage=$KernelImage
     fi

Thanks,
Bhupesh

>> Cons:
>>   - One needs to add a decompress_kernel() -> gunzip() -> inflate() kind-of logic in kernel
>> space to handle gzipp'ed image for arm64.
> 
> We support gzipped initramfs so the code already exists. More of a problem is kdump (which
> we don't yet support), which has to fit in the reserved crashkernel region, and we won't
> know the size of the compressed image until we've decompressed it. (its just fiddly)
> 
> 
>> So, I was wondering which approach should be more suitable - fixing this in user-space v/s
>> fix this in kernel-space.
> 
> As user-space can do this, I think it should!
> 
> 
> Thanks,
> 
> James
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Query] arm64: Right approach to support Image.gz file type via kexec_file_load()
  2019-06-24  5:59   ` Bhupesh Sharma
@ 2019-06-24 17:35     ` James Morse
  0 siblings, 0 replies; 4+ messages in thread
From: James Morse @ 2019-06-24 17:35 UTC (permalink / raw)
  To: Bhupesh Sharma
  Cc: Mark Rutland, Ard Biesheuvel, Catalin Marinas, matthewgarrett,
	Will Deacon, AKASHI Takahiro, Bhupesh SHARMA, kexec,
	linux-arm-kernel

Hi Bhupesh,

On 24/06/2019 06:59, Bhupesh Sharma wrote:
> On 06/20/2019 08:58 PM, James Morse wrote:
>> On 19/06/2019 22:23, Bhupesh Sharma wrote:
>>> Since most distributions use 'make zinstall' rule inside 'arch/arm64/boot/Makefile' (see
>>> [1] for details) to install the arm64 Image.gz compressed file inside the boot destination
>>> directory (for e.g. /boot), currently we cannot use kexec_file_load() to load vmlinuz (or
>>> Image.gz):
>>
>> It's not just kexec_file_load(), we don't support booting from compressed or elf image
>> formats either: the bootloader has to decompress any Image.gz before it can run it.
> 
> That's correct.
> 
>>> ... kernel returns -EINVAL error value, as it is not able to locate the magic number
>>> =0x644d5241, which is expected in the 64-byte header of the decompressed kernel image


>>> This seems to have the following pros and cons, which I can think of:
>>>
>>> Pros:
>>>   - Changes can be handled in the user-space (kexec_tools) and no changes are required in
>>> kernel space for handling the unsigned/non-secure boot case.
>>>
>>> Cons:
>>>   - One obvious issue is how to handle the signed kernel Image.gz, because signature
>>> verification is managed inside the kernel, so handling a signed Image.gz would require
>>> kernel intervention eventually.

>> How do you sign an Image.gz? Isn't the signature written into the PE header?

> That's correct, normally in user-land one uses standard signing utilities like the sbsign
> tools (see [1]). For example I use the following method to sign the decompressed kernel
> Image:
> 
> $ sbsign --key ${KEY} --cert ${CERT} Image --output Image.signed

| morse@eglon:~/kernel/linux/build_arm64$ sbsign --key certs/signing_key.pem  --cert \
|   certs/signing_key.pem arch/arm64/boot/Image.gz
| Invalid DOS header magic

... because that gzip file isn't a PE32+ that can be loaded by UEFI.


> The problem happens when we have a Image.gz instead of a decompressed Image in distro
> environments.
> 
> Now the process becomes a lot more complicated:
> 
> - User uses sbsign tool to sign Image.gz, lets call the resulting file as Image.gz.signed

Secure Boot is the reason for all this signature stuff. Having only one way these things
get signed means it will work on any platform that supports signatures. Supporting
multiple formats means potentially multiple, conflicting, signatures.


Image.gz isn't a PE32+ file, so wherever sbsign puts the signature, it isn't somewhere the
kernel or UEFI know how to validate it.


> - kexec_file_load() is invoked using a command line resembling something like:
> 
> $ kexec -s -l Image.gz.signed --initrd=/boot/initramfs-`uname -r`.img --reuse-cmdline
> 
> - Now since kexec_tools (user land) has no support for parsing the signature appended
> before the Image.gz file (using which it creates a decompressed Image file) and then to
> re-sign the resulting Image file (before it is passed as a fd to the syscall), I am not
> sure how this can be handled in user-land appropriately.

Surely the right thing to do here is unzip the file, sign it, re-compress it.
It has been compressed to save space. The bootloader/grub has to uncompress it before if
can get get UEFI to boot it.
I'm pretty sure you can't point the efi boot variables at a gzip file.

(UEFI has its own compression scheme in appendix H, I can't find any mention of gzip in
the spec)


>>> 2. Add support in kernel (for which I have a RFC patch ready), which handles an 'Image.gz'
>>> being passed via kexec_file_load(), using an approach as follows:
>>>
>>> a). Define a 'arch_kexec_kernel_image_probe' for arm64, which overrides the __weak
>>> definition in 'kernel/kexec_file.c'
>>> b). Inside 'arch_kexec_kernel_image_probe' for arm64, check if we have been passed a
>>> magic header  0x1f, 0x8b (\037 \213) which indicates a 'gzip format' Image file.
>>> b). Decompress the contents inside a buffer using a decompress_kernel() -> gunzip() ->
>>> inflate() logic.
>>>
>>> This seems to have the following pros and cons, which I can think of:
>>>
>>> Pros:
>>>   - Handling signed Image.gz becomes easier in the kernel itself.
>>
>> I don't follow: you can't boot this, so why would you sign it?
> 
> 
> Because that's what most distributions do normally (I share some signing
> rules as a reference below) - if the gzipped EFI images are present then they sign them via
> pesign tool (see <http://manpages.ubuntu.com/manpages/bionic/man1/pesign.1.html>)

Do they expect platform firmware to boot these? It doesn't work for me:
| FS0:\> Image.gz
| Unloading driver at 0x00000000000
| Error reported: Unsupported
| FS0:\> Image
| Loading driver at 0x087F9180000 EntryPoint=0x087FA445F98
| EFI stub: Booting Linux Kernel...

It's grub's gzip module that does the decompression. In the same way we expect kexec-tools
to decompress the blob to feed kexec_file_load the kernel Image.

If you decompress the Image.gz, sign it, re-compress it it should all just work.


Thanks,

James

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-06-24 17:35 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-19 21:23 [Query] arm64: Right approach to support Image.gz file type via kexec_file_load() Bhupesh Sharma
2019-06-20 15:28 ` James Morse
2019-06-24  5:59   ` Bhupesh Sharma
2019-06-24 17:35     ` James Morse

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).