From mboxrd@z Thu Jan 1 00:00:00 1970 From: takahiro.akashi@linaro.org (AKASHI Takahiro) Date: Wed, 14 Mar 2018 15:40:04 +0900 Subject: [Query] ARM64 kaslr support - randomness, seeding and kdump In-Reply-To: References: <20180313102158.GI25863@linaro.org> <20180313104715.prurmrizho4ddc4l@lakrids.cambridge.arm.com> <20180313110747.GJ25863@linaro.org> <20180313112016.ocx4qqhji3zfwjhs@lakrids.cambridge.arm.com> <20180314021050.GK25863@linaro.org> Message-ID: <20180314064002.GL25863@linaro.org> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On Wed, Mar 14, 2018 at 10:33:03AM +0530, Bhupesh Sharma wrote: > ' > > On Wed, Mar 14, 2018 at 7:40 AM, AKASHI Takahiro > wrote: > > On Wed, Mar 14, 2018 at 01:18:47AM +0530, Bhupesh Sharma wrote: > >> On Tue, Mar 13, 2018 at 4:50 PM, Mark Rutland wrote: > >> > On Tue, Mar 13, 2018 at 08:07:49PM +0900, AKASHI Takahiro wrote: > >> >> On Tue, Mar 13, 2018 at 10:47:15AM +0000, Mark Rutland wrote: > >> >> > On Tue, Mar 13, 2018 at 07:22:03PM +0900, AKASHI Takahiro wrote: > >> >> > > On Mon, Mar 12, 2018 at 08:58:00PM +0000, Ard Biesheuvel wrote: > >> >> > > > On 12 March 2018 at 20:14, Bhupesh Sharma wrote: > >> >> > > >> >> > > More importantly, neither arm64 _kexec_ supports kaslr. > >> > >> Sorry if my earlier email was not clear on this, but I meant both the > >> kdump/kexec cases. > >> > >> While for kdump there is no current requirement for physical > >> randomization, for kexec it would be good to support the same as the > >> primary kernel was already supporting kaslr and the secondary kernel > >> (if compiled with CONFIG_RANDOMIZE_BASE) would randomizes the virtual > >> address at which the kernel image is loaded. > >> > >> If we have physical randomization supported in this case in the > >> secondary/kexec kernel we can avoid potential misuse related to the > >> physical address being known at which the secondary/kexec kernel is > >> loaded. > >> > >> >> > > >> >> > The below is just considering this, and ignoring kdump (where I don't > >> >> > think we care at all about KASLR). > >> >> > > >> >> > > Currently kexec-tools is set to determine where the kernel actually be > >> >> > > loaded, using a constant offset, text_offset, which comes from an image's > >> >> > > boot header and relocation of an image to the load address is performed > >> >> > > at the very end of the first kernel without knowing whether the 2nd kernel > >> >> > > has kaslr support enabled or not. > >> >> > > >> >> > The kexec tools shouldn't need to know whether the kernel supports KASLR > >> >> > at all. > >> >> > > >> >> > If the new kernel image has bit 3 (Kernel physical placement) set, kexec > >> >> > tools can choose to randomize the physical load address, regardless of > >> >> > whether that kernel has KASLR enabled. > >> >> > >> >> So, by definition, is randomness, if we say so, in physical address not > >> >> part of KASLR? > >> > > >> > Physical randomization is not part of the kernel's KASLR implementation. > >> > > >> > We happen to do it in the EFI stub, because we can in that context. But > >> > generally, physical randomization is not part of arm64's in-kernel > >> > KASLR. > >> > > >> > For various reasons, the physical address that the kernel is loaded to > >> > may be arbitrary, so we have to cope with physical randomization > >> > regardless. > >> > >> Indeed, since the primary kernel depends on the firmware's > >> EFI_RNG_PROTOCOL implementation (if available) to randomise the > >> physical location of the kernel Image, for the secondary/kexec kernel, > >> if can have two approaches to enable physical randomization: > > > > I believe that you're now talking about "virtual" randomization. > > > >> - Implement a UEFI stub for loading the kexec kernel as well, or > >> > >> - Extend the 'kexec-tools' to invoke the entropy source available in > >> the primary kernel (provided by the firmware via EFI_RNG_PROTOCOL) to > >> generate a random seed to randomize the physical address and populate > >> it in the '/chosen/kaslr-seed' property of the device-tree being > >> passed to the secondary/kexec kernel and let the normal code flow in > >> ' arch/arm64/kernel/kaslr.c', function 'kaslr_early_init' to get the > >> seed for the secondary kernel from the '/chosen/kaslr-seed' property > >> itself. > >> > >> Personally the later approach looks simpler to me from a implementation p-o-v. > > > > If kaslr-seed has a critical value in terms of security, is kexec-tools > > a right place? It is exposed to user space albeit for a short time of period. > > But doesn't this problem exist in the arm64 kexec design already for > kexec_load() case? > Since it relies on sending a dtb (updated with the > 'linux,usable-memory') property to the secondary/kexec kernel, we can > easily introduce a security vulnerability in the system by expanding > the dtb to include a static value for '/chosen/kaslr-seed'. > > Consider the following scenario (which I tried yesterday on my arm64 > board just out of curiosity): > > 1. Primary kernel and secondary kernel both are compiled with kaslr > flags (CONFIG_RANDOMIZE_BASE) > > 2. Primary kernel is loaded at random physical address on the basis of > the '/chosen/kaslr-seed' property. > > 3. Thereafter this property is memset to 0. > > 4. Now we call 'kexec -l + kexec -e' combination to warm boot to a > secondary/kexec kernel. > > 5. Since 'kexec-tools' picks up the existing dtb with > '/chosen/kaslr-seed' set to 0, it passes the same to the > secondary/kexec kernel. > > 6. Instead if we have a vulnerable 'kexec-tools' user space > application, which unpacks the dtb and sets the '/chosen/kaslr-seed' > to a known static non-zero value. > > 7. Now the secondary/kexec kernel is invoked and the > 'kaslr_early_init()' finds a valid, non-zero '/chosen/kaslr-seed' and > uses it to calculate the offsets for randomizing the linear region and > randomizing the base of the module region. Since the seed was a known > static value, determining the randomized bases of the above regions is > always possible. > > So, I am not sure the existing 'kexec-tools' design can protect us > from such security vulnerabilities anyway as we rely on passing the > dtb to the secondary kernel for arm64 kexec to work. > > What I was suggesting in the previous mail was that instead of passing > a zero '/chosen/kaslr-seed' to the secondary/kexec kernel (which > effectively leads to a *nokaslr* behaviour), we can do the right thing > by using a entropy source (if available) to generate a random seed. I will comment on those later if any. > > > (Speaking of kexec_file, we can easily adopt this approach as fdt modification > > is done totally inside the kernel. Likewise, "physical" randomization would be > > easy in part of arm64_relocate_new_kernel() because we only have to care bit 3 > > of boot header's flags after Mark's comment.) > > I think we need to handle both the kexec_load() and kexec_file_load() > cases transparently as the user may invoke either of them. > > Just for my understanding - in the arm64 kexec_file_load() case we > don't pass the modified dtb via user-space to the secondary kernel. > Right (sorry I still haven't looked at the latest kexec_file_load() > patches yet)? Correct. In kexec_file case, the 1st kernel is responsible for preparing dtb for 2nd kernel by duplicating the current one and modifying it if necessary. As such, kexec_file hardly relies on kexec-tools. (You know kexec-tools sources have not been well reviewed by anyone.) Thanks, -Takahiro AKASHI > Thanks, > Bhupesh > > > > >> For example, currently in the kernel we normally invoke 'update_fdt' > >> (inside 'drivers/fimrware/efi/libstub/fdt.c') from the UEFI stub, > >> wherein we have this check for CONFIG_RANDOMIZE_BASE: > >> > >> static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, > >> unsigned long orig_fdt_size, > >> void *fdt, int new_fdt_size, char *cmdline_ptr, > >> u64 initrd_addr, u64 initrd_size) > >> { > >> > >> ... > >> if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { > >> efi_status_t efi_status; > >> > >> efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64), > >> (u8 *)&fdt_val64); > >> if (efi_status == EFI_SUCCESS) { > >> status = fdt_setprop(fdt, node, "kaslr-seed", > >> &fdt_val64, sizeof(fdt_val64)); > >> if (status) > >> goto fdt_set_fail; > >> } else if (efi_status != EFI_NOT_FOUND) { > >> return efi_status; > >> } > >> } > >> ... > >> } > >> > >> I am thinking of modifying the kexec-tools code for arm64 (which > >> already processes the device tree to pass it to the secondary/kexec > >> kernel), so that we can do something like the following: > >> > >> --> efi_get_random_bytes(sys_table, sizeof(fdt_val64), > >> (u8 *)&fdt_val64); > >> ------> fdt_setprop(fdt, node, "kaslr-seed", &fdt_val64, > >> sizeof(fdt_val64)); > >> > >> Now when the modified dtb is passed to the secondary/kexec kernel it > >> will automatically find a valid seed, will wipe it to zero for > >> security reasons and use the same to perform physical randomization. > >> > >> If this looks sensible I will try to take a stab at this approach and > >> share results on thread in the coming days. > >> Please share your inputs. > >> > >> Regards, > >> Bhupesh From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from mail-io0-x22d.google.com ([2607:f8b0:4001:c06::22d]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1ew04e-00006V-E8 for kexec@lists.infradead.org; Wed, 14 Mar 2018 06:39:48 +0000 Received: by mail-io0-x22d.google.com with SMTP id d71so3051451iog.4 for ; Tue, 13 Mar 2018 23:39:34 -0700 (PDT) Date: Wed, 14 Mar 2018 15:40:04 +0900 From: AKASHI Takahiro Subject: Re: [Query] ARM64 kaslr support - randomness, seeding and kdump Message-ID: <20180314064002.GL25863@linaro.org> References: <20180313102158.GI25863@linaro.org> <20180313104715.prurmrizho4ddc4l@lakrids.cambridge.arm.com> <20180313110747.GJ25863@linaro.org> <20180313112016.ocx4qqhji3zfwjhs@lakrids.cambridge.arm.com> <20180314021050.GK25863@linaro.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "kexec" Errors-To: kexec-bounces+dwmw2=infradead.org@lists.infradead.org To: Bhupesh Sharma Cc: Mark Rutland , Bhupesh SHARMA , kexec@lists.infradead.org, linux-arm-kernel , Ard Biesheuvel On Wed, Mar 14, 2018 at 10:33:03AM +0530, Bhupesh Sharma wrote: > ' > > On Wed, Mar 14, 2018 at 7:40 AM, AKASHI Takahiro > wrote: > > On Wed, Mar 14, 2018 at 01:18:47AM +0530, Bhupesh Sharma wrote: > >> On Tue, Mar 13, 2018 at 4:50 PM, Mark Rutland wrote: > >> > On Tue, Mar 13, 2018 at 08:07:49PM +0900, AKASHI Takahiro wrote: > >> >> On Tue, Mar 13, 2018 at 10:47:15AM +0000, Mark Rutland wrote: > >> >> > On Tue, Mar 13, 2018 at 07:22:03PM +0900, AKASHI Takahiro wrote: > >> >> > > On Mon, Mar 12, 2018 at 08:58:00PM +0000, Ard Biesheuvel wrote: > >> >> > > > On 12 March 2018 at 20:14, Bhupesh Sharma wrote: > >> >> > > >> >> > > More importantly, neither arm64 _kexec_ supports kaslr. > >> > >> Sorry if my earlier email was not clear on this, but I meant both the > >> kdump/kexec cases. > >> > >> While for kdump there is no current requirement for physical > >> randomization, for kexec it would be good to support the same as the > >> primary kernel was already supporting kaslr and the secondary kernel > >> (if compiled with CONFIG_RANDOMIZE_BASE) would randomizes the virtual > >> address at which the kernel image is loaded. > >> > >> If we have physical randomization supported in this case in the > >> secondary/kexec kernel we can avoid potential misuse related to the > >> physical address being known at which the secondary/kexec kernel is > >> loaded. > >> > >> >> > > >> >> > The below is just considering this, and ignoring kdump (where I don't > >> >> > think we care at all about KASLR). > >> >> > > >> >> > > Currently kexec-tools is set to determine where the kernel actually be > >> >> > > loaded, using a constant offset, text_offset, which comes from an image's > >> >> > > boot header and relocation of an image to the load address is performed > >> >> > > at the very end of the first kernel without knowing whether the 2nd kernel > >> >> > > has kaslr support enabled or not. > >> >> > > >> >> > The kexec tools shouldn't need to know whether the kernel supports KASLR > >> >> > at all. > >> >> > > >> >> > If the new kernel image has bit 3 (Kernel physical placement) set, kexec > >> >> > tools can choose to randomize the physical load address, regardless of > >> >> > whether that kernel has KASLR enabled. > >> >> > >> >> So, by definition, is randomness, if we say so, in physical address not > >> >> part of KASLR? > >> > > >> > Physical randomization is not part of the kernel's KASLR implementation. > >> > > >> > We happen to do it in the EFI stub, because we can in that context. But > >> > generally, physical randomization is not part of arm64's in-kernel > >> > KASLR. > >> > > >> > For various reasons, the physical address that the kernel is loaded to > >> > may be arbitrary, so we have to cope with physical randomization > >> > regardless. > >> > >> Indeed, since the primary kernel depends on the firmware's > >> EFI_RNG_PROTOCOL implementation (if available) to randomise the > >> physical location of the kernel Image, for the secondary/kexec kernel, > >> if can have two approaches to enable physical randomization: > > > > I believe that you're now talking about "virtual" randomization. > > > >> - Implement a UEFI stub for loading the kexec kernel as well, or > >> > >> - Extend the 'kexec-tools' to invoke the entropy source available in > >> the primary kernel (provided by the firmware via EFI_RNG_PROTOCOL) to > >> generate a random seed to randomize the physical address and populate > >> it in the '/chosen/kaslr-seed' property of the device-tree being > >> passed to the secondary/kexec kernel and let the normal code flow in > >> ' arch/arm64/kernel/kaslr.c', function 'kaslr_early_init' to get the > >> seed for the secondary kernel from the '/chosen/kaslr-seed' property > >> itself. > >> > >> Personally the later approach looks simpler to me from a implementation p-o-v. > > > > If kaslr-seed has a critical value in terms of security, is kexec-tools > > a right place? It is exposed to user space albeit for a short time of period. > > But doesn't this problem exist in the arm64 kexec design already for > kexec_load() case? > Since it relies on sending a dtb (updated with the > 'linux,usable-memory') property to the secondary/kexec kernel, we can > easily introduce a security vulnerability in the system by expanding > the dtb to include a static value for '/chosen/kaslr-seed'. > > Consider the following scenario (which I tried yesterday on my arm64 > board just out of curiosity): > > 1. Primary kernel and secondary kernel both are compiled with kaslr > flags (CONFIG_RANDOMIZE_BASE) > > 2. Primary kernel is loaded at random physical address on the basis of > the '/chosen/kaslr-seed' property. > > 3. Thereafter this property is memset to 0. > > 4. Now we call 'kexec -l + kexec -e' combination to warm boot to a > secondary/kexec kernel. > > 5. Since 'kexec-tools' picks up the existing dtb with > '/chosen/kaslr-seed' set to 0, it passes the same to the > secondary/kexec kernel. > > 6. Instead if we have a vulnerable 'kexec-tools' user space > application, which unpacks the dtb and sets the '/chosen/kaslr-seed' > to a known static non-zero value. > > 7. Now the secondary/kexec kernel is invoked and the > 'kaslr_early_init()' finds a valid, non-zero '/chosen/kaslr-seed' and > uses it to calculate the offsets for randomizing the linear region and > randomizing the base of the module region. Since the seed was a known > static value, determining the randomized bases of the above regions is > always possible. > > So, I am not sure the existing 'kexec-tools' design can protect us > from such security vulnerabilities anyway as we rely on passing the > dtb to the secondary kernel for arm64 kexec to work. > > What I was suggesting in the previous mail was that instead of passing > a zero '/chosen/kaslr-seed' to the secondary/kexec kernel (which > effectively leads to a *nokaslr* behaviour), we can do the right thing > by using a entropy source (if available) to generate a random seed. I will comment on those later if any. > > > (Speaking of kexec_file, we can easily adopt this approach as fdt modification > > is done totally inside the kernel. Likewise, "physical" randomization would be > > easy in part of arm64_relocate_new_kernel() because we only have to care bit 3 > > of boot header's flags after Mark's comment.) > > I think we need to handle both the kexec_load() and kexec_file_load() > cases transparently as the user may invoke either of them. > > Just for my understanding - in the arm64 kexec_file_load() case we > don't pass the modified dtb via user-space to the secondary kernel. > Right (sorry I still haven't looked at the latest kexec_file_load() > patches yet)? Correct. In kexec_file case, the 1st kernel is responsible for preparing dtb for 2nd kernel by duplicating the current one and modifying it if necessary. As such, kexec_file hardly relies on kexec-tools. (You know kexec-tools sources have not been well reviewed by anyone.) Thanks, -Takahiro AKASHI > Thanks, > Bhupesh > > > > >> For example, currently in the kernel we normally invoke 'update_fdt' > >> (inside 'drivers/fimrware/efi/libstub/fdt.c') from the UEFI stub, > >> wherein we have this check for CONFIG_RANDOMIZE_BASE: > >> > >> static efi_status_t update_fdt(efi_system_table_t *sys_table, void *orig_fdt, > >> unsigned long orig_fdt_size, > >> void *fdt, int new_fdt_size, char *cmdline_ptr, > >> u64 initrd_addr, u64 initrd_size) > >> { > >> > >> ... > >> if (IS_ENABLED(CONFIG_RANDOMIZE_BASE)) { > >> efi_status_t efi_status; > >> > >> efi_status = efi_get_random_bytes(sys_table, sizeof(fdt_val64), > >> (u8 *)&fdt_val64); > >> if (efi_status == EFI_SUCCESS) { > >> status = fdt_setprop(fdt, node, "kaslr-seed", > >> &fdt_val64, sizeof(fdt_val64)); > >> if (status) > >> goto fdt_set_fail; > >> } else if (efi_status != EFI_NOT_FOUND) { > >> return efi_status; > >> } > >> } > >> ... > >> } > >> > >> I am thinking of modifying the kexec-tools code for arm64 (which > >> already processes the device tree to pass it to the secondary/kexec > >> kernel), so that we can do something like the following: > >> > >> --> efi_get_random_bytes(sys_table, sizeof(fdt_val64), > >> (u8 *)&fdt_val64); > >> ------> fdt_setprop(fdt, node, "kaslr-seed", &fdt_val64, > >> sizeof(fdt_val64)); > >> > >> Now when the modified dtb is passed to the secondary/kexec kernel it > >> will automatically find a valid seed, will wipe it to zero for > >> security reasons and use the same to perform physical randomization. > >> > >> If this looks sensible I will try to take a stab at this approach and > >> share results on thread in the coming days. > >> Please share your inputs. > >> > >> Regards, > >> Bhupesh _______________________________________________ kexec mailing list kexec@lists.infradead.org http://lists.infradead.org/mailman/listinfo/kexec