Skip to content

Commit 51d6ca3

Browse files
t-8chKAGA-KOKO
authored andcommitted
vdso: Add generic random data storage
Extend the generic vDSO data storage with a page for the random state data. The random state data is stored in a dedicated page, as the existing storage page is only meant for time-related, time-namespace-aware data. This simplifies to access logic to not need to handle time namespaces anymore and also frees up more space in the time-related page. In case further generic vDSO data store is required it can be added to the random state page. Signed-off-by: Thomas Weißschuh <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Link: https://lore.kernel.org/all/[email protected]
1 parent df7fcbe commit 51d6ca3

File tree

5 files changed

+45
-5
lines changed

5 files changed

+45
-5
lines changed

drivers/char/random.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ static void crng_reseed(struct work_struct *work)
278278
WRITE_ONCE(base_crng.generation, next_gen);
279279
#ifdef CONFIG_VDSO_GETRANDOM
280280
/* base_crng.generation's invalid value is ULONG_MAX, while
281-
* _vdso_rng_data.generation's invalid value is 0, so add one to the
281+
* vdso_k_rng_data->generation's invalid value is 0, so add one to the
282282
* former to arrive at the latter. Use smp_store_release so that this
283283
* is ordered with the write above to base_crng.generation. Pairs with
284284
* the smp_rmb() before the syscall in the vDSO code.
@@ -290,7 +290,7 @@ static void crng_reseed(struct work_struct *work)
290290
* because the vDSO side only checks whether the value changed, without
291291
* actually using or interpreting the value.
292292
*/
293-
smp_store_release((unsigned long *)&__arch_get_k_vdso_rng_data()->generation, next_gen + 1);
293+
smp_store_release((unsigned long *)&vdso_k_rng_data->generation, next_gen + 1);
294294
#endif
295295
if (!static_branch_likely(&crng_is_ready))
296296
crng_init = CRNG_READY;
@@ -743,7 +743,7 @@ static void __cold _credit_init_bits(size_t bits)
743743
queue_work(system_unbound_wq, &set_ready);
744744
atomic_notifier_call_chain(&random_ready_notifier, 0, NULL);
745745
#ifdef CONFIG_VDSO_GETRANDOM
746-
WRITE_ONCE(__arch_get_k_vdso_rng_data()->is_ready, true);
746+
WRITE_ONCE(vdso_k_rng_data->is_ready, true);
747747
#endif
748748
wake_up_interruptible(&crng_init_wait);
749749
kill_fasync(&fasync, SIGIO, POLL_IN);

include/asm-generic/vdso/vsyscall.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,13 @@ static __always_inline const struct vdso_time_data *__arch_get_vdso_u_time_data(
1313
}
1414
#endif
1515

16+
#ifndef __arch_get_vdso_u_rng_data
17+
static __always_inline const struct vdso_rng_data *__arch_get_vdso_u_rng_data(void)
18+
{
19+
return &vdso_u_rng_data;
20+
}
21+
#endif
22+
1623
#else /* !CONFIG_GENERIC_VDSO_DATA_STORE */
1724

1825
#ifndef __arch_get_k_vdso_data
@@ -25,6 +32,11 @@ static __always_inline struct vdso_data *__arch_get_k_vdso_data(void)
2532

2633
#define __arch_get_vdso_u_time_data __arch_get_vdso_data
2734

35+
#ifndef __arch_get_vdso_u_rng_data
36+
#define __arch_get_vdso_u_rng_data() __arch_get_vdso_rng_data()
37+
#endif
38+
#define vdso_k_rng_data __arch_get_k_vdso_rng_data()
39+
2840
#endif /* CONFIG_GENERIC_VDSO_DATA_STORE */
2941

3042
#ifndef __arch_update_vsyscall

