Command line randomness
v3 cover Command line randomness
Hi,
This is v3 of the series to add the kernel command line as a source of randomness. The main change from v2 is to correctly place the command line randomness _before_ the stack canary initialization so the canary can take advantage of that.
Daniel Micay (1):
extract early boot entropy from the passed cmdline
Laura Abbott (1):
init: Move stack canary initialization after setup_arch
init/main.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
Signature · 1 line
2.13.0
PATCH v3 1/2 init: Move stack canary initialization after setup_arch
From: Laura Abbott <[email protected]>
Stack canary intialization involves getting a random number. Getting this random number may involve accessing caches or other architectural specific features which are not available until after the architecture is setup. Move the stack canary initialization later to accomodate this.
---
v3: Ack from Kees
--- init/main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
init/main.c +5 -6
@@ -515,12 +515,6 @@ asmlinkage __visible void __init start_kernel(void)smp_setup_processor_id ();debug_objects_early_init (); -/* -* Set up the initial canary ASAP: -*/ -add_latent_entropy (); -boot_init_stack_canary (); -cgroup_init_early ();local_irq_disable ();
@@ -534,6 +528,11 @@ asmlinkage __visible void __init start_kernel(void)page_address_init ();pr_notice ("%s" , linux_banner);setup_arch (&command_line); +/* +* Set up the the initial canary and entropy after arch +*/ +add_latent_entropy (); +boot_init_stack_canary ();mm_init_cpumask (&init_mm);setup_command_line (command_line);setup_nr_cpu_ids ();
Signature · 1 line
2.13.0
PATCH v3 2/2 extract early boot entropy from the passed cmdline
In reply to Laura AbbottFrom: Daniel Micay <[email protected]>
Existing Android bootloaders usually pass data useful as early entropy on the kernel command-line. It may also be the case on other embedded systems. Sample command-line from a Google Pixel running CopperheadOS:
console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0
androidboot.hardware=sailfish user_debug=31 ehci-hcd.park=3
lpm_levels.sleep_disabled=1 cma=32M@0-0xffffffff buildvariant=user
veritykeyid=id:dfcb9db0089e5b3b4090a592415c28e1cb4545ab
androidboot.bootdevice=624000.ufshc androidboot.verifiedbootstate=yellow
androidboot.veritymode=enforcing androidboot.keymaster=1
androidboot.serialno=FA6CE0305299 androidboot.baseband=msm
mdss_mdp.panel=1:dsi:0:qcom,mdss_dsi_samsung_ea8064tg_1080p_cmd:1:none:cfg:single_dsi
androidboot.slot_suffix=_b fpsimd.fpsimd_settings=0
app_setting.use_app_setting=0 kernelflag=0x00000000 debugflag=0x00000000
androidboot.hardware.revision=PVT radioflag=0x00000000
radioflagex1=0x00000000 radioflagex2=0x00000000 cpumask=0x00000000
androidboot.hardware.ddr=4096MB,Hynix,LPDDR4 androidboot.ddrinfo=00000006
androidboot.ddrsize=4GB androidboot.hardware.color=GRA00
androidboot.hardware.ufs=32GB,Samsung androidboot.msm.hw_ver_id=268824801
androidboot.qf.st=2 androidboot.cid=11111111 androidboot.mid=G-2PW4100
androidboot.bootloader=8996-012001-1704121145
androidboot.oem_unlock_support=1 androidboot.fp_src=1
androidboot.htc.hrdump=detected androidboot.ramdump.opt=mem@2g:2g,mem@4g:2g
androidboot.bootreason=reboot androidboot.ramdump_enable=0 ro
root=/dev/dm-0 dm="system none ro,0 1 android-verity /dev/sda34"
rootwait skip_initramfs init=/init androidboot.wificountrycode=US
androidboot.boottime=1BLL:85,1BLE:669,2BLL:0,2BLE:1777,SW:6,KL:8136Among other things, it contains a value unique to the device (androidboot.serialno=FA6CE0305299), unique to the OS builds for the device variant (veritykeyid=id:dfcb9db0089e5b3b4090a592415c28e1cb4545ab) and timings from the bootloader stages in milliseconds (androidboot.boottime=1BLL:85,1BLE:669,2BLL:0,2BLE:1777,SW:6,KL:8136).
---
v3: add_device_randomness comes before canary initialization, clarified comment.
--- init/main.c | 2 ++ 1 file changed, 2 insertions(+)
init/main.c +2 -0
@@ -530,8 +530,10 @@ asmlinkage __visible void __init start_kernel(void)setup_arch (&command_line);/* * Set up the the initial canary and entropy after arch +* and after adding latent and command line entropy. */ add_latent_entropy (); +add_device_randomness (command_line,strlen (command_line));boot_init_stack_canary ();mm_init_cpumask (&init_mm);setup_command_line (command_line);
Signature · 1 line
2.13.0
Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
Quoted 37 lines · Laura Abbott
From: Daniel Micay <[email protected]>
Existing Android bootloaders usually pass data useful as early entropy on the kernel command-line. It may also be the case on other embedded systems. Sample command-line from a Google Pixel running CopperheadOS:
console=ttyHSL0,115200,n8 androidboot.console=ttyHSL0 androidboot.hardware=sailfish user_debug=31 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 cma=32M@0-0xffffffff buildvariant=user veritykeyid=id:dfcb9db0089e5b3b4090a592415c28e1cb4545ab androidboot.bootdevice=624000.ufshc androidboot.verifiedbootstate=yellow androidboot.veritymode=enforcing androidboot.keymaster=1 androidboot.serialno=FA6CE0305299 androidboot.baseband=msm mdss_mdp.panel=1:dsi:0:qcom,mdss_dsi_samsung_ea8064tg_1080p_cmd:1:none:cfg:single_dsi androidboot.slot_suffix=_b fpsimd.fpsimd_settings=0 app_setting.use_app_setting=0 kernelflag=0x00000000 debugflag=0x00000000 androidboot.hardware.revision=PVT radioflag=0x00000000 radioflagex1=0x00000000 radioflagex2=0x00000000 cpumask=0x00000000 androidboot.hardware.ddr=4096MB,Hynix,LPDDR4 androidboot.ddrinfo=00000006 androidboot.ddrsize=4GB androidboot.hardware.color=GRA00 androidboot.hardware.ufs=32GB,Samsung androidboot.msm.hw_ver_id=268824801 androidboot.qf.st=2 androidboot.cid=11111111 androidboot.mid=G-2PW4100 androidboot.bootloader=8996-012001-1704121145 androidboot.oem_unlock_support=1 androidboot.fp_src=1 androidboot.htc.hrdump=detected androidboot.ramdump.opt=mem@2g:2g,mem@4g:2g androidboot.bootreason=reboot androidboot.ramdump_enable=0 ro root=/dev/dm-0 dm="system none ro,0 1 android-verity /dev/sda34" rootwait skip_initramfs init=/init androidboot.wificountrycode=US androidboot.boottime=1BLL:85,1BLE:669,2BLL:0,2BLE:1777,SW:6,KL:8136Among other things, it contains a value unique to the device (androidboot.serialno=FA6CE0305299), unique to the OS builds for the device variant (veritykeyid=id:dfcb9db0089e5b3b4090a592415c28e1cb4545ab) and timings from the bootloader stages in milliseconds (androidboot.boottime=1BLL:85,1BLE:669,2BLL:0,2BLE:1777,SW:6,KL:8136).
Quoted 3 lines
Signed-off-by Daniel Micay <[email protected]>[labbott: Line-wrapped command line]Signed-off-by Laura Abbott <[email protected]>
Thanks!
-Kees
Quoted 24 lines
---
v3:add_device_randomnesscomes before canary initialization, clarified comment.--- init/main.c | 2 ++ 1 file changed, 2 insertions(+)init/main.c +2
-1@@ -530,8 +530,10 @@ asmlinkage __visible void __init start_kernel(void)setup_arch (&command_line);/* * Set up the the initial canary and entropy after arch +* and after adding latent and command line entropy. */ add_latent_entropy (); +add_device_randomness (command_line,strlen (command_line));boot_init_stack_canary ();mm_init_cpumask (&init_mm);setup_command_line (command_line); --2.13.0
Signature · 2 lines
Kees Cook Pixel Security
Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
In reply to Laura AbbottQuoted 5 lines · Laura Abbott
From: Daniel Micay <[email protected]>
Existing Android bootloaders usually pass data useful as early entropy on the kernel command-line. It may also be the case on other embedded systems.....
May I suggest a slight adjustment to the beginning commit description?
Feed the boot command-line as to the /dev/random entropy pool
Existing Android bootloaders usually pass data which may not be known by an external attacker on the kernel command-line. It may also be the case on other embedded systems. Sample command-line from a Google Pixel running CopperheadOS....
The idea here is to if anything, err on the side of under-promising the amount of security we can guarantee that this technique will provide. For example, how hard is it really for an attacker who has an APK installed locally to get the device serial number? Or the OS version? And how much variability is there in the bootloader stages in milliseconds?
I think we should definitely do this. So this is more of a request to be very careful what we promise in the commit description, not an objection to the change itself.
Cheers,
- Ted
Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
Quoted 18 lines · Theodore Ts'o
Quoted 7 lines · Laura Abbott
From: Daniel Micay <[email protected]>
Existing Android bootloaders usually pass data useful as early entropy
on the kernel command-line. It may also be the case on other embedded
systems.....May I suggest a slight adjustment to the beginning commit description?
Feed the boot command-line as to the
/dev/randomentropy poolExisting Android bootloaders usually pass data which may not be known by an external attacker on the kernel command-line. It may also be the case on other embedded systems. Sample command-line from a Google Pixel running CopperheadOS....
Quoted 6 lines
The idea here is to if anything, err on the side of under-promising the amount of security we can guarantee that this technique will provide. For example, how hard is it really for an attacker who has an APK installed locally to get the device serial number? Or the OS version? And how much variability is there in the bootloader stages in milliseconds?
The serial number is currently accessible to local apps up until Android 7.x so it doesn't have value if the adversary has local access. Access to it without the READ_PHONE_STATE permission is being removed for apps targeting Android 8.0 and will presumably be restructed for all apps at some point in the future:
https://android-developers.googleblog.com/2017/04/changes-to-device-identifiers-in.html
Some bootloader stages vary a bit in time each boot. There's not much variance or measurement precision so there's only a small amount of entropy from this. The ones that consistently vary in timing do so independently from each other so that helps a bit. Also worth noting that before Android 8.0+, local apps can access the boot times since it's written to a system property. After Android 8.0+, all that stuff is inaccessible to them (no permission to get them) since there's a whitelisting model for system property access.
Quoted 3 lines
I think we should definitely do this. So this is more of a request to be very careful what we promise in the commit description, not an objection to the change itself.
I did say 'external attacker' but it could be made clearer. It's primarily aimed at getting a tiny bit of extra entropy for the kernel stack canary and other probabilistic exploit mitigations set up in early boot. On non-x86 archs, i.e. 99.9% of Android devices, the kernel stack canary remains the same after it's set up in that early boot code.
Android devices almost all have a hardware RNG and Android init blocks until a fair bit of data is read from it along with restoring entropy that's regularly saved while running, but unfortunately that's not available at this point in the boot process.
The kernel could save / restore entropy using pstore (which at least Nexus / Pixel devices have - not sure about others). I don't know how early that could feasibly be done. Ideally it would do that combined with early usage of the hwrng.
Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
Quoted 1 line
I did say 'external attacker' but it could be made clearer.
Er, s/say/mean to imply/
I do think it will have some local value after Android 8 which should start shipping in a few days though.
I'll look into having the kernel stash some entropy in pstore soon since that seems like it could be a great improvement. I'm not sure how often / where it should hook into for regularly refreshing it though. Doing it only on powering down isn't ideal.
Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
Quoted 3 lines · Daniel Micay
Quoted 1 line
I did say 'external attacker' but it could be made clearer.
Er, s/say/mean to imply/
Right, that's why I had suggested modifying the first few lines of the commit description to read something like this:
Feed the boot command-line as to the /dev/random entropy pool
Existing Android bootloaders usually pass data which may not be known by an external attacker on the kernel command-line. It may also be the case on other embedded systems. Sample command-line from a Google Pixel running CopperheadOS:
(Or something like that.)
Quoted 4 lines
I'll look into having the kernel stash some entropy in pstore soon since that seems like it could be a great improvement. I'm not sure how often / where it should hook into for regularly refreshing it though. Doing it only on powering down isn't ideal.
One thing we could do is to agree on a standard place where the entropy would be stashed, and then have the kernel remove it from being visible in /proc/cmdline. That's not a perfect answer, since the user might be able to look at the command line via other mechanisms. (For example, on x86, by looking at GRUB while the system is booting.)
However, an attacker who is merely running code on the local system is not likely to be gain access to that value --- so it's definitely an improvement.
Refreshing the entry immediately after boot, and before a clean shutdown would be ideal from a security perspective. I don't know if there are write endurance issues with updating the pstore that frequently, though.
- Ted
Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
In reply to Theodore Ts'oQuoted 23 lines · Theodore Ts'o
Quoted 5 lines · Laura Abbott
From: Daniel Micay <[email protected]>
Existing Android bootloaders usually pass data useful as early entropy on the kernel command-line. It may also be the case on other embedded systems.....
May I suggest a slight adjustment to the beginning commit description?
Feed the boot command-line as to the
/dev/randomentropy poolExisting Android bootloaders usually pass data which may not be known by an external attacker on the kernel command-line. It may also be the case on other embedded systems. Sample command-line from a Google Pixel running CopperheadOS....
The idea here is to if anything, err on the side of under-promising the amount of security we can guarantee that this technique will provide. For example, how hard is it really for an attacker who has an APK installed locally to get the device serial number? Or the OS version? And how much variability is there in the bootloader stages in milliseconds?
Quoted 3 lines
I think we should definitely do this. So this is more of a request to be very careful what we promise in the commit description, not an objection to the change itself.
The command line is visible to unpriviledged userspace (/proc/cmdline, dmesg). Is that a problem?
U-boot already does some crypto stuff, so it may have some randomness. Should we create parameter random=xxxxxxxxxxx that is "censored" during kernel boot?
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
Re: [kernel-hardening] Re: [PATCHv3 2/2] extract early boot entropy from the passed cmdline
Quoted 2 lines · Pavel Machek
The command line is visible to unpriviledged userspace (
/proc/cmdline, dmesg). Is that a problem?
These files are not exposed to untrusted processes on Android.
Signature · 1 line
Nick Kralevich | Android Security | [email protected] | 650.214.4037