summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/char/random.c9
-rw-r--r--lib/vdso/getrandom.c2
2 files changed, 9 insertions, 2 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 87fe61295ea1..c12f906e05d6 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -281,8 +281,15 @@ static void crng_reseed(struct work_struct *work)
* former to arrive at the latter. Use smp_store_release so that this
* is ordered with the write above to base_crng.generation. Pairs with
* the smp_rmb() before the syscall in the vDSO code.
+ *
+ * Cast to unsigned long for 32-bit architectures, since atomic 64-bit
+ * operations are not supported on those architectures. This is safe
+ * because base_crng.generation is a 32-bit value. On big-endian
+ * architectures it will be stored in the upper 32 bits, but that's okay
+ * because the vDSO side only checks whether the value changed, without
+ * actually using or interpreting the value.
*/
- smp_store_release(&_vdso_rng_data.generation, next_gen + 1);
+ smp_store_release((unsigned long *)&_vdso_rng_data.generation, next_gen + 1);
#endif
if (!static_branch_likely(&crng_is_ready))
crng_init = CRNG_READY;
diff --git a/lib/vdso/getrandom.c b/lib/vdso/getrandom.c
index e1db228bc4f0..bacf19dbb6a1 100644
--- a/lib/vdso/getrandom.c
+++ b/lib/vdso/getrandom.c
@@ -68,8 +68,8 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
struct vgetrandom_state *state = opaque_state;
size_t batch_len, nblocks, orig_len = len;
bool in_use, have_retried = false;
- unsigned long current_generation;
void *orig_buffer = buffer;
+ u64 current_generation;
u32 counter[2] = { 0 };
if (unlikely(opaque_len == ~0UL && !buffer && !len && !flags)) {