From: Eric W. Biederman <hidden> Date: 2016-07-12 13:38:30
AKASHI Takahiro [off-list ref] writes:
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
Nacked-by: "Eric W. Biederman" [off-list ref]
I am happy to see support for other architectures, but for the sake of
not moving some code in the kernel let's not build an attackable
infrastructure.
Eric
Hello Eric,
Am Dienstag, 12 Juli 2016, 08:25:48 schrieb Eric W. Biederman:
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
There are situations where userspace needs to change things in the device
tree to be used by the next kernel.
For example, Petitboot (the boot loader used in OpenPOWER machines) is a
userspace application running in an intermediary Linux instance and uses
kexec to load the target OS. It has to modify the device tree that will be
used by the next kernel so that the next kernel uses the same console that
petitboot was configured to use (i.e., set the /chosen/linux,stdout-path
property). It also modifies the device tree to allow the kernel to inherit
Petitboot's Openfirmware framebuffer.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
On Tue, Jul 12, 2016 at 10:58:09AM -0300, Thiago Jung Bauermann wrote:
Hello Eric,
Am Dienstag, 12 Juli 2016, 08:25:48 schrieb Eric W. Biederman:
quoted
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
There are situations where userspace needs to change things in the device
tree to be used by the next kernel.
For example, Petitboot (the boot loader used in OpenPOWER machines) is a
userspace application running in an intermediary Linux instance and uses
kexec to load the target OS. It has to modify the device tree that will be
used by the next kernel so that the next kernel uses the same console that
petitboot was configured to use (i.e., set the /chosen/linux,stdout-path
property). It also modifies the device tree to allow the kernel to inherit
Petitboot's Openfirmware framebuffer.
Can some of this be done with the help of kernel command line options for
second kernel?
Vivek
From: Stewart Smith <hidden> Date: 2016-07-12 23:46:01
Vivek Goyal [off-list ref] writes:
On Tue, Jul 12, 2016 at 10:58:09AM -0300, Thiago Jung Bauermann wrote:
quoted
Hello Eric,
Am Dienstag, 12 Juli 2016, 08:25:48 schrieb Eric W. Biederman:
quoted
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
There are situations where userspace needs to change things in the device
tree to be used by the next kernel.
For example, Petitboot (the boot loader used in OpenPOWER machines) is a
userspace application running in an intermediary Linux instance and uses
kexec to load the target OS. It has to modify the device tree that will be
used by the next kernel so that the next kernel uses the same console that
petitboot was configured to use (i.e., set the /chosen/linux,stdout-path
property). It also modifies the device tree to allow the kernel to inherit
Petitboot's Openfirmware framebuffer.
Can some of this be done with the help of kernel command line options for
second kernel?
how would this be any more secure?
Passing in an address for a framebuffer via command line option means
you could scribble over any bit of memory, which is the same kind of
damage you could do by modifying the device tree.
--
Stewart Smith
OPAL Architect, IBM.
On Wed, Jul 13, 2016 at 09:45:22AM +1000, Stewart Smith wrote:
Vivek Goyal [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:09AM -0300, Thiago Jung Bauermann wrote:
quoted
Hello Eric,
Am Dienstag, 12 Juli 2016, 08:25:48 schrieb Eric W. Biederman:
quoted
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
There are situations where userspace needs to change things in the device
tree to be used by the next kernel.
For example, Petitboot (the boot loader used in OpenPOWER machines) is a
userspace application running in an intermediary Linux instance and uses
kexec to load the target OS. It has to modify the device tree that will be
used by the next kernel so that the next kernel uses the same console that
petitboot was configured to use (i.e., set the /chosen/linux,stdout-path
property). It also modifies the device tree to allow the kernel to inherit
Petitboot's Openfirmware framebuffer.
Can some of this be done with the help of kernel command line options for
second kernel?
how would this be any more secure?
Passing in an address for a framebuffer via command line option means
you could scribble over any bit of memory, which is the same kind of
damage you could do by modifying the device tree.
It is not necessarily safer but works with given framework and we don't
have to modify existing system call.
Also it will allow you to pass in only one thing at a time instead of
allowing passing in new unsigned DTB, which can potentially do lot more.
Vivek
On Tuesday, July 12, 2016 8:25:48 AM CEST Eric W. Biederman wrote:
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
Nacked-by: "Eric W. Biederman" [off-list ref]
I am happy to see support for other architectures, but for the sake of
not moving some code in the kernel let's not build an attackable
infrastructure.
For historic context, the flattened devicetree format that we now use
to pass data about the system from boot loader to kernel was initially
introduced specifically for the purpose of enabling kexec:
On Open Firmware, the DT is extracted from running firmware and copied
into dynamically allocated data structures. After a kexec, the runtime
interface to the firmware is not available, so the flattened DT format
was created as a way to pass the same data in a binary blob to the new
kernel in a format that can be read from the kernel by walking the
directories in /proc/device-tree/*.
There are a couple of reasons for modifying the devicetree:
- For kboot/petitboot, you can have a kernel that is not booted through
DT at all but hardwired to a particular machine, and that passes
a DT for the entire hardware to the kernel that you actually want to
run.
- for kdump, you need to tell the new kernel about the modified location
of the memory, so the dump kernel doesn't overwrite the contents
it wants to dump
- we typically ship devicetree sources for embedded machines with the
kernel sources. As more hardware of the system gets enabled, the
devicetree gains extra nodes and properties that describe the hardware
more completely, so we need to use the latest DT blob to use all
the drivers
- in some cases, kernels will fail to boot at all with an older version
of the DT, or fail to use the devices that were working on the
earlier kernel. This is usually considered a bug, but it's not rare
- In some cases, the kernel can update its DT at runtime, and the new
settings are expected to be available in the new kernel too, though
there are cases where you actually don't want the modified contents.
Arnd
On Tue, Jul 12, 2016 at 04:02:46PM +0200, Arnd Bergmann wrote:
On Tuesday, July 12, 2016 8:25:48 AM CEST Eric W. Biederman wrote:
quoted
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
Nacked-by: "Eric W. Biederman" [off-list ref]
I am happy to see support for other architectures, but for the sake of
not moving some code in the kernel let's not build an attackable
infrastructure.
For historic context, the flattened devicetree format that we now use
to pass data about the system from boot loader to kernel was initially
introduced specifically for the purpose of enabling kexec:
On Open Firmware, the DT is extracted from running firmware and copied
into dynamically allocated data structures. After a kexec, the runtime
interface to the firmware is not available, so the flattened DT format
was created as a way to pass the same data in a binary blob to the new
kernel in a format that can be read from the kernel by walking the
directories in /proc/device-tree/*.
So this DT is available inside kernel and running kernel can still
retrieve it and pass it to second kernel?
There are a couple of reasons for modifying the devicetree:
- For kboot/petitboot, you can have a kernel that is not booted through
DT at all but hardwired to a particular machine, and that passes
a DT for the entire hardware to the kernel that you actually want to
run.
- for kdump, you need to tell the new kernel about the modified location
of the memory, so the dump kernel doesn't overwrite the contents
it wants to dump
In x86 we do this with the help of kernel command line options.
- we typically ship devicetree sources for embedded machines with the
kernel sources. As more hardware of the system gets enabled, the
devicetree gains extra nodes and properties that describe the hardware
more completely, so we need to use the latest DT blob to use all
the drivers
- in some cases, kernels will fail to boot at all with an older version
of the DT, or fail to use the devices that were working on the
earlier kernel. This is usually considered a bug, but it's not rare
- In some cases, the kernel can update its DT at runtime, and the new
settings are expected to be available in the new kernel too, though
there are cases where you actually don't want the modified contents.
I am assuming that modified DT and unmodifed one both are accessible to
kernel. And if user space can make decisions which modfied fields to use
for new kernels and which ones not, then same can be done in kernel too?
Vivek
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
quoted
On Open Firmware, the DT is extracted from running firmware and copied
into dynamically allocated data structures. After a kexec, the runtime
interface to the firmware is not available, so the flattened DT format
was created as a way to pass the same data in a binary blob to the new
kernel in a format that can be read from the kernel by walking the
directories in /proc/device-tree/*.
So this DT is available inside kernel and running kernel can still
retrieve it and pass it to second kernel?
The kernel only uses the flattened DT blob at boot time and converts
it into the runtime data structures (struct device_node). The original
dtb is typically overwritten later.
quoted
- we typically ship devicetree sources for embedded machines with the
kernel sources. As more hardware of the system gets enabled, the
devicetree gains extra nodes and properties that describe the hardware
more completely, so we need to use the latest DT blob to use all
the drivers
- in some cases, kernels will fail to boot at all with an older version
of the DT, or fail to use the devices that were working on the
earlier kernel. This is usually considered a bug, but it's not rare
- In some cases, the kernel can update its DT at runtime, and the new
settings are expected to be available in the new kernel too, though
there are cases where you actually don't want the modified contents.
I am assuming that modified DT and unmodifed one both are accessible to
kernel. And if user space can make decisions which modfied fields to use
for new kernels and which ones not, then same can be done in kernel too?
The unmodified DT can typically be found on disk next to the kernel binary.
The option you have is to either read it from /proc/devicetree or to
read it from from /boot/*.dtb.
Arnd
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-12 14:50:28
On Tue, Jul 12, 2016 at 04:24:10PM +0200, Arnd Bergmann wrote:
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
quoted
quoted
On Open Firmware, the DT is extracted from running firmware and copied
into dynamically allocated data structures. After a kexec, the runtime
interface to the firmware is not available, so the flattened DT format
was created as a way to pass the same data in a binary blob to the new
kernel in a format that can be read from the kernel by walking the
directories in /proc/device-tree/*.
So this DT is available inside kernel and running kernel can still
retrieve it and pass it to second kernel?
The kernel only uses the flattened DT blob at boot time and converts
it into the runtime data structures (struct device_node). The original
dtb is typically overwritten later.
On arm64 we deliberately preserved the DTB, so we can take that and
build a new DTB from that kernel-side.
quoted
quoted
- we typically ship devicetree sources for embedded machines with the
kernel sources. As more hardware of the system gets enabled, the
devicetree gains extra nodes and properties that describe the hardware
more completely, so we need to use the latest DT blob to use all
the drivers
- in some cases, kernels will fail to boot at all with an older version
of the DT, or fail to use the devices that were working on the
earlier kernel. This is usually considered a bug, but it's not rare
- In some cases, the kernel can update its DT at runtime, and the new
settings are expected to be available in the new kernel too, though
there are cases where you actually don't want the modified contents.
I am assuming that modified DT and unmodifed one both are accessible to
kernel. And if user space can make decisions which modfied fields to use
for new kernels and which ones not, then same can be done in kernel too?
The unmodified DT can typically be found on disk next to the kernel binary.
The option you have is to either read it from /proc/devicetree or to
read it from from /boot/*.dtb.
/proc/devicetree (aka /sys/firmware/devicetree) is a filesystem derived
from the raw DTB (which is exposed at /sys/firmware/fdt).
The blob that was handed to the kernel at boot time is exposed at
/sys/firmware/fdt.
Thanks,
Mark.
From: Dave Young <hidden> Date: 2016-07-13 02:36:54
On 07/12/16 at 03:50pm, Mark Rutland wrote:
On Tue, Jul 12, 2016 at 04:24:10PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
quoted
quoted
On Open Firmware, the DT is extracted from running firmware and copied
into dynamically allocated data structures. After a kexec, the runtime
interface to the firmware is not available, so the flattened DT format
was created as a way to pass the same data in a binary blob to the new
kernel in a format that can be read from the kernel by walking the
directories in /proc/device-tree/*.
So this DT is available inside kernel and running kernel can still
retrieve it and pass it to second kernel?
The kernel only uses the flattened DT blob at boot time and converts
it into the runtime data structures (struct device_node). The original
dtb is typically overwritten later.
On arm64 we deliberately preserved the DTB, so we can take that and
build a new DTB from that kernel-side.
quoted
quoted
quoted
- we typically ship devicetree sources for embedded machines with the
kernel sources. As more hardware of the system gets enabled, the
devicetree gains extra nodes and properties that describe the hardware
more completely, so we need to use the latest DT blob to use all
the drivers
- in some cases, kernels will fail to boot at all with an older version
of the DT, or fail to use the devices that were working on the
earlier kernel. This is usually considered a bug, but it's not rare
- In some cases, the kernel can update its DT at runtime, and the new
settings are expected to be available in the new kernel too, though
there are cases where you actually don't want the modified contents.
I am assuming that modified DT and unmodifed one both are accessible to
kernel. And if user space can make decisions which modfied fields to use
for new kernels and which ones not, then same can be done in kernel too?
The unmodified DT can typically be found on disk next to the kernel binary.
The option you have is to either read it from /proc/devicetree or to
read it from from /boot/*.dtb.
/proc/devicetree (aka /sys/firmware/devicetree) is a filesystem derived
from the raw DTB (which is exposed at /sys/firmware/fdt).
The blob that was handed to the kernel at boot time is exposed at
/sys/firmware/fdt.
I believe the blob can be read and passed to kexec kernel in kernel code without
the extra fd.
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well. From my understanding
it is reasonable but yes I think we should think carefully about the design.
Thanks
Dave
On Wednesday, July 13, 2016 10:36:14 AM CEST Dave Young wrote:
On 07/12/16 at 03:50pm, Mark Rutland wrote:
quoted
On Tue, Jul 12, 2016 at 04:24:10PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
/proc/devicetree (aka /sys/firmware/devicetree) is a filesystem derived
from the raw DTB (which is exposed at /sys/firmware/fdt).
The blob that was handed to the kernel at boot time is exposed at
/sys/firmware/fdt.
I believe the blob can be read and passed to kexec kernel in kernel code without
the extra fd.
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well. From my understanding
it is reasonable but yes I think we should think carefully about the design.
Ok, I can see four interesting use cases here:
- Using the dtb that the kernel has saved at boot time. Ideally this should not
require an additional step of signing it, since the running kernel already
trusts it.
- A dtb blob from the file system that was produced along with the kernel image.
If we require a signature on the kernel, the the same requirement should be
made on the dtb. Whoever signs the kernel can also sign the dtb.
The tricky part here is the kernel command line that is part of the dtb
and that may need to be modified.
- Modifying the dtb at for any of the reasons I listed: This should always
be possible when we do not use secure boot, just like booting an unsigned
kernel is.
- kboot/petitboot with all of the user space being part of the trusted boot
chain: it would be good to allow these to modify the dtb as needed without
breaking the trust chain, just like we allow grub or u-boot to modify the dtb
before passing it to the kernel.
Arnd
From: Stewart Smith <hidden> Date: 2016-07-13 08:24:23
Arnd Bergmann [off-list ref] writes:
On Wednesday, July 13, 2016 10:36:14 AM CEST Dave Young wrote:
quoted
On 07/12/16 at 03:50pm, Mark Rutland wrote:
quoted
On Tue, Jul 12, 2016 at 04:24:10PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
/proc/devicetree (aka /sys/firmware/devicetree) is a filesystem derived
from the raw DTB (which is exposed at /sys/firmware/fdt).
The blob that was handed to the kernel at boot time is exposed at
/sys/firmware/fdt.
I believe the blob can be read and passed to kexec kernel in kernel code without
the extra fd.
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well. From my understanding
it is reasonable but yes I think we should think carefully about the design.
Ok, I can see four interesting use cases here:
- Using the dtb that the kernel has saved at boot time. Ideally this should not
require an additional step of signing it, since the running kernel already
trusts it.
- using current view of the hardware, flattened into a new dtb.
This should already be trusted, as it's what we're running now (boot +
runtime changes)
--
Stewart Smith
OPAL Architect, IBM.
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-13 09:42:09
On Wed, Jul 13, 2016 at 10:01:33AM +0200, Arnd Bergmann wrote:
On Wednesday, July 13, 2016 10:36:14 AM CEST Dave Young wrote:
quoted
On 07/12/16 at 03:50pm, Mark Rutland wrote:
quoted
On Tue, Jul 12, 2016 at 04:24:10PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
/proc/devicetree (aka /sys/firmware/devicetree) is a filesystem derived
from the raw DTB (which is exposed at /sys/firmware/fdt).
The blob that was handed to the kernel at boot time is exposed at
/sys/firmware/fdt.
I believe the blob can be read and passed to kexec kernel in kernel code without
the extra fd.
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well. From my understanding
it is reasonable but yes I think we should think carefully about the design.
Ok, I can see four interesting use cases here:
- Using the dtb that the kernel has saved at boot time. Ideally this should not
require an additional step of signing it, since the running kernel already
trusts it.
We have sufficient information from the existing kexec_file_load syscall
prototype to do this in-kernel.
- A dtb blob from the file system that was produced along with the kernel image.
If we require a signature on the kernel, the the same requirement should be
made on the dtb. Whoever signs the kernel can also sign the dtb.
The tricky part here is the kernel command line that is part of the dtb
and that may need to be modified.
I suspect that for this case, following the example of the existing
sycall, we'd allow the kernel to modify bootargs and initrd properties
after verfiying the signature of the DTB.
The big question is whether this is a realistic case on a secure boot
system.
- Modifying the dtb at for any of the reasons I listed: This should always
be possible when we do not use secure boot, just like booting an unsigned
kernel is.
This is possible with the existing kexec_load syscall, for the non
secure boot case.
- kboot/petitboot with all of the user space being part of the trusted boot
chain: it would be good to allow these to modify the dtb as needed without
breaking the trust chain, just like we allow grub or u-boot to modify the dtb
before passing it to the kernel.
It depends on *what* we need to modify here. We can modify the bootargs
and initrd properties as part of the kexec_file_load syscall, so what
else would we want to alter?
Thanks,
Mark.
On Wednesday, July 13, 2016 10:41:28 AM CEST Mark Rutland wrote:
On Wed, Jul 13, 2016 at 10:01:33AM +0200, Arnd Bergmann wrote:
quoted
On Wednesday, July 13, 2016 10:36:14 AM CEST Dave Young wrote:
quoted
On 07/12/16 at 03:50pm, Mark Rutland wrote:
quoted
On Tue, Jul 12, 2016 at 04:24:10PM +0200, Arnd Bergmann wrote:
quoted
On Tuesday, July 12, 2016 10:18:11 AM CEST Vivek Goyal wrote:
/proc/devicetree (aka /sys/firmware/devicetree) is a filesystem derived
from the raw DTB (which is exposed at /sys/firmware/fdt).
The blob that was handed to the kernel at boot time is exposed at
/sys/firmware/fdt.
I believe the blob can be read and passed to kexec kernel in kernel code without
the extra fd.
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well. From my understanding
it is reasonable but yes I think we should think carefully about the design.
Ok, I can see four interesting use cases here:
- Using the dtb that the kernel has saved at boot time. Ideally this should not
require an additional step of signing it, since the running kernel already
trusts it.
We have sufficient information from the existing kexec_file_load syscall
prototype to do this in-kernel.
Ok.
quoted
- A dtb blob from the file system that was produced along with the kernel image.
If we require a signature on the kernel, the the same requirement should be
made on the dtb. Whoever signs the kernel can also sign the dtb.
The tricky part here is the kernel command line that is part of the dtb
and that may need to be modified.
I suspect that for this case, following the example of the existing
sycall, we'd allow the kernel to modify bootargs and initrd properties
after verfiying the signature of the DTB.
Makes sense.
The big question is whether this is a realistic case on a secure boot
system.
What does x86 do here? I assume changes to the command line are also
limited.
quoted
- Modifying the dtb at for any of the reasons I listed: This should always
be possible when we do not use secure boot, just like booting an unsigned
kernel is.
This is possible with the existing kexec_load syscall, for the non
secure boot case.
Ok, let's skip that then.
quoted
- kboot/petitboot with all of the user space being part of the trusted boot
chain: it would be good to allow these to modify the dtb as needed without
breaking the trust chain, just like we allow grub or u-boot to modify the dtb
before passing it to the kernel.
It depends on *what* we need to modify here. We can modify the bootargs
and initrd properties as part of the kexec_file_load syscall, so what
else would we want to alter?
I guess petitboot can also just use kexec_load() instead of kexec_file_load(),
as long as the initramfs containing petitboot is trusted by the kernel.
Arnd
Am Mittwoch, 13 Juli 2016, 15:13:42 schrieb Arnd Bergmann:
On Wednesday, July 13, 2016 10:41:28 AM CEST Mark Rutland wrote:
quoted
On Wed, Jul 13, 2016 at 10:01:33AM +0200, Arnd Bergmann wrote:
quoted
- kboot/petitboot with all of the user space being part of the trusted
boot> >
chain: it would be good to allow these to modify the dtb as needed
without breaking the trust chain, just like we allow grub or u-boot
to modify the dtb before passing it to the kernel.
It depends on *what* we need to modify here. We can modify the bootargs
and initrd properties as part of the kexec_file_load syscall, so what
else would we want to alter?
I guess petitboot can also just use kexec_load() instead of
kexec_file_load(), as long as the initramfs containing petitboot is
trusted by the kernel.
For secure boot, Petitboot needs to use kexec_file_load, because of the
following two features which the system call enables:
1. only allow loading of signed kernels.
2. "measure" (i.e., record the hashes of) the kernel, initrd, kernel
command line and other boot inputs for the Integrity Measurement
Architecture subsystem.
Those can't be done with kexec_load.
As for what we need to modify, Petitboot does the following modifications to
the DTB:
1. Set /chosen/linux,stdout-path based on which console is being used to
interact with it, as Stewart mentioned in another email.
2. Set display properties on /pciex@n/.../vga@0 in machines with an
OpenFirmware framebuffer.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
On Wednesday, July 13, 2016 3:45:41 PM CEST Thiago Jung Bauermann wrote:
Am Mittwoch, 13 Juli 2016, 15:13:42 schrieb Arnd Bergmann:
quoted
On Wednesday, July 13, 2016 10:41:28 AM CEST Mark Rutland wrote:
quoted
On Wed, Jul 13, 2016 at 10:01:33AM +0200, Arnd Bergmann wrote:
quoted
- kboot/petitboot with all of the user space being part of the trusted
boot> >
chain: it would be good to allow these to modify the dtb as needed
without breaking the trust chain, just like we allow grub or u-boot
to modify the dtb before passing it to the kernel.
It depends on *what* we need to modify here. We can modify the bootargs
and initrd properties as part of the kexec_file_load syscall, so what
else would we want to alter?
I guess petitboot can also just use kexec_load() instead of
kexec_file_load(), as long as the initramfs containing petitboot is
trusted by the kernel.
For secure boot, Petitboot needs to use kexec_file_load, because of the
following two features which the system call enables:
1. only allow loading of signed kernels.
2. "measure" (i.e., record the hashes of) the kernel, initrd, kernel
command line and other boot inputs for the Integrity Measurement
Architecture subsystem.
Those can't be done with kexec_load.
Can't petitboot do both of these in user space?
Arnd
Am Mittwoch, 13 Juli 2016, 21:59:18 schrieb Arnd Bergmann:
On Wednesday, July 13, 2016 3:45:41 PM CEST Thiago Jung Bauermann wrote:
quoted
Am Mittwoch, 13 Juli 2016, 15:13:42 schrieb Arnd Bergmann:
quoted
On Wednesday, July 13, 2016 10:41:28 AM CEST Mark Rutland wrote:
quoted
On Wed, Jul 13, 2016 at 10:01:33AM +0200, Arnd Bergmann wrote:
quoted
- kboot/petitboot with all of the user space being part of the
trusted
boot> >
chain: it would be good to allow these to modify the dtb as
needed
without breaking the trust chain, just like we allow grub or
u-boot
to modify the dtb before passing it to the kernel.
It depends on *what* we need to modify here. We can modify the
bootargs
and initrd properties as part of the kexec_file_load syscall, so
what
else would we want to alter?
I guess petitboot can also just use kexec_load() instead of
kexec_file_load(), as long as the initramfs containing petitboot is
trusted by the kernel.
For secure boot, Petitboot needs to use kexec_file_load, because of the
following two features which the system call enables:
1. only allow loading of signed kernels.
2. "measure" (i.e., record the hashes of) the kernel, initrd, kernel
command line and other boot inputs for the Integrity Measurement
Architecture subsystem.
Those can't be done with kexec_load.
Can't petitboot do both of these in user space?
To be honest I'm not sure if it *can't* be done from userspace but if you do
it from the kernel you can guarantee that any kernel image that is loaded
gets verified and measured.
Whereas if you verify and measure the kernel in userspace then if there's a
vulnerability in the system which allows an attacker to upload their own
binary, then they can use kexec_load directly and bypass the verification
and measurement.
So it's a more resilient design.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
On Wednesday, July 13, 2016 11:18:04 PM CEST Thiago Jung Bauermann wrote:
Am Mittwoch, 13 Juli 2016, 21:59:18 schrieb Arnd Bergmann:
quoted
On Wednesday, July 13, 2016 3:45:41 PM CEST Thiago Jung Bauermann wrote:
quoted
Am Mittwoch, 13 Juli 2016, 15:13:42 schrieb Arnd Bergmann:
For secure boot, Petitboot needs to use kexec_file_load, because of the
following two features which the system call enables:
1. only allow loading of signed kernels.
2. "measure" (i.e., record the hashes of) the kernel, initrd, kernel
command line and other boot inputs for the Integrity Measurement
Architecture subsystem.
Those can't be done with kexec_load.
Can't petitboot do both of these in user space?
To be honest I'm not sure if it *can't* be done from userspace but if you do
it from the kernel you can guarantee that any kernel image that is loaded
gets verified and measured.
Whereas if you verify and measure the kernel in userspace then if there's a
vulnerability in the system which allows an attacker to upload their own
binary, then they can use kexec_load directly and bypass the verification
and measurement.
So it's a more resilient design.
Right, but the question remains whether this helps while you allow the
boot loader to modify the dtb. If an attacker gets in and cannot modify
the kernel or initid but can modify the DT, a successful attack would
be a bit harder than having a modified kernel, but you may still need
to treat the system as compromised.
Arnd
Am Donnerstag, 14 Juli 2016, 10:29:11 schrieb Arnd Bergmann:
On Wednesday, July 13, 2016 11:18:04 PM CEST Thiago Jung Bauermann wrote:
quoted
Am Mittwoch, 13 Juli 2016, 21:59:18 schrieb Arnd Bergmann:
quoted
On Wednesday, July 13, 2016 3:45:41 PM CEST Thiago Jung Bauermann
wrote:
quoted
quoted
quoted
Am Mittwoch, 13 Juli 2016, 15:13:42 schrieb Arnd Bergmann:
For secure boot, Petitboot needs to use kexec_file_load, because of
the
following two features which the system call enables:
1. only allow loading of signed kernels.
2. "measure" (i.e., record the hashes of) the kernel, initrd, kernel
command line and other boot inputs for the Integrity Measurement
Architecture subsystem.
Those can't be done with kexec_load.
Can't petitboot do both of these in user space?
To be honest I'm not sure if it *can't* be done from userspace but if
you do it from the kernel you can guarantee that any kernel image that
is loaded gets verified and measured.
Whereas if you verify and measure the kernel in userspace then if
there's a vulnerability in the system which allows an attacker to
upload their own binary, then they can use kexec_load directly and
bypass the verification and measurement.
So it's a more resilient design.
Right, but the question remains whether this helps while you allow the
boot loader to modify the dtb. If an attacker gets in and cannot modify
the kernel or initid but can modify the DT, a successful attack would
be a bit harder than having a modified kernel, but you may still need
to treat the system as compromised.
Yes, and the same question also remains regarding the kernel command line.
We can have the kernel perform sanity checks on the device tree, just as the
kernel needs to sanity check the command line.
There's the point that was raised about not wanting to increase the attack
surface, and that's a valid point. But at least in the way Petitboot works
today, it needs to modify the device tree and pass it to the kernel.
One thing that is unavoidable to come from userspace is
/chosen/linux,stdout-path, because it's Petitboot that knows from which
console the user is interacting with. The other modification to set
properties in vga@0 can be done in the kernel.
Given that on DTB-based systems /chosen is an important and established way
to pass information to the operating system being booted, I'd like to
suggest the following, then:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall would accept a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. The kernel can then add the properties in /chosen
to the device tree that it will pass to the next kernel.
What do you think?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
On Thursday, July 14, 2016 10:44:14 PM CEST Thiago Jung Bauermann wrote:
Am Donnerstag, 14 Juli 2016, 10:29:11 schrieb Arnd Bergmann:
quoted
Right, but the question remains whether this helps while you allow the
boot loader to modify the dtb. If an attacker gets in and cannot modify
the kernel or initid but can modify the DT, a successful attack would
be a bit harder than having a modified kernel, but you may still need
to treat the system as compromised.
Yes, and the same question also remains regarding the kernel command line.
We can have the kernel perform sanity checks on the device tree, just as the
kernel needs to sanity check the command line.
There's the point that was raised about not wanting to increase the attack
surface, and that's a valid point. But at least in the way Petitboot works
today, it needs to modify the device tree and pass it to the kernel.
One thing that is unavoidable to come from userspace is
/chosen/linux,stdout-path, because it's Petitboot that knows from which
console the user is interacting with. The other modification to set
properties in vga@0 can be done in the kernel.
Given that on DTB-based systems /chosen is an important and established way
to pass information to the operating system being booted, I'd like to
suggest the following, then:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall would accept a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. The kernel can then add the properties in /chosen
to the device tree that it will pass to the next kernel.
What do you think?
I think that helps, as it makes the problem space correspond to that
of modifying the command line, but I can still come up with countless
attacks based on modifications of the /chosen node and/or the command
line, in fact it's probably easier than any other node.
What methods to we have in place for command line changes today on
other architectures?
Arnd
On Fri, Jul 15, 2016 at 09:31:02AM +0200, Arnd Bergmann wrote:
On Thursday, July 14, 2016 10:44:14 PM CEST Thiago Jung Bauermann wrote:
quoted
Am Donnerstag, 14 Juli 2016, 10:29:11 schrieb Arnd Bergmann:
quoted
quoted
Right, but the question remains whether this helps while you allow the
boot loader to modify the dtb. If an attacker gets in and cannot modify
the kernel or initid but can modify the DT, a successful attack would
be a bit harder than having a modified kernel, but you may still need
to treat the system as compromised.
Yes, and the same question also remains regarding the kernel command line.
We can have the kernel perform sanity checks on the device tree, just as the
kernel needs to sanity check the command line.
There's the point that was raised about not wanting to increase the attack
surface, and that's a valid point. But at least in the way Petitboot works
today, it needs to modify the device tree and pass it to the kernel.
One thing that is unavoidable to come from userspace is
/chosen/linux,stdout-path, because it's Petitboot that knows from which
console the user is interacting with. The other modification to set
properties in vga@0 can be done in the kernel.
Given that on DTB-based systems /chosen is an important and established way
to pass information to the operating system being booted, I'd like to
suggest the following, then:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall would accept a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. The kernel can then add the properties in /chosen
to the device tree that it will pass to the next kernel.
What do you think?
I think that helps, as it makes the problem space correspond to that
of modifying the command line, but I can still come up with countless
attacks based on modifications of the /chosen node and/or the command
line, in fact it's probably easier than any other node.
I don't know anything about DTB. So here comes a very basic question. Does
DTB allow passing an executable blob to kernel or pass the location of
some unsigned executable code at kernel level. I think from secureboot point of
view that would be a concern. Being able to trick kernel to execute an
unsigned code at privileged level.
Vivek
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-15 13:34:04
On Fri, Jul 15, 2016 at 09:26:10AM -0400, Vivek Goyal wrote:
On Fri, Jul 15, 2016 at 09:31:02AM +0200, Arnd Bergmann wrote:
quoted
On Thursday, July 14, 2016 10:44:14 PM CEST Thiago Jung Bauermann wrote:
quoted
Am Donnerstag, 14 Juli 2016, 10:29:11 schrieb Arnd Bergmann:
quoted
quoted
Right, but the question remains whether this helps while you allow the
boot loader to modify the dtb. If an attacker gets in and cannot modify
the kernel or initid but can modify the DT, a successful attack would
be a bit harder than having a modified kernel, but you may still need
to treat the system as compromised.
Yes, and the same question also remains regarding the kernel command line.
We can have the kernel perform sanity checks on the device tree, just as the
kernel needs to sanity check the command line.
There's the point that was raised about not wanting to increase the attack
surface, and that's a valid point. But at least in the way Petitboot works
today, it needs to modify the device tree and pass it to the kernel.
One thing that is unavoidable to come from userspace is
/chosen/linux,stdout-path, because it's Petitboot that knows from which
console the user is interacting with. The other modification to set
properties in vga@0 can be done in the kernel.
Given that on DTB-based systems /chosen is an important and established way
to pass information to the operating system being booted, I'd like to
suggest the following, then:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall would accept a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. The kernel can then add the properties in /chosen
to the device tree that it will pass to the next kernel.
What do you think?
I think that helps, as it makes the problem space correspond to that
of modifying the command line, but I can still come up with countless
attacks based on modifications of the /chosen node and/or the command
line, in fact it's probably easier than any other node.
I don't know anything about DTB. So here comes a very basic question. Does
DTB allow passing an executable blob to kernel or pass the location of
some unsigned executable code at kernel level. I think from secureboot point of
view that would be a concern. Being able to trick kernel to execute an
unsigned code at privileged level.
The DTB itself won't contain executable code.
However, arbitrary bindings could point kernel at such code. For
instance, /chosen/linux,uefi-system-table could point the kernel at a
faked EFI system table, with pointers to malicious code. So
arbitrary modification of /chosen is not safe.
Bindings describe arbitrary system features (devices, firmware
interfaces, etc), so in general they might provide mechanisms to execute
code.
Thanks,
Mark.
Am Freitag, 15 Juli 2016, 14:33:47 schrieb Mark Rutland:
On Fri, Jul 15, 2016 at 09:26:10AM -0400, Vivek Goyal wrote:
quoted
On Fri, Jul 15, 2016 at 09:31:02AM +0200, Arnd Bergmann wrote:
quoted
On Thursday, July 14, 2016 10:44:14 PM CEST Thiago Jung Bauermann
wrote:
quoted
quoted
quoted
Am Donnerstag, 14 Juli 2016, 10:29:11 schrieb Arnd Bergmann:
quoted
Right, but the question remains whether this helps while you allow
the
boot loader to modify the dtb. If an attacker gets in and cannot
modify
the kernel or initid but can modify the DT, a successful attack
would
be a bit harder than having a modified kernel, but you may still
need
to treat the system as compromised.
Yes, and the same question also remains regarding the kernel command
line.
We can have the kernel perform sanity checks on the device tree,
just as the kernel needs to sanity check the command line.
There's the point that was raised about not wanting to increase the
attack surface, and that's a valid point. But at least in the way
Petitboot works today, it needs to modify the device tree and pass
it to the kernel.
One thing that is unavoidable to come from userspace is
/chosen/linux,stdout-path, because it's Petitboot that knows from
which
console the user is interacting with. The other modification to set
properties in vga@0 can be done in the kernel.
Given that on DTB-based systems /chosen is an important and
established way to pass information to the operating system being
booted, I'd like to suggest the following, then:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but
instead of accepting a complete DTB from userspace, the syscall
would accept a DTB containing only a /chosen node. If the DTB
contains any other node, the syscall fails with EINVAL. The kernel
can then add the properties in /chosen to the device tree that it
will pass to the next kernel.
What do you think?
I think that helps, as it makes the problem space correspond to that
of modifying the command line, but I can still come up with countless
attacks based on modifications of the /chosen node and/or the command
line, in fact it's probably easier than any other node.
I don't know anything about DTB. So here comes a very basic question.
Does DTB allow passing an executable blob to kernel or pass the
location of some unsigned executable code at kernel level. I think from
secureboot point of view that would be a concern. Being able to trick
kernel to execute an unsigned code at privileged level.
The DTB itself won't contain executable code.
However, arbitrary bindings could point kernel at such code. For
instance, /chosen/linux,uefi-system-table could point the kernel at a
faked EFI system table, with pointers to malicious code. So
arbitrary modification of /chosen is not safe.
PowerPC doesn't have UEFI so this option is not a concern in that
architecture. I'm having a look at what a PowerPC kernel gets from /chosen
and haven't found anything of concern so far, but I'm still looking.
On the other hand, the kernel command line has the option acpi_rsdp, which
is used to pass the address of the RSDP. I don't really know much about EFI
so I'm not sure if it can be used to point to code that the kernel can
execute, but it does point to tables that contain AML code.
Bindings describe arbitrary system features (devices, firmware
interfaces, etc), so in general they might provide mechanisms to execute
code.
Even bindings in /chosen?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-15 15:47:43
On Fri, Jul 15, 2016 at 12:29:09PM -0300, Thiago Jung Bauermann wrote:
Am Freitag, 15 Juli 2016, 14:33:47 schrieb Mark Rutland:
quoted
On Fri, Jul 15, 2016 at 09:26:10AM -0400, Vivek Goyal wrote:
quoted
I don't know anything about DTB. So here comes a very basic question.
Does DTB allow passing an executable blob to kernel or pass the
location of some unsigned executable code at kernel level. I think from
secureboot point of view that would be a concern. Being able to trick
kernel to execute an unsigned code at privileged level.
The DTB itself won't contain executable code.
However, arbitrary bindings could point kernel at such code. For
instance, /chosen/linux,uefi-system-table could point the kernel at a
faked EFI system table, with pointers to malicious code. So
arbitrary modification of /chosen is not safe.
PowerPC doesn't have UEFI so this option is not a concern in that
architecture. I'm having a look at what a PowerPC kernel gets from /chosen
and haven't found anything of concern so far, but I'm still looking.
On the other hand, the kernel command line has the option acpi_rsdp, which
is used to pass the address of the RSDP. I don't really know much about EFI
so I'm not sure if it can be used to point to code that the kernel can
execute, but it does point to tables that contain AML code.
Please let's not conflate EFI and ACPI, the two are distinct.
I believe that there aren't any ACPI tables which contain native code,
or which contain pointers to native code, but I could be mistaken. It
doesn't seem unlikely that malicious AML is possible, but I'm not
familiar enough with AML to know how we sandbox that.
From a scan of Documentation/kernel-parameters.txt, it doesn't look like
there are options to override the EFI system table (or related tables),
so it doesn't look like there's a trivial mechanism to trigger arbitrary
code execution. It looks like efi_fake_mem could be used to trick the
kernel to poke things it shouldn't, though that likely brings the system
down entirely.
quoted
Bindings describe arbitrary system features (devices, firmware
interfaces, etc), so in general they might provide mechanisms to execute
code.
Even bindings in /chosen?
Yes, even bindings in /chosen. As above, the linux,uefi-system-table
property lives under /chosen, and provides pointers to native code.
Control over this property could yield arbitrary code execution.
Additionally, there are drivers that just go looking for a compatible
string, and will probe regardless of where the node is in the hierarchy.
e.g. clock controller drivers, memory nodes. So /chosen isn't sandboxed
as such.
I fear that there are many things that one could place under /chosen
that could make the kernel do the wrong thing. Given the example of
drivers, I'm not sure it's going to be possible to audit all the
relevant code.
Thanks,
Mark.
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2016-07-15 13:42:38
On Fri, Jul 15, 2016 at 09:26:10AM -0400, Vivek Goyal wrote:
On Fri, Jul 15, 2016 at 09:31:02AM +0200, Arnd Bergmann wrote:
quoted
I think that helps, as it makes the problem space correspond to that
of modifying the command line, but I can still come up with countless
attacks based on modifications of the /chosen node and/or the command
line, in fact it's probably easier than any other node.
I don't know anything about DTB. So here comes a very basic question. Does
DTB allow passing an executable blob to kernel or pass the location of
some unsigned executable code at kernel level.
DT on ARM is a description of the hardware - it can be thought of as a
set of nodes with properties attached. The properties can describe
anything (we have documentation in Documentation/devicetree/bindings
which describes what we expect the properties to contain.)
On other architectures, DT can also contain open-firmware "functions"
but I don't think there's much support in the kernel for that - maybe
the PPC folk can reply on that point.
It is possible that someone may, at some point, decide to create a
property that points to some executable blob, but I can't think of a
reason why we should ever allow such a monstrosity in mainline kernels.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
On Friday, July 15, 2016 2:42:10 PM CEST Russell King - ARM Linux wrote:
On other architectures, DT can also contain open-firmware "functions"
but I don't think there's much support in the kernel for that - maybe
the PPC folk can reply on that point.
The open firmware runtime interface are shut down by the time we have
a flattened device tree, so those are not accessible any more. IIRC
SPARC leaves the open firmware interface live, but it doesn't use
fdt, so that's not relevant here.
However, the powerpc specific RTAS runtime services provide a similar
interface to the UEFI runtime support and allow to call into
binary code from the kernel, which gets mapped from a physical
address in the "linux,rtas-base" property in the rtas device node.
Modifying the /rtas node will definitely give you a backdoor into
priviledged code, but modifying only /chosen should not let you get
in through that specific method.
Arnd
Am Freitag, 15 Juli 2016, 22:26:09 schrieb Arnd Bergmann:
On Friday, July 15, 2016 2:42:10 PM CEST Russell King - ARM Linux wrote:
quoted
On other architectures, DT can also contain open-firmware "functions"
but I don't think there's much support in the kernel for that - maybe
the PPC folk can reply on that point.
The open firmware runtime interface are shut down by the time we have
a flattened device tree, so those are not accessible any more. IIRC
SPARC leaves the open firmware interface live, but it doesn't use
fdt, so that's not relevant here.
However, the powerpc specific RTAS runtime services provide a similar
interface to the UEFI runtime support and allow to call into
binary code from the kernel, which gets mapped from a physical
address in the "linux,rtas-base" property in the rtas device node.
Modifying the /rtas node will definitely give you a backdoor into
priviledged code, but modifying only /chosen should not let you get
in through that specific method.
Except that arch/powerpc/kernel/rtas.c looks for any node in the tree called
"rtas", so it will try to use /chosen/rtas, or /chosen/foo/rtas.
We can forbid subnodes in /chosen in the dtb passed to kexec_file_load,
though that means userspace can't use the simple-framebuffer binding via
this mechanism.
We also have to blacklist the device_type and compatible properties in
/chosen to avoid the problem Mark mentioned.
Still doable, but not ideal. :-/
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
Am Freitag, 15 Juli 2016, 18:03:35 schrieb Thiago Jung Bauermann:
Am Freitag, 15 Juli 2016, 22:26:09 schrieb Arnd Bergmann:
quoted
However, the powerpc specific RTAS runtime services provide a similar
interface to the UEFI runtime support and allow to call into
binary code from the kernel, which gets mapped from a physical
address in the "linux,rtas-base" property in the rtas device node.
Modifying the /rtas node will definitely give you a backdoor into
priviledged code, but modifying only /chosen should not let you get
in through that specific method.
Except that arch/powerpc/kernel/rtas.c looks for any node in the tree
called "rtas", so it will try to use /chosen/rtas, or /chosen/foo/rtas.
We can forbid subnodes in /chosen in the dtb passed to kexec_file_load,
though that means userspace can't use the simple-framebuffer binding via
this mechanism.
We also have to blacklist the device_type and compatible properties in
/chosen to avoid the problem Mark mentioned.
Still doable, but not ideal. :-/
So even if not ideal, the solution above is desirable for powerpc. We would
like to preserve the ability of allowing userspace to pass parameters to the
OS via the DTB, even if secure boot is enabled.
I would like to turn the above into a proposal:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall accepts a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. If the DTB contains any subnode in /chosen, or if
there's a compatible or device_type property in /chosen, the syscall fails
with EINVAL as well.
The kernel can then add the properties in /chosen to the device tree that it
will pass to the next kernel.
What do you think?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
From: Jeremy Kerr <hidden> Date: 2016-07-22 00:53:58
Hi Thiago,
So even if not ideal, the solution above is desirable for powerpc. We would
like to preserve the ability of allowing userspace to pass parameters to the
OS via the DTB, even if secure boot is enabled.
I would like to turn the above into a proposal:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall accepts a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. If the DTB contains any subnode in /chosen, or if
there's a compatible or device_type property in /chosen, the syscall fails
with EINVAL as well.
This works for me. We could even have it as just a DTB fragment that is
merged *at* the /chosen/ node of the kernel-device tree - so would not
contain a /chosen node itself, and it would be impossible to provide
nodes outside of /chosen. Either is fine.
Thanks!
Jeremy
From: Michael Ellerman <hidden> Date: 2016-07-22 02:54:33
Thiago Jung Bauermann [off-list ref] writes:
Am Freitag, 15 Juli 2016, 18:03:35 schrieb Thiago Jung Bauermann:
quoted
Am Freitag, 15 Juli 2016, 22:26:09 schrieb Arnd Bergmann:
quoted
However, the powerpc specific RTAS runtime services provide a similar
interface to the UEFI runtime support and allow to call into
binary code from the kernel, which gets mapped from a physical
address in the "linux,rtas-base" property in the rtas device node.
Modifying the /rtas node will definitely give you a backdoor into
priviledged code, but modifying only /chosen should not let you get
in through that specific method.
Except that arch/powerpc/kernel/rtas.c looks for any node in the tree
called "rtas", so it will try to use /chosen/rtas, or /chosen/foo/rtas.
We can forbid subnodes in /chosen in the dtb passed to kexec_file_load,
though that means userspace can't use the simple-framebuffer binding via
this mechanism.
We also have to blacklist the device_type and compatible properties in
/chosen to avoid the problem Mark mentioned.
Still doable, but not ideal. :-/
So even if not ideal, the solution above is desirable for powerpc. We would
like to preserve the ability of allowing userspace to pass parameters to the
OS via the DTB, even if secure boot is enabled.
I would like to turn the above into a proposal:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but instead of
accepting a complete DTB from userspace, the syscall accepts a DTB
containing only a /chosen node. If the DTB contains any other node, the
syscall fails with EINVAL. If the DTB contains any subnode in /chosen, or if
there's a compatible or device_type property in /chosen, the syscall fails
with EINVAL as well.
The kernel can then add the properties in /chosen to the device tree that it
will pass to the next kernel.
What do you think?
I think we will inevitably have someone who wants to pass something
other than a child of /chosen.
At that point we would be faced with adding yet another syscall, or at
best a new flag.
I think we'd be better allowing userspace to pass a DTB, and having an
explicit whitelist (in the kernel) of which nodes & properties are
allowed in that DTB.
For starters it would only contain /chosen/stdout-path (for example).
But we would be able to add new nodes & properties in future.
The downside is userspace would have no way of detecting the content of
the white list, other than trial and error. But in practice I'm not sure
that would be a big problem.
cheers
Am Freitag, 22 Juli 2016, 12:54:28 schrieb Michael Ellerman:
Thiago Jung Bauermann [off-list ref] writes:
quoted
So even if not ideal, the solution above is desirable for powerpc. We
would like to preserve the ability of allowing userspace to pass
parameters to the OS via the DTB, even if secure boot is enabled.
I would like to turn the above into a proposal:
Extend the syscall as shown in this RFC from Takahiro AKASHI, but
instead of accepting a complete DTB from userspace, the syscall accepts
a DTB containing only a /chosen node. If the DTB contains any other
node, the syscall fails with EINVAL. If the DTB contains any subnode in
/chosen, or if there's a compatible or device_type property in /chosen,
the syscall fails with EINVAL as well.
The kernel can then add the properties in /chosen to the device tree
that it will pass to the next kernel.
What do you think?
I think we will inevitably have someone who wants to pass something
other than a child of /chosen.
At that point we would be faced with adding yet another syscall, or at
best a new flag.
I think we'd be better allowing userspace to pass a DTB, and having an
explicit whitelist (in the kernel) of which nodes & properties are
allowed in that DTB.
Sounds good to me.
For starters it would only contain /chosen/stdout-path (for example).
But we would be able to add new nodes & properties in future.
If we allow things outside of chosen, we can keep the offb.c hook in
Petitboot and whitelist the framebuffer properties it adds to the vga node.
The downside is userspace would have no way of detecting the content of
the white list, other than trial and error. But in practice I'm not sure
that would be a big problem.
For our use case in OpenPower I don't think it would be a problem, since the
userspace and the kernel are developed together.
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2016-07-15 08:49:47
On Wed, Jul 13, 2016 at 03:13:42PM +0200, Arnd Bergmann wrote:
On Wednesday, July 13, 2016 10:41:28 AM CEST Mark Rutland wrote:
quoted
The big question is whether this is a realistic case on a secure boot
system.
What does x86 do here? I assume changes to the command line are also
limited.
They aren't. You can specify /anything/ even with a fully-signed kernel
and initrd, which was one of the things I pointed out in my previous
set of responses.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
On Fri, Jul 15, 2016 at 09:49:25AM +0100, Russell King - ARM Linux wrote:
On Wed, Jul 13, 2016 at 03:13:42PM +0200, Arnd Bergmann wrote:
quoted
On Wednesday, July 13, 2016 10:41:28 AM CEST Mark Rutland wrote:
quoted
The big question is whether this is a realistic case on a secure boot
system.
What does x86 do here? I assume changes to the command line are also
limited.
They aren't. You can specify /anything/ even with a fully-signed kernel
and initrd, which was one of the things I pointed out in my previous
set of responses.
Yes, kernel command line is not signed. For that matter even initird is
not signed. Just kernel is signed and its signatures are verified. Idea
is an unsigned code should not be able to execute in kernel space.
Vivek
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-13 09:35:13
On Wed, Jul 13, 2016 at 10:36:14AM +0800, Dave Young wrote:
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well.
It depends on what you mean by "a different kernel", and what this
implies for the DTB.
I expect future arm64 Linux kernels to function with today's DTBs, and
the existing boot protocol. The kexec_file_load syscall already has
enough information for the kernel to inject the initrd and bootargs
properties into a DTB.
In practice on x86 today, kexec_file_load only supports booting to a
Linux kernel, because the in-kernel purgatory only implements the x86
Linux boot protocol. Analagously, for arm64 I think that the first
kernel should use its internal copy of the boot DTB, with /chosen fixed
up appropriately, assuming the next kernel is an arm64 Linux image.
If booting another OS, the only parts of the DTB I would expect to
change are the properties under chosen, as everything else *should* be
OS-independent. However the other OS may have a completely different
boot protocol, might not even take a DTB, and will likely need a
compeltely different purgatory implementation. So just allowing the DTB
to be altered isn't sufficient for that case.
There might be cases where we want a different DTB, but as far as I can
tell we have nothing analagous on x86 today. If we do need this, we
should have an idea of what real case(s) were trying to solve.
Thanks,
Mark.
Apologies for the slow response. I'm attending LinuxCon this week.
On Wed, Jul 13, 2016 at 10:34:47AM +0100, Mark Rutland wrote:
On Wed, Jul 13, 2016 at 10:36:14AM +0800, Dave Young wrote:
quoted
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well.
It depends on what you mean by "a different kernel", and what this
implies for the DTB.
I expect future arm64 Linux kernels to function with today's DTBs, and
the existing boot protocol. The kexec_file_load syscall already has
enough information for the kernel to inject the initrd and bootargs
properties into a DTB.
In practice on x86 today, kexec_file_load only supports booting to a
Linux kernel, because the in-kernel purgatory only implements the x86
Linux boot protocol. Analagously, for arm64 I think that the first
kernel should use its internal copy of the boot DTB, with /chosen fixed
up appropriately, assuming the next kernel is an arm64 Linux image.
If booting another OS, the only parts of the DTB I would expect to
change are the properties under chosen, as everything else *should* be
OS-independent. However the other OS may have a completely different
boot protocol, might not even take a DTB, and will likely need a
compeltely different purgatory implementation. So just allowing the DTB
to be altered isn't sufficient for that case.
There might be cases where we want a different DTB, but as far as I can
tell we have nothing analagous on x86 today. If we do need this, we
should have an idea of what real case(s) were trying to solve.
What I had in my mind was:
- Kdump
As Russel said, we definitely need to modify dtb.
In addition to bootargs and initrd proerties (FYI, in my arm64
implementation for arm64, eflcorehdr info is also passed as DT
property), we may want to remove unnecessary devices and
even add a dedicated storage device for storing a core dump image.
- Say, booting BE kernel on ACPI LE kernel
In this case, there is no useful dtb in the kernel.
Have said that, as Mark said, we may be able to use normal kexec_load
system call if we don't need a "secure" kexec.
BTW, why doesn't the current kexec_load have ability of verifying
a signature of initramfs image? Is IMA/EVM expected to be used
at runtime?
Thanks,
-Takahiro AKASHI
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-13 18:00:16
On Thu, Jul 14, 2016 at 02:38:06AM +0900, AKASHI Takahiro wrote:
Apologies for the slow response. I'm attending LinuxCon this week.
On Wed, Jul 13, 2016 at 10:34:47AM +0100, Mark Rutland wrote:
quoted
On Wed, Jul 13, 2016 at 10:36:14AM +0800, Dave Young wrote:
quoted
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well.
It depends on what you mean by "a different kernel", and what this
implies for the DTB.
I expect future arm64 Linux kernels to function with today's DTBs, and
the existing boot protocol. The kexec_file_load syscall already has
enough information for the kernel to inject the initrd and bootargs
properties into a DTB.
In practice on x86 today, kexec_file_load only supports booting to a
Linux kernel, because the in-kernel purgatory only implements the x86
Linux boot protocol. Analagously, for arm64 I think that the first
kernel should use its internal copy of the boot DTB, with /chosen fixed
up appropriately, assuming the next kernel is an arm64 Linux image.
If booting another OS, the only parts of the DTB I would expect to
change are the properties under chosen, as everything else *should* be
OS-independent. However the other OS may have a completely different
boot protocol, might not even take a DTB, and will likely need a
compeltely different purgatory implementation. So just allowing the DTB
to be altered isn't sufficient for that case.
There might be cases where we want a different DTB, but as far as I can
tell we have nothing analagous on x86 today. If we do need this, we
should have an idea of what real case(s) were trying to solve.
What I had in my mind was:
- Kdump
As Russel said, we definitely need to modify dtb.
I agree that *something* needs to modify the DTB to pass the cmdline and
initrd properties.
What I'm trying to point out that it isn't necessary that *userspace*
does so for the vast majority of kexec_file_load cases.
If userspace where to have to modify things dynamically, then you can't
have a secure deployment. Either you don't verify signatures on things
modified by userspace, giving a backdoor, or each machine has to have a
local copy of (locally) trusted private keys, which comes with other
risks (e.g. offline extraction of the keys).
In addition to bootargs and initrd proerties (FYI, in my arm64
implementation for arm64, eflcorehdr info is also passed as DT
property),
As pointed out, for kexec_file_load we can add code to the kernel can
add bootargs and initrd properties as necessary for this case. The
existing kexec_file_load prototype allows userspace to pass the required
information.
we may want to remove unnecessary devices and even add a dedicated
storage device for storing a core dump image.
I suspect that bringing up a minimal number of devices is better
controlled by a cmdline option. In general, figuring out what is
necessary and what is not is going to be board specific, so hacking the
FW tables (DTB or ACPI) is not a very portable/reliable approach.
Do we actually add devices in practice? More so than the above that
requires special knowledge of the platform (including things that were
not described in the boot DTB).
In the ACPI case modifying a DTB alone is not sufficient to change the
information regarding devices, as those won't be described in the DTB.
It's not possible to convert ACPI to DTB in general.
- Say, booting BE kernel on ACPI LE kernel
In this case, there is no useful dtb in the kernel.
If the platform only has ACPI, then you cannot boot a BE kernel to begin
with. As above one cannot convert ACPI to DTB, so one would need
extensive platform knowledge for this to work.
I think it's fair to say that this is not a realistic/common case.
Have said that, as Mark said, we may be able to use normal kexec_load
system call if we don't need a "secure" kexec.
BTW, why doesn't the current kexec_load have ability of verifying
a signature of initramfs image?
I believe the code was written before secure boot was a concern, and in
the absence of secure boot it was expected that a trusted userspace
would verify signatures itself.
Is IMA/EVM expected to be used at runtime?
Sorry, I'm not sure what those abbreviations mean. Could you expand
them?
Thanks,
Mark.
On Wednesday, July 13, 2016 6:58:32 PM CEST Mark Rutland wrote:
quoted
we may want to remove unnecessary devices and even add a dedicated
storage device for storing a core dump image.
I suspect that bringing up a minimal number of devices is better
controlled by a cmdline option. In general, figuring out what is
necessary and what is not is going to be board specific, so hacking the
FW tables (DTB or ACPI) is not a very portable/reliable approach.
Do we actually add devices in practice? More so than the above that
requires special knowledge of the platform (including things that were
not described in the boot DTB).
In the ACPI case modifying a DTB alone is not sufficient to change the
information regarding devices, as those won't be described in the DTB.
It's not possible to convert ACPI to DTB in general.
A more likely scenario would be replacing ACPI tables with a DTB that
describes the platform in order to use devices that the ACPI tables
don't contain.
quoted
- Say, booting BE kernel on ACPI LE kernel
In this case, there is no useful dtb in the kernel.
If the platform only has ACPI, then you cannot boot a BE kernel to begin
with. As above one cannot convert ACPI to DTB, so one would need
extensive platform knowledge for this to work.
I think what he meant was to pass a DTB to the kexec kernel in order
to run BE, while the original kernel can only run LE due to ACPI.
If you boot a LE kernel using DTB, the same DTB should work
for a kexec boot for a BE kernel.
Arnd
From: Mark Rutland <mark.rutland@arm.com> Date: 2016-07-14 12:42:20
On Wed, Jul 13, 2016 at 09:57:28PM +0200, Arnd Bergmann wrote:
On Wednesday, July 13, 2016 6:58:32 PM CEST Mark Rutland wrote:
quoted
quoted
we may want to remove unnecessary devices and even add a dedicated
storage device for storing a core dump image.
I suspect that bringing up a minimal number of devices is better
controlled by a cmdline option. In general, figuring out what is
necessary and what is not is going to be board specific, so hacking the
FW tables (DTB or ACPI) is not a very portable/reliable approach.
Do we actually add devices in practice? More so than the above that
requires special knowledge of the platform (including things that were
not described in the boot DTB).
In the ACPI case modifying a DTB alone is not sufficient to change the
information regarding devices, as those won't be described in the DTB.
It's not possible to convert ACPI to DTB in general.
A more likely scenario would be replacing ACPI tables with a DTB that
describes the platform in order to use devices that the ACPI tables
don't contain.
To do so, you need special knowledge of the platform, which users are
unlikely to have in practice for ACPI-based platforms.
So, I think that boils down to the same problem, and the same comments
apply.
quoted
quoted
- Say, booting BE kernel on ACPI LE kernel
In this case, there is no useful dtb in the kernel.
quoted
If the platform only has ACPI, then you cannot boot a BE kernel to begin
with. As above one cannot convert ACPI to DTB, so one would need
extensive platform knowledge for this to work.
I think what he meant was to pass a DTB to the kexec kernel in order
to run BE, while the original kernel can only run LE due to ACPI.
I understood that. My point was that to build that DTB, you need to have
knowledge of the platform that you are unlikely to have.
The platform firmware may expect to interact with AML, which you can't
place in DT or run in a BE context.
If you need to run BE kernels on a platform, you would likely get a
platform that could boot a BE kernel from the outset (i.e. one that
provides a DTB), or run that code ina VM under an LE host.
Thanks,
Mark.
From: Dave Young <hidden> Date: 2016-07-14 01:55:00
On 07/14/16 at 02:38am, AKASHI Takahiro wrote:
Apologies for the slow response. I'm attending LinuxCon this week.
On Wed, Jul 13, 2016 at 10:34:47AM +0100, Mark Rutland wrote:
quoted
On Wed, Jul 13, 2016 at 10:36:14AM +0800, Dave Young wrote:
quoted
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well.
It depends on what you mean by "a different kernel", and what this
implies for the DTB.
I expect future arm64 Linux kernels to function with today's DTBs, and
the existing boot protocol. The kexec_file_load syscall already has
enough information for the kernel to inject the initrd and bootargs
properties into a DTB.
In practice on x86 today, kexec_file_load only supports booting to a
Linux kernel, because the in-kernel purgatory only implements the x86
Linux boot protocol. Analagously, for arm64 I think that the first
kernel should use its internal copy of the boot DTB, with /chosen fixed
up appropriately, assuming the next kernel is an arm64 Linux image.
If booting another OS, the only parts of the DTB I would expect to
change are the properties under chosen, as everything else *should* be
OS-independent. However the other OS may have a completely different
boot protocol, might not even take a DTB, and will likely need a
compeltely different purgatory implementation. So just allowing the DTB
to be altered isn't sufficient for that case.
There might be cases where we want a different DTB, but as far as I can
tell we have nothing analagous on x86 today. If we do need this, we
should have an idea of what real case(s) were trying to solve.
What I had in my mind was:
- Kdump
As Russel said, we definitely need to modify dtb.
In addition to bootargs and initrd proerties (FYI, in my arm64
implementation for arm64, eflcorehdr info is also passed as DT
property), we may want to remove unnecessary devices and
even add a dedicated storage device for storing a core dump image.
- Say, booting BE kernel on ACPI LE kernel
In this case, there is no useful dtb in the kernel.
Have said that, as Mark said, we may be able to use normal kexec_load
system call if we don't need a "secure" kexec.
BTW, why doesn't the current kexec_load have ability of verifying
a signature of initramfs image? Is IMA/EVM expected to be used
at runtime?
I believe there are some limitations for verify signatures in kexec_load.
First kexec-tools need to be trusted, but there's no way to sign and
verify signature of shared libraries. There maybe other limitations I
can not remember which are also reasons why Vivek moved to current
file based syscall.
Thanks
Dave
From: Dave Young <hidden> Date: 2016-07-14 01:50:44
On 07/13/16 at 10:34am, Mark Rutland wrote:
On Wed, Jul 13, 2016 at 10:36:14AM +0800, Dave Young wrote:
quoted
But consider we can kexec to a different kernel and a different initrd so there
will be use cases to pass a total different dtb as well.
It depends on what you mean by "a different kernel", and what this
implies for the DTB.
I thought about kexec as a boot loader just like other bootloaders.
So just like a normal boot kexec should also accept external dtb.
But acutally kexec is different because it can get original dtb and
use it. So I agreed if we can not find a real use case that we have
to extend it we should keep current interface.
I expect future arm64 Linux kernels to function with today's DTBs, and
the existing boot protocol. The kexec_file_load syscall already has
enough information for the kernel to inject the initrd and bootargs
properties into a DTB.
In practice on x86 today, kexec_file_load only supports booting to a
Linux kernel, because the in-kernel purgatory only implements the x86
Linux boot protocol. Analagously, for arm64 I think that the first
kernel should use its internal copy of the boot DTB, with /chosen fixed
up appropriately, assuming the next kernel is an arm64 Linux image.
If booting another OS, the only parts of the DTB I would expect to
change are the properties under chosen, as everything else *should* be
OS-independent. However the other OS may have a completely different
boot protocol, might not even take a DTB, and will likely need a
compeltely different purgatory implementation. So just allowing the DTB
to be altered isn't sufficient for that case.
There might be cases where we want a different DTB, but as far as I can
tell we have nothing analagous on x86 today. If we do need this, we
should have an idea of what real case(s) were trying to solve.
Hi Eric,
I'm trying to understand your concerns leading to your nack. I hope you
don't mind expanding your thoughts on them a bit.
Am Dienstag, 12 Juli 2016, 08:25:48 schrieb Eric W. Biederman:
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
I don't understand how the kernel signature will be invalidated.
There are some types of boot images that can embed a device tree blob in
them, but the kernel can also be handed a separate device tree blob from
firmware, the boot loader, or kexec. This latter case is what we are
discussing, so we are not talking about modifying an embedded blob in the
kernel image.
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
I also don't understand what you mean by code execution. How does passing a
device tree blob via kexec enables code execution? How can the signature
scheme be defeated?
--
[]'s
Thiago Jung Bauermann
IBM Linux Technology Center
Hi Eric,
I'm trying to understand your concerns leading to your nack. I hope you
don't mind expanding your thoughts on them a bit.
Am Dienstag, 12 Juli 2016, 08:25:48 schrieb Eric W. Biederman:
quoted
AKASHI Takahiro [off-list ref] writes:
quoted
Device tree blob must be passed to a second kernel on DTB-capable
archs, like powerpc and arm64, but the current kernel interface
lacks this support.
This patch extends kexec_file_load system call by adding an extra
argument to this syscall so that an arbitrary number of file descriptors
can be handed out from user space to the kernel.
See the background [1].
Please note that the new interface looks quite similar to the current
system call, but that it won't always mean that it provides the "binary
compatibility."
[1] http://lists.infradead.org/pipermail/kexec/2016-June/016276.html
So this design is wrong. The kernel already has the device tree blob,
you should not be extracting it from the kernel munging it, and then
reinserting it in the kernel if you want signatures and everything to
pass.
I don't understand how the kernel signature will be invalidated.
There are some types of boot images that can embed a device tree blob in
them, but the kernel can also be handed a separate device tree blob from
firmware, the boot loader, or kexec. This latter case is what we are
discussing, so we are not talking about modifying an embedded blob in the
kernel image.
quoted
What x86 does is pass it's equivalent of the device tree blob from one
kernel to another directly and behind the scenes. It does not go
through userspace for this.
Until a persuasive case can be made for going around the kernel and
probably adding a feature (like code execution) that can be used to
defeat the signature scheme I am going to nack this.
I also don't understand what you mean by code execution. How does passing a
device tree blob via kexec enables code execution? How can the signature
scheme be defeated?
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
In general, tampering with the hardware inventory of a machine opens up
a security hole, and one must be very cautious which modifications are
allowed. You're giving this power to an (unsigned, hence untrusted)
userspace application; Eric argues that only the kernel should have
this power.
Just my two cents,
Petr T
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2016-07-12 22:18:43
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
However, your point is valid as an attacker can redirect the console
and/or mounted root on the to-be-kexec'd kernel if they can modify
the DTB - and there's a whole host of subtle ways to do that, not
necessarily just modification of the kernel command line.
In general, tampering with the hardware inventory of a machine opens up
a security hole, and one must be very cautious which modifications are
allowed. You're giving this power to an (unsigned, hence untrusted)
userspace application; Eric argues that only the kernel should have
this power.
Given that, how does crashdump work in this scenario?
crashdump works by adding an elfcorehdr=address argument to the
crash-booted kernel's command line. If you can add to the kernel
command line, you can redirect the console and do all sorts of
other stuff like specifying a different filesystem to mount, etc.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
From: Stewart Smith <hidden> Date: 2016-07-13 05:00:16
Russell King - ARM Linux [off-list ref] writes:
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
--
Stewart Smith
OPAL Architect, IBM.
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2016-07-13 07:37:45
On Wed, Jul 13, 2016 at 02:59:51PM +1000, Stewart Smith wrote:
Russell King - ARM Linux [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
I think you misunderstood my point.
On ARM, we do not go:
kernel (kexec'd from) -> boot loader -> kernel (kexec'd to)
but we go:
kernel (kexec'd from) -> kernel (kexec'd to)
There's no intermediate step involving any bootloader.
Hence, my point is that the dtb loaded by kexec is _only_ used by the
kernel which is being kexec'd to, not by the bootloader, nor indeed
the kernel which it is loaded into.
Moreover, if you read the bit that I quoted (which is what I was
replying to), you'll notice that it is talking about the DTB loaded
by kexec somehow causing the _bootloader_ to be redirected to an
alternative console. This point is wholely false on ARM.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
On 13 July 2016 at 09:36, Russell King - ARM Linux
[off-list ref] wrote:
On Wed, Jul 13, 2016 at 02:59:51PM +1000, Stewart Smith wrote:
quoted
Russell King - ARM Linux [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
I think you misunderstood my point.
On ARM, we do not go:
kernel (kexec'd from) -> boot loader -> kernel (kexec'd to)
but we go:
kernel (kexec'd from) -> kernel (kexec'd to)
There's no intermediate step involving any bootloader.
Hence, my point is that the dtb loaded by kexec is _only_ used by the
kernel which is being kexec'd to, not by the bootloader, nor indeed
the kernel which it is loaded into.
Moreover, if you read the bit that I quoted (which is what I was
replying to), you'll notice that it is talking about the DTB loaded
by kexec somehow causing the _bootloader_ to be redirected to an
alternative console. This point is wholely false on ARM.
The particular example may not apply, but the argument that the DTB
-as a description of the hardware topology- needs to be signed if the
kernel is also signed is valid. We do the same in the UEFI stub, i.e.,
it normally takes a dtb= argument to allow the DTB to be overridden,
but this feature is disabled when Secure Boot is in effect. By the
same reasoning, if any kind of kexec kernel image validation is in
effect, we should either validate the DTB image as well, or disallow
external DTBs and only perform kexec with the kernel's current DTB
(the blob it was booted with, not the unflattened data structure)
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2016-07-13 08:10:51
On Wed, Jul 13, 2016 at 09:47:56AM +0200, Ard Biesheuvel wrote:
On 13 July 2016 at 09:36, Russell King - ARM Linux
[off-list ref] wrote:
quoted
On Wed, Jul 13, 2016 at 02:59:51PM +1000, Stewart Smith wrote:
quoted
Russell King - ARM Linux [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
I think you misunderstood my point.
On ARM, we do not go:
kernel (kexec'd from) -> boot loader -> kernel (kexec'd to)
but we go:
kernel (kexec'd from) -> kernel (kexec'd to)
There's no intermediate step involving any bootloader.
Hence, my point is that the dtb loaded by kexec is _only_ used by the
kernel which is being kexec'd to, not by the bootloader, nor indeed
the kernel which it is loaded into.
Moreover, if you read the bit that I quoted (which is what I was
replying to), you'll notice that it is talking about the DTB loaded
by kexec somehow causing the _bootloader_ to be redirected to an
alternative console. This point is wholely false on ARM.
The particular example may not apply, but the argument that the DTB
-as a description of the hardware topology- needs to be signed if the
kernel is also signed is valid. We do the same in the UEFI stub, i.e.,
it normally takes a dtb= argument to allow the DTB to be overridden,
but this feature is disabled when Secure Boot is in effect. By the
same reasoning, if any kind of kexec kernel image validation is in
effect, we should either validate the DTB image as well, or disallow
external DTBs and only perform kexec with the kernel's current DTB
(the blob it was booted with, not the unflattened data structure)
*Sigh* yes, I know full well, which is why I said what I said in my
_first_ reply:
"However, your point is valid as an attacker can redirect the console
and/or mounted root on the to-be-kexec'd kernel if they can modify
the DTB - and there's a whole host of subtle ways to do that, not
necessarily just modification of the kernel command line."
and I went on to raise a valid point about the necessity to do that
for crashdump, which has been _completely_ ignored.
So, I just stopped reading your reply after the first three lines,
because we are in fact in agreement... but thanks for trying to waste
my time.
Please, keep with the overall discussion, and stop replying to a single
email as a whole point in isolation to every other email in the thread.
And stop bikeshedding, by picking up on the easy stuff but ignoring the
more fundamental points, like the crashdump issue I mentioned in my
first reply and now this reply.
Thanks.
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.
From: Stewart Smith <hidden> Date: 2016-07-13 08:20:40
Ard Biesheuvel [off-list ref] writes:
On 13 July 2016 at 09:36, Russell King - ARM Linux
[off-list ref] wrote:
quoted
On Wed, Jul 13, 2016 at 02:59:51PM +1000, Stewart Smith wrote:
quoted
Russell King - ARM Linux [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
I think you misunderstood my point.
On ARM, we do not go:
kernel (kexec'd from) -> boot loader -> kernel (kexec'd to)
but we go:
kernel (kexec'd from) -> kernel (kexec'd to)
There's no intermediate step involving any bootloader.
Hence, my point is that the dtb loaded by kexec is _only_ used by the
kernel which is being kexec'd to, not by the bootloader, nor indeed
the kernel which it is loaded into.
Moreover, if you read the bit that I quoted (which is what I was
replying to), you'll notice that it is talking about the DTB loaded
by kexec somehow causing the _bootloader_ to be redirected to an
alternative console. This point is wholely false on ARM.
The particular example may not apply, but the argument that the DTB
-as a description of the hardware topology- needs to be signed if the
kernel is also signed is valid. We do the same in the UEFI stub, i.e.,
it normally takes a dtb= argument to allow the DTB to be overridden,
but this feature is disabled when Secure Boot is in effect. By the
same reasoning, if any kind of kexec kernel image validation is in
effect, we should either validate the DTB image as well, or disallow
external DTBs and only perform kexec with the kernel's current DTB
(the blob it was booted with, not the unflattened data structure)
DTB booted with != current description of hardware
We could have had: PCI hotplug, CPU/memory/cache offlined due to
hardware error, change in available pstates / CPU frequencies.
There is merit in having a signed dtb if you're booting a signed kernel
in a secure boot scenario. However, we still need to set up /chosen/ and
we still need a way to do something like the offb hack.
--
Stewart Smith
OPAL Architect, IBM.
From: Stewart Smith <hidden> Date: 2016-07-13 07:56:09
Russell King - ARM Linux [off-list ref] writes:
On Wed, Jul 13, 2016 at 02:59:51PM +1000, Stewart Smith wrote:
quoted
Russell King - ARM Linux [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
I think you misunderstood my point.
On ARM, we do not go:
kernel (kexec'd from) -> boot loader -> kernel (kexec'd to)
but we go:
kernel (kexec'd from) -> kernel (kexec'd to)
There's no intermediate step involving any bootloader.
Hence, my point is that the dtb loaded by kexec is _only_ used by the
kernel which is being kexec'd to, not by the bootloader, nor indeed
the kernel which it is loaded into.
Moreover, if you read the bit that I quoted (which is what I was
replying to), you'll notice that it is talking about the DTB loaded
by kexec somehow causing the _bootloader_ to be redirected to an
alternative console. This point is wholely false on ARM.
Ahh.. I missed the bootloader bit there.
In which case, we're the same on OpenPOWER, there is no intermediate
bootloader - in our case we have linux (with kexec) taking on what uboot
or grub is typically used for on other platforms.
--
Stewart Smith
OPAL Architect, IBM.
From: Russell King - ARM Linux <linux@armlinux.org.uk> Date: 2016-07-13 08:27:20
On Wed, Jul 13, 2016 at 05:55:33PM +1000, Stewart Smith wrote:
Russell King - ARM Linux [off-list ref] writes:
quoted
On Wed, Jul 13, 2016 at 02:59:51PM +1000, Stewart Smith wrote:
quoted
Russell King - ARM Linux [off-list ref] writes:
quoted
On Tue, Jul 12, 2016 at 10:58:05PM +0200, Petr Tesarik wrote:
quoted
I'm not an expert on DTB, so I can't provide an example of code
execution, but you have already mentioned the /chosen/linux,stdout-path
property. If an attacker redirects the bootloader to an insecure
console, they may get access to the system that would otherwise be
impossible.
I fail to see how kexec connects with the boot loader - the DTB image
that's being talked about is one which is passed from the currently
running kernel to the to-be-kexec'd kernel. For ARM (and I suspect
also ARM64) that's a direct call chain which doesn't involve any
boot loader or firmware, and certainly none that would involve the
passed DTB image.
For OpenPOWER machines, kexec is the bootloader. Our bootloader is a
linux kernel and initramfs with a UI (petitboot) - this means we never
have to write a device driver twice: write a kernel one and you're done
(for booting from the device and using it in your OS).
I think you misunderstood my point.
On ARM, we do not go:
kernel (kexec'd from) -> boot loader -> kernel (kexec'd to)
but we go:
kernel (kexec'd from) -> kernel (kexec'd to)
There's no intermediate step involving any bootloader.
Hence, my point is that the dtb loaded by kexec is _only_ used by the
kernel which is being kexec'd to, not by the bootloader, nor indeed
the kernel which it is loaded into.
Moreover, if you read the bit that I quoted (which is what I was
replying to), you'll notice that it is talking about the DTB loaded
by kexec somehow causing the _bootloader_ to be redirected to an
alternative console. This point is wholely false on ARM.
Ahh.. I missed the bootloader bit there.
In which case, we're the same on OpenPOWER, there is no intermediate
bootloader - in our case we have linux (with kexec) taking on what uboot
or grub is typically used for on other platforms.
Indeed - maybe Eric knows better, but I can't see any situation where
the dtb we load via kexec should ever affect "the bootloader", unless
the "kernel" that's being loaded into kexec is "the bootloader".
Now, going back to the more fundamental issue raised in my first reply,
about the kernel command line.
On x86, I can see that it _is_ possible for userspace to specify a
command line, and the kernel loading the image provides the command
line to the to-be-kexeced kernel with very little checking. So, if
your kernel is signed, what stops the "insecure userspace" loading
a signed kernel but giving it an insecure rootfs and/or console?
--
RMK's Patch system: http://www.armlinux.org.uk/developer/patches/
FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up
according to speedtest.net.