Bug 1568263

Summary: kaslr: arm64 kernel does not use entropy source supplied from EFI_RNG_PROTOCOL to populate /dev/urandom
Product: [Fedora] Fedora Reporter: Bhupesh Sharma <bhsharma>
Component: kernelAssignee: Bhupesh Sharma <bhsharma>
Status: CLOSED WONTFIX QA Contact: Fedora Extras Quality Assurance <extras-qa>
Severity: low Docs Contact:
Priority: unspecified    
Version: rawhideCC: airlied, bhsharma, bskeggs, ewk, hdegoede, ichavero, itamar, jarodwilson, jglisse, john.j5live, jonathan, josef, kdump-bugs, kernel-maint, linville, mchehab, mjg59, ruyang, steved
Target Milestone: ---   
Target Release: ---   
Hardware: aarch64   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-07-30 06:29:44 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:

Description Bhupesh Sharma 2018-04-17 05:09:57 UTC
Description of problem:

I was doing some experimentation with kernel modules (or extending the argument even to user-space applications) which relies on random number generation support from the kernel using 'getrandom' / 'get_random_bytes' kind of
syscall/kernel interface, on platforms where we don't have a
compatible EFI firmware which supports EFI_RNG_PROTOCOL, I was
thinking that there would not be sufficient entropy (inside '/dev/urandom') available for the caller kernel modules (or user-space applications)
and I was looking to enable 'CONFIG_WARN_ALL_UNSEEDED_RANDOM=y' to ensure that
callers of unseeded randomness in such kernel modules/user-space
applications are WARN'ed.

1. Instead I saw that random numbers are available on these platforms
starting from early boot (i.e. crng init is already done):

[root@qualcomm-amberwing]# dmesg | grep -i random
random: crng init done

2. The reason is that upstream aarch64 kernel uses the timer counter
value to generate random numbers starting from early boot (which is
probable not a good alternative when we have a compatible EFI firmware
which can pass entropy to the kernel):

'include/linux/timex.h' :
---------------------------

#define random_get_entropy()    get_cycles()

'arch/arm64/include/asm/timex.h' :
-------------------------------------------

/*
 * Use the current timer as a cycle counter since this is what we use for
 * the delay loop.
 */
#define get_cycles()    arch_timer_read_counter()

'drivers/clocksource/arm_arch_timer.c' :
--------------------------------------------------

u64 (*arch_timer_read_counter)(void) = arch_counter_get_cntvct;

3. And when other linux kernel modules (or even userspace
applications) try to do some random number generation using the kernel
support using 'getrandom' / 'get_random_bytes', the entropy is already
available.

So the caller would be supplied with random numbers, as I confirmed on
arm64 platforms which do not support EFI_RNG_PROTOCOL:

Also on such platforms 'wait_for_random_bytes' returns 0 indicating
that the 'urandom' pool has been seeded:

/*
 * Wait for the urandom pool to be seeded and thus guaranteed to supply
 * cryptographically secure random numbers. This applies to: the /dev/urandom
 * device, the get_random_bytes function, and the get_random_{u32,u64,int,long}
 * family of functions. Using any of these functions without first calling
 * this function forfeits the guarantee of security.
 *
 * Returns: 0 if the urandom pool has been seeded.
 *          -ERESTARTSYS if the function was interrupted by a signal.
 */
int wait_for_random_bytes(void)

4. Accordingly, I think the arm64 timer count is probably not a good
entropy source on platforms which indeed support EFI_RNG_PROTOCOL and
we should  be looking to extend 'arch_get_random_*' or
'random_get_entropy' for arm64, to provide seed/entropy using APIs
like 'efi_random_get_seed'?

How reproducible:

Attachment contains an example of a loadable kernel module which can be used to generate a random number using get_random_bytes() API. It also uses 'wait_for_random_bytes' to make sure that the urandom pool is already seeded and thus guaranteed to supply cryptographically secure random numbers

Steps to Reproduce:

1. Compile the loadable module:
# cd get_random_module
# make clean; make

2. Insert the loadable module:
# insmod mod_get_random_bytes.ko

3. Verify that you see the message 'wait_for_random_bytes returned ret=0' and the random number generated is unique everytime the module is loaded.

Additional info:

Please see the upstream discussion I am having with arm maintainers on the same here: <https://marc.info/?l=kexec&m=152373738806134&w=2>