include/vdso/datapage.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,10 @@ extern struct vdso_time_data _timens_data[CS_BASES] __attribute__((visibility("h
144144
extern struct vdso_rng_data _vdso_rng_data __attribute__((visibility("hidden")));
145145
#else
146146
extern struct vdso_time_data vdso_u_time_data[CS_BASES] __attribute__((visibility("hidden")));
147+
extern struct vdso_rng_data vdso_u_rng_data __attribute__((visibility("hidden")));
147148

148149
extern struct vdso_time_data *vdso_k_time_data;
150+
extern struct vdso_rng_data *vdso_k_rng_data;
149151
#endif
150152

151153
/**
@@ -161,6 +163,7 @@ union vdso_data_store {
161163
enum vdso_pages {
162164
VDSO_TIME_PAGE_OFFSET,
163165
VDSO_TIMENS_PAGE_OFFSET,
166+
VDSO_RNG_PAGE_OFFSET,
164167
VDSO_NR_PAGES
165168
};
166169

@@ -184,9 +187,16 @@ enum vdso_pages {
184187

185188
#else /* !__ASSEMBLY__ */
186189

190+
#ifdef CONFIG_VDSO_GETRANDOM
191+
#define __vdso_u_rng_data PROVIDE(vdso_u_rng_data = vdso_u_data + 2 * PAGE_SIZE);
192+
#else
193+
#define __vdso_u_rng_data
194+
#endif
195+
187196
#define VDSO_VVAR_SYMS \
188197
PROVIDE(vdso_u_data = . - __VDSO_PAGES * PAGE_SIZE); \
189198
PROVIDE(vdso_u_time_data = vdso_u_data); \
199+
__vdso_u_rng_data \
190200

191201

192202
#endif /* !__ASSEMBLY__ */

lib/vdso/datastore.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ struct vdso_time_data *vdso_k_time_data = vdso_time_data_store.data;
1717
static_assert(sizeof(vdso_time_data_store) == PAGE_SIZE);
1818
#endif /* CONFIG_HAVE_GENERIC_VDSO */
1919

20+
#ifdef CONFIG_VDSO_GETRANDOM
21+
static union {
22+
struct vdso_rng_data data;
23+
u8 page[PAGE_SIZE];
24+
} vdso_rng_data_store __page_aligned_data;
25+
struct vdso_rng_data *vdso_k_rng_data = &vdso_rng_data_store.data;
26+
static_assert(sizeof(vdso_rng_data_store) == PAGE_SIZE);
27+
#endif /* CONFIG_VDSO_GETRANDOM */
28+
2029
static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
2130
struct vm_area_struct *vma, struct vm_fault *vmf)
2231
{
@@ -53,6 +62,11 @@ static vm_fault_t vvar_fault(const struct vm_special_mapping *sm,
5362
return VM_FAULT_SIGBUS;
5463
pfn = __phys_to_pfn(__pa_symbol(vdso_k_time_data));
5564
break;
65+
case VDSO_RNG_PAGE_OFFSET:
66+
if (!IS_ENABLED(CONFIG_VDSO_GETRANDOM))
67+
return VM_FAULT_SIGBUS;
68+
pfn = __phys_to_pfn(__pa_symbol(vdso_k_rng_data));
69+
break;
5670
default:
5771
return VM_FAULT_SIGBUS;
5872
}

lib/vdso/getrandom.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <uapi/linux/mman.h>
1313
#include <uapi/linux/random.h>
1414

15+
/* Bring in default accessors */
16+
#include <vdso/vsyscall.h>
17+
1518
#undef PAGE_SIZE
1619
#undef PAGE_MASK
1720
#define PAGE_SIZE (1UL << CONFIG_PAGE_SHIFT)
@@ -152,7 +155,7 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
152155

153156
/*
154157
* Prevent the syscall from being reordered wrt current_generation. Pairs with the
155-
* smp_store_release(&_vdso_rng_data.generation) in random.c.
158+
* smp_store_release(&vdso_k_rng_data->generation) in random.c.
156159
*/
157160
smp_rmb();
158161

@@ -256,5 +259,6 @@ __cvdso_getrandom_data(const struct vdso_rng_data *rng_info, void *buffer, size_
256259
static __always_inline ssize_t
257260
__cvdso_getrandom(void *buffer, size_t len, unsigned int flags, void *opaque_state, size_t opaque_len)
258261
{
259-
return __cvdso_getrandom_data(__arch_get_vdso_rng_data(), buffer, len, flags, opaque_state, opaque_len);
262+
return __cvdso_getrandom_data(__arch_get_vdso_u_rng_data(), buffer, len, flags,
263+
opaque_state, opaque_len);
260264
}

0 commit comments

Comments
 (0